Concept · multi-tenancy

Multi-tenancy — keyed by a token, hardened at every path.

OpenClawMU's tenant isolation is the load-bearing change vs. upstream. Here's exactly how it works, what's isolated, and what isn't.

What is a tenant?

A tenant is a namespace inside a single OpenClawMU gateway. It owns a directory on disk, a SHA-256-hashed token, a quota budget, a set of channel pairings, and an optional config overlay that can override anything except admin-only keys.

From the operator's perspective, a tenant is the unit you bill, snapshot, rotate credentials for, or delete. From an end-user's perspective, a tenant is just "the AI assistant they talk to" — they never see the multi-tenant machinery.

What's isolated per tenant

  • Session store — chat history, conversation state, tool-use traces.
  • Memory — sqlite-vec embeddings + content store.
  • Plugins / skills — installed extensions from ClawHub or local paths.
  • Sandboxes — per-tenant bubblewrap or Docker roots.
  • Cron jobs — scheduled tasks owned by this tenant.
  • Channel credentials — WhatsApp pairing, Telegram bot token, Slack OAuth, etc.
  • Devices & nodes — paired clients for distributed setups.
  • Config overlay — tenant-level overrides (model choice, max tokens, allowed tools).

What's shared across tenants

  • The Node process — one gateway, one event loop. Tenants share CPU.
  • LLM clients — stateless adapter classes; calls are tagged with tenant ID.
  • The dispatcher — the function that routes JSON-RPC method names to handlers.
  • Gateway config — admin keys, rate-card, S3 bucket configuration.

The token model

Tenant tokens are generated by the gateway when you run tenants create. The plaintext token is shown once in the CLI output — you copy it into your client app or your CI secret store. The gateway stores only the SHA-256 hash. There is no recovery path if you lose the token; tenants token rotate is the correct response.

Verification on every inbound request:

  1. Extract the Bearer token from the Authorization header.
  2. Compute its SHA-256 hash.
  3. Look up the hash in the keystore.
  4. Constant-time compare with crypto.timingSafeEqual.
  5. If match: resolve the tenant ID and attach it to the request context. If not: 401, no detail leaked.

Admin-only key protection

Tenants can override their own config via a YAML overlay — model choice, max tokens, system prompt, allowed tools. But certain keys are admin-only: API credentials for downstream LLMs, the rate card, S3 bucket credentials, gateway-wide feature flags. Tenant overlays that try to override these keys are rejected at load time with a clear error.

~/.openclaw/tenants/acme/config.yaml
# Allowed overrides — tenant scope
model: claude-opus-4-7
max_tokens: 8192
system_prompt: |
  You are the Acme Corp AI assistant.
  Be concise. Cite sources.
allowed_tools:
  - bash
  - web_search
  - file_read

# Forbidden — these would fail load (admin-only keys)
# anthropic_api_key: ...   # ✗ rejected
# rate_card: ...           # ✗ rejected
# s3_credentials: ...      # ✗ rejected

Path-traversal protection

Every method that takes a path string normalizes the path with path.resolve and asserts that the resolved path starts with the tenant's root directory. Inputs containing .., absolute paths, or symlinks that escape the root are rejected. This applies to: plugin loaders, file_read / file_write tools, sandbox mount specs, backup target paths, restore source paths, and config overlay file paths.

The 59 tenant-scoped methods

The dispatcher allow-lists 59 JSON-RPC methods that a tenant token can invoke. Categories:

  • tenants.* — self-info, token-rotate (own scope only).
  • terminal.* — spawn, write, resize, close.
  • config.* — read & write the tenant config overlay.
  • agents.* — create runs, stream outputs, cancel.
  • sessions.* — create, list, get, delete.
  • cron.* — add, list, remove, run-now.
  • skills.* — install from ClawHub, list, uninstall.
  • channels.* — pair WhatsApp/Telegram/Slack/etc., list, unpair.
  • voice.* — wake-word config, transcript history.
  • devices.* / nodes.* — pair external clients.
  • health — gateway and per-tenant liveness.

Methods outside this allow-list (e.g. tenants.create, tenants.delete, billing rate-card management) require the admin key — they never accept a tenant token.

EXFOLIATE!

Run your own gateway today.

Apache-2.0, self-hosted, no SaaS layer between you and your users. Install the CLI, create your first tenant, mint a token — you're routing traffic in 60 seconds.