Multi-user
LogLife supports multiple users on a single OpenClaw instance. Each user gets their own agent, which means fully isolated conversation history, long-term memory, API keys, model selection, and usage tracking. All of this is achieved through configuration — no OpenClaw source modifications are needed.How it works
The multi-user system maps each user to their own OpenClaw agent. When a message arrives, the gateway uses bindings to route it to the correct agent based on the sender’s channel and peer ID. Allow-lists control who can message the bot on each channel.What each user gets
Generated configuration
The multi-user system produces agenerated.json file that contains:
agents.list— one agent definition per user (ID, name, model, skills)bindings— routing rules mapping{channel, peerId}to an agentchannels— per-channel allow-lists and DM policiessession— session scoping settingsenv— shared environment variables (API keys used by all users)
openclaw.json after register/unregister operations. This avoids relying on $include during hot reload.
Session scoping
The default session scope ismain, which gives each agent one continuous conversation regardless of which channel the user messages from. This is the correct setting for journaling — your journal is your journal, whether you write from WhatsApp or Telegram.
Other OpenClaw session scopes are available but less useful with the multi-user layer:
Since each agent only has one user, the agent boundary already provides complete isolation between users. The
dmScope setting only affects behavior within each agent.
Runtime user registration
New users are added at runtime through the/loglife/register endpoint. The registration flow:
- The plugin reads
users.json(the source of truth for all users) - Appends the new user with their phone number as an identifier
- Calls
generateConfig()to rebuildgenerated.json - Merges generated
agents,bindings,channels, andsessionintoopenclaw.json - Writes
openclaw.json(no restart required)
Runtime user removal
Users can be removed at runtime through/loglife/unregister:
- The plugin reads
users.json - Removes the matching user by phone identifier
- Rebuilds
generated.json - Merges the updated generated config into
openclaw.json - Cleans stale allow-list fields when a channel no longer has managed users
The full rebuild approach regenerates
generated.json from scratch on every registration. This is fast enough for the foreseeable scale — under 50ms at 1,000 users, about 1-2 seconds at 100,000 users.Memory isolation
OpenClaw has six layers of persistent state. Five of them are fully isolated per agent (and therefore per user):
The only shared layer is debug logs, which are operational data that no agent reads to inform its responses. For anything that affects what the bot says, remembers, or knows, the isolation is complete.
Per-user API keys
By default, all users share API keys configured inshared.env within users.json. When a user needs their own keys (for separate billing, rate limits, or scoped services), their env field in users.json is populated and writeAuthProfiles() writes per-agent credentials to ~/.openclaw/agents/<agentId>/agent/auth-profiles.json.
API keys can be stored as 1Password references (op:// URIs) instead of raw values. These are resolved at config generation time via the op read CLI.
File structure
The multi-user code lives inside the plugin atplugin/multi-user/: