Skip to main content
This page covers the internal architecture of the LogLife plugin — how users are isolated, how configuration is generated, and how the system scales.

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

CapabilityDescription
Separate conversation historyEach agent stores transcripts independently
Isolated long-term memoryEach agent has its own vector database (memory/<agentId>.sqlite)
Per-user API keysEach agent can have its own provider credentials
Per-user modelAlice can use Claude while Bob uses GPT-4o
Per-user skillsDifferent tools and capabilities per user
Usage trackingThe gateway’s byAgent API gives per-user breakdowns
Cross-channel identityMultiple identifiers (WhatsApp, Telegram) route to the same agent

Generated configuration

The multi-user system produces a generated.json file that is included in openclaw.json via the $include directive. This file contains:
  • agents.list — one agent definition per user (ID, name, model, skills)
  • bindings — routing rules mapping {channel, peerId} to an agent
  • channels — per-channel allow-lists and DM policies
  • session — session scoping settings
  • env — shared environment variables (API keys used by all users)

Session scoping

The default session scope is main, 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:
dmScopeBehavior with multi-user
mainOne session per agent. All channels unified. (default)
per-peerSeparate sessions per peer ID. Fragments cross-channel identity.
per-channel-peerSeparate sessions per channel. Most fragmented.
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:
  1. The plugin reads users.json (the source of truth for all users)
  2. Appends the new user with their phone number as an identifier
  3. Calls generateConfig() to rebuild generated.json
  4. Writes the updated config
  5. Touches openclaw.json to trigger a gateway hot-reload
The gateway picks up the new agent, binding, and allow-list entry immediately — no restart required.
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):
LayerLocationIsolated?
Conversation history~/.openclaw/agents/{agentId}/sessions/*.jsonlYes
Session metadata~/.openclaw/agents/{agentId}/sessions/sessions.jsonYes
Long-term memory~/.openclaw/memory/{agentId}.sqliteYes
Workspace files~/.openclaw/workspace-{agentId}/Yes
Auth profiles~/.openclaw/agents/{agentId}/agent/auth-profiles.jsonYes
Debug/trace logs~/.openclaw/logs/*.jsonlNo (shared, operational only)
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 in shared.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 at plugin/multi-user/:
FilePurpose
types.tsType definitions (UsersConfig, UserProfile, ParsedIdentifier)
identifiers.tsParses phone numbers and channel handles into {channel, peerId}
generate.tsProduces the OpenClaw config fragment from users.json
auth-setup.tsWrites per-user API keys to agent auth profiles
usage.tsMaps gateway usage data to user profiles
users.example.jsonTemplate for users.json