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 accountId is 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 raise maxAgents temporarily; 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:

  1. 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
  2. A new workspace is created under the workspaceTemplate path
  3. The agent is registered and a binding is created for this user
  4. On first access, the workspace helper generates any missing bootstrap files (AGENTS.md, SOUL.md, USER.md, and so on)
  5. Every later message from this user is routed to their dedicated agent

Configuration options

SettingDescriptionDefault
channels.feishu.dynamicAgentCreation.enabledEnable automatic per-user agent creationfalse
channels.feishu.dynamicAgentCreation.workspaceTemplatePath template for dynamic agent workspaces~/.openclaw/workspace-{agentId}
channels.feishu.dynamicAgentCreation.agentDirTemplateAgent directory name template~/.openclaw/agents/{agentId}/agent
channels.feishu.dynamicAgentCreation.maxAgentsMaximum number of dynamic agents to createunlimited

Template variables:

  • {agentId} - the generated agent ID (e.g., feishu-ou_xxxxxx or feishu-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.

ValueBehaviorBest for
"main"Each user's DM maps to their agent's main sessionSingle-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 sessionPublic multi-user bots needing stronger isolation
"per-account-channel-peer"Each (account + channel + user) combination gets a separate sessionMulti-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.configWrites is false (default: enabled).
  • bindings should be empty: Dynamic agents register their own bindings automatically
  • Upgrade path: Manual bindings you already have keep working alongside dynamic agents
  • session.dmScope is global: All channels are affected, not only Feishu
818 words · updated Oct 26, 2026