OpenClawSkills
GitHub
核心概念 • TutorialHeader.readTime

多代理路由

Multi-Agent Routing: Isolated agents, channel accounts, bindings.

Goal: multiple _isolated_ agents (separate workspace + ''agentDir'' + sessions), plus multiple channel accounts (e.g. two WhatsApps) in one running Gateway. Inbound is routed to an agent via bindings.

Tutorial.step

What is "one agent"?

An agent is a fully scoped brain with its own:

- Workspace (files, AGENTS.md/SOUL.md/USER.md, local notes, persona rules).

- ''State directory'' (''agentDir'') for auth profiles, model registry, and per-agent config.

- ''Session store'' (chat history + routing state) under ''~/.openclaw/agents/<agentId>/sessions''.

Auth profiles are per-agent. Each agent reads from its own:

Terminal
~/.openclaw/agents/<agentId>/agent/auth-profiles.json

主要代理的认证信息是''自动的在分钟享不会被''。代理間在 ''agentDir''

copy ''auth-profiles.json'' into the other agent's ''agentDir''.

''skills/'' 他的代理的 ''~/.openclaw/skills'' 在复制执行。

The Gateway can host one agent (default) or many agents side-by-side.

''Workspace note:'' each agent's workspace is the ''default cwd'', not a hard sandbox. Relative paths resolve inside the workspace, but absolute paths can reach other host locations unless sandboxing is enabled. See ''Sandboxing''.

The Gateway can host **one agent** (default) or **many agents** side-by-side.

**Workspace note:** each agent's workspace is the **default cwd**, not a hard

沙盒不是。相对路径是工作区内在解决被但、绝对路径是

reach other host locations unless sandboxing is enabled. See

''沙盒''请参阅。

Tutorial.step

Paths (quick map)

- 设置:''~/.openclaw/openclaw.json''(或 ''OPENCLAW_CONFIG_PATH'')

- 状态目录:''~/.openclaw''(或 ''OPENCLAW_STATE_DIR'')

- 工作区:''~/.openclaw/workspace''(或 ''~/.openclaw/workspace-<agentId>'')

- 代理目录:''~/.openclaw/agents/<agentId>/agent''(或 ''agents.list[].agentDir'')

- 会话:''~/.openclaw/agents/<agentId>/sessions''

#

Tutorial.step

Single-agent mode (default)

何也不执行場合、OpenClaw 是 1 次的代理运行执行:

- ''agentId'' defaults to ''''main''''.

- Sessions are keyed as ''agent:main:<mainKey>''.

- Workspace defaults to ''~/.openclaw/workspace'' (or ''~/.openclaw/workspace-<profile>'' when ''OPENCLAW_PROFILE'' is set).

Tutorial.step

代理向导

使用代理向导添加新的隔离代理:

Bash
openclaw agents add work

Then add ''bindings'' (or let the wizard do it) to route inbound messages.

確認:

Bash
openclaw agents list --bindings
Tutorial.step

多个代理 = 多个人,多种个性

With ''multiple agents'', each ''agentId'' becomes a ''fully isolated persona'':

- ''Different phone numbers/accounts'' (per channel ''accountId'').

- ''Different personalities'' (per-agent workspace files like ''AGENTS.md'' and ''SOUL.md'').

- Separate auth + sessions (no cross-talk unless explicitly enabled).

This lets multiple people share one Gateway server while keeping their AI "brains" and data isolated.

Tutorial.step

1 次的 WhatsApp 编号、复数的人(DM 分钟割)

You can route ''different WhatsApp DMs'' to different agents while staying on ''one WhatsApp account''. Match on sender E.164 (like ''+15551234567'') with ''peer.kind: "dm"''. Replies still come from the same WhatsApp number (no per-agent sender identity).

Important detail: direct chats collapse to the agent's main session key, so true isolation requires one agent per person.

例:

Json5
{
  agents: {
    list: [
      { id: "alex", workspace: "~/.openclaw/workspace-alex" },
      { id: "mia", workspace: "~/.openclaw/workspace-mia" },
    ],
  },
  bindings: [
    { agentId: "alex", match: { channel: "whatsapp", peer: { kind: "dm", id: "+15551230001" } } },
    { agentId: "mia", match: { channel: "whatsapp", peer: { kind: "dm", id: "+15551230002" } } },
  ],
  channels: {
    whatsapp: {
      dmPolicy: "allowlist",
      allowFrom: ["+15551230001", "+15551230002"],
    },
  },
}

注意事項:

- DM access control is per WhatsApp account (pairing/allowlist), not per agent.

- For shared groups, either bind the group to one agent or use ''Broadcast groups''.

Tutorial.step

Routing rules (how messages pick an agent)

Bindings are deterministic and most-specific wins:

1. ''peer'' 一致(正確那 DM/群组/渠道 ID)

2. ''guildId''(Discord)

3. ''teamId''(Slack)

4. ''accountId'' 但渠道和一致

5. 渠道级别的一致 (''accountId: "*"'')

Tutorial.step

复数的账户/电话号码

Channels that support ''multiple accounts'' (e.g. WhatsApp) use ''accountId'' to identify each login. Each ''accountId'' can be routed to a different agent, so one server can host multiple phone numbers without mixing sessions.

Each `accountId` can be routed to a different agent, so one server can

host multiple phone numbers without mixing sessions.

Tutorial.step

概念

- ''agentId'':「脳」(工作区、代理每个认证、代理每个会话存储)。

- ''accountId'':渠道账户实示例(示示例:WhatsApp 账户 ''"personal"'' vs ''"biz"'')。

- ''binding'': routes inbound messages to an ''agentId'' via ''(channel, accountId, peer)'' and optionally guild/team ids.

- 直接聊天是 ''agent:<agentId>:<mainKey>'' 在崩壊执行(代理每个「主要」;''session.mainKey'')。

Tutorial.step

示示例:2 次的 WhatsApp → 2 次的代理

''~/.openclaw/openclaw.json'' (JSON5):

Js
{
  agents: {
    list: [
      {
        id: "home",
        default: true,
        name: "Home",
        workspace: "~/.openclaw/workspace-home",
        agentDir: "~/.openclaw/agents/home/agent",
      },
      {
        id: "work",
        name: "Work",
        workspace: "~/.openclaw/workspace-work",
        agentDir: "~/.openclaw/agents/work/agent",
      },
    ],
  },

  // Deterministic routing: first match wins (most-specific first).
  bindings: [
    { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
    { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },

    // Optional per-peer override (example: send a specific group to work agent).
    {
      agentId: "work",
      match: {
        channel: "whatsapp",
        accountId: "personal",
        peer: { kind: "group", id: "[email protected]" },
      },
    },
  ],

  // Off by default: agent-to-agent messaging must be explicitly enabled + allowlisted.
  tools: {
    agentToAgent: {
      enabled: false,
      allow: ["home", "work"],
    },
  },

  channels: {
    whatsapp: {
      accounts: {
        personal: {
          // Optional override. Default: ~/.openclaw/credentials/whatsapp/personal
          // authDir: "~/.openclaw/credentials/whatsapp/personal",
        },
        biz: {
          // Optional override. Default: ~/.openclaw/credentials/whatsapp/biz
          // authDir: "~/.openclaw/credentials/whatsapp/biz",
        },
      },
    },
  },
}
Tutorial.step

Example: WhatsApp for daily chat + Telegram for deep work

渠道在分钟割:WhatsApp 高速那日常代理在、Telegram Opus 代理在路由执行。

Json5
{
  agents: {
    list: [
      {
        id: "chat",
        name: "Everyday",
        workspace: "~/.openclaw/workspace-chat",
        model: "anthropic/claude-sonnet-4-5",
      },
      {
        id: "opus",
        name: "Deep Work",
        workspace: "~/.openclaw/workspace-opus",
        model: "anthropic/claude-opus-4-5",
      },
    ],
  },
  bindings: [
    { agentId: "chat", match: { channel: "whatsapp" } },
    { agentId: "opus", match: { channel: "telegram" } },
  ],
}

注意事項:

- If you have multiple accounts for a channel, add accountId to the binding (e.g. '{ channel: "whatsapp", accountId: "personal" }').

- To route a single DM/group to Opus while keeping the rest on chat, add a ''match.peer'' binding for that peer; peer matches always win over channel-wide rules.

Tutorial.step

Example: same channel, one peer to Opus

Keep WhatsApp on the fast agent, but route one DM to Opus:

Json5
{
  agents: {
    list: [
      {
        id: "chat",
        name: "Everyday",
        workspace: "~/.openclaw/workspace-chat",
        model: "anthropic/claude-sonnet-4-5",
      },
      {
        id: "opus",
        name: "Deep Work",
        workspace: "~/.openclaw/workspace-opus",
        model: "anthropic/claude-opus-4-5",
      },
    ],
  },
  bindings: [
    { agentId: "opus", match: { channel: "whatsapp", peer: { kind: "dm", id: "+15551234567" } } },
    { agentId: "chat", match: { channel: "whatsapp" } },
  ],
}

对等绑定始终优先,因此请将它们放在通道范围的规则之上。

Tutorial.step

绑定到 WhatsApp 群组的家庭代理

将专用家庭代理绑定到单个 WhatsApp 群组,带有提及限制和更严格的工具策略:

注意事项:

Json5
{
  agents: {
    list: [
      {
        id: "family",
        name: "Family",
        workspace: "~/.openclaw/workspace-family",
        identity: { name: "Family Bot" },
        groupChat: {
          mentionPatterns: ["@family", "@familybot", "@Family Bot"],
        },
        sandbox: {
          mode: "all",
          scope: "agent",
        },
        tools: {
          allow: [
            "exec",
            "read",
            "sessions_list",
            "sessions_history",
            "sessions_send",
            "sessions_spawn",
            "session_status",
          ],
          deny: ["write", "edit", "apply_patch", "browser", "canvas", "nodes", "cron"],
        },
      },
    ],
  },
  bindings: [
    {
      agentId: "family",
      match: {
        channel: "whatsapp",
        peer: { kind: "group", id: "[email protected]" },
      },
    },
  ],
}

- Tool allow/deny lists are ''tools'', not skills. If a skill needs to run a binary, ensure ''exec'' is allowed and the binary exists in the sandbox.

- For stricter gating, set ''agents.list[].groupChat.mentionPatterns'' and keep group allowlists enabled for the channel.

Ensure binary exists, `exec` is allowed, and binary is present in sandbox.

- For stricter gates, set `agents.list[].groupChat.mentionPatterns` and

Tutorial.step

代理每个沙盒和工具设置

Starting with v2026.1.6, each agent can have its own sandbox and tool restrictions:

Js
{
  agents: {
    list: [
      {
        id: "personal",
        workspace: "~/.openclaw/workspace-personal",
        sandbox: {
          mode: "off",  // No sandbox for personal agent
        },
        // No tool restrictions - all tools available
      },
      {
        id: "family",
        workspace: "~/.openclaw/workspace-family",
        sandbox: {
          mode: "all",     // Always sandboxed
          scope: "agent",  // One container per agent
          docker: {
            // Optional one-time setup after container creation
            setupCommand: "apt-get update && apt-get install -y git curl",
          },
        },
        tools: {
          allow: ["read"],                    // Only read tool
          deny: ["exec", "write", "edit", "apply_patch"],    // Deny others
        },
      },
    ],
  },
}

Note: ''setupCommand'' lives under ''sandbox.docker'' and runs once on container creation.