Feishu dynamic agents: per-user agent isolation explained
Learn how to enable dynamicAgentCreation so every Feishu DM user gets an isolated agent with their own workspace, bootstrap files, and private conversation history. Useful for public bots that need per-user assistants.
Read this when
- Running a public Feishu bot where each user needs a private assistant
- Configuring `dynamicAgentCreation` or `session.dmScope`
Per-user agent isolation: each person who sends a Feishu DM receives a dedicated workspace, their own bootstrap files, and separate conversation history.
Per-user agent isolation (Dynamic Agent Creation)
Turn on dynamicAgentCreation so that an isolated agent instance is created automatically for every DM user. Each person then gets:
- A workspace directory of their own
- Their own
USER.md/SOUL.md/MEMORY.md - Conversation history kept private
- Skills and state that are isolated
Public bots need this when every user should have a private AI assistant of their own.
Note
The normalized Feishu
accountIdis part of every dynamic binding, so both default and named accounts send each sender to the right dynamic agent.On an older release, a named account may have created an unscoped dynamic agent. That legacy agent still counts toward
maxAgents. Before you remove it, verify the default account does not use it, or raisemaxAgentstemporarily; OpenClaw cannot reliably determine which account owns ambiguous legacy state.
Quick setup
{
channels: {
feishu: {
dmPolicy: "open",
allowFrom: ["*"],
dynamicAgentCreation: {
enabled: true,
workspaceTemplate: "~/.openclaw/workspace-{agentId}",
agentDirTemplate: "~/.openclaw/agents/{agentId}/agent",
},
},
},
session: {
// Critical: makes each user's DM their "main session"
// Automatically loads USER.md / SOUL.md / MEMORY.md
// For stronger isolation, use "per-channel-peer" instead
dmScope: "main",
},
}
How it works
The first time a new user sends a DM:
- The channel derives a unique
agentId:feishu-{user_open_id}for the default account, or a bounded account-prefixed identity digest for a named account - A new workspace is created under the
workspaceTemplatepath - The agent is registered and a binding is created for this user
- On first access, the workspace helper generates any missing bootstrap files (
AGENTS.md,SOUL.md,USER.md, and so on) - Every later message from this user is routed to their dedicated agent
Configuration options
| Setting | Description | Default |
|---|---|---|
channels.feishu.dynamicAgentCreation.enabled | Enable automatic per-user agent creation | false |
channels.feishu.dynamicAgentCreation.workspaceTemplate | Path template for dynamic agent workspaces | ~/.openclaw/workspace-{agentId} |
channels.feishu.dynamicAgentCreation.agentDirTemplate | Agent directory name template | ~/.openclaw/agents/{agentId}/agent |
channels.feishu.dynamicAgentCreation.maxAgents | Maximum number of dynamic agents to create | unlimited |
Template variables:
{agentId}- the generated agent ID (e.g.,feishu-ou_xxxxxxorfeishu-support-<identity_digest>){userId}- the sender's Feishu open_id (e.g.,ou_xxxxxx)
Session scope
How direct messages map to agent sessions is governed by session.dmScope. Because this is a global setting, every channel is affected.
| Value | Behavior | Best for |
|---|---|---|
"main" | Each user's DM maps to their agent's main session | Single-user bots where you want USER.md / SOUL.md to auto-load |
"per-peer" | Each peer gets a separate session (regardless of channel) | Isolation keyed by sender identity only |
"per-channel-peer" | Each (channel + user) combination gets a separate session | Public multi-user bots needing stronger isolation |
"per-account-channel-peer" | Each (account + channel + user) combination gets a separate session | Multi-account bots needing account-level session isolation |
Tradeoff: With "main", bootstrap files load automatically (USER.md, SOUL.md, MEMORY.md), but every DM on every channel then shares one session key pattern. If you run a public multi-user bot where isolation matters more than automatic bootstrap loading, pick "per-channel-peer" and handle bootstrap files yourself.
Note
Choose
"per-account-channel-peer"when the same sender should keep separate sessions across named Feishu accounts. Account scope is preserved by dynamic bindings.
Typical multi-user deployment
{
channels: {
feishu: {
appId: "cli_xxx",
appSecret: "xxx",
dmPolicy: "open",
allowFrom: ["*"],
groupPolicy: "open",
requireMention: true,
dynamicAgentCreation: {
enabled: true,
workspaceTemplate: "~/.openclaw/workspace-{agentId}",
agentDirTemplate: "~/.openclaw/agents/{agentId}/agent",
},
},
},
session: {
// Choose dmScope based on your isolation needs:
// "main" for bootstrap auto-loading, "per-channel-peer" for stronger isolation
dmScope: "main",
},
bindings: [], // Empty - dynamic agents auto-bind
}
Verification
To verify that dynamic creation works, inspect the gateway logs:
feishu: creating dynamic agent "feishu-ou_xxxxxx" for user ou_xxxxxx
workspace: /home/user/.openclaw/workspace-feishu-ou_xxxxxx
agentDir: /home/user/.openclaw/agents/feishu-ou_xxxxxx/agent
To list every workspace that was created:
ls -la ~/.openclaw/workspace-*
Notes
- Workspace isolation: Every user gets an agent instance and workspace directory of their own. In the normal messaging flow, one user cannot see another user's files or conversation history.
- Security boundary: What this provides is isolation of messaging context, not a security boundary against hostile co-tenants. The agent process and the host environment are shared.
- Config writes must stay enabled: Creating a dynamic agent writes agents and bindings into the config, and this step is skipped when
channels.feishu.configWritesisfalse(default: enabled). bindingsshould be empty: Dynamic agents register their own bindings automatically- Upgrade path: Manual bindings you already have keep working alongside dynamic agents
session.dmScopeis global: All channels are affected, not only Feishu