多 Agent 路由

目標:在同一個運行中的 Gateway 裡擁有多個_隔離_的 agent(獨立的工作區 + agentDir + sessions),加上多個頻道帳號(例如兩個 WhatsApp)。入站訊息透過綁定路由到指定的 agent。

什麼是「一個 agent」?

一個 agent 是一個有完整範疇的大腦,擁有自己的:

  • 工作區(檔案、AGENTS.md/SOUL.md/USER.md、本地筆記、人格規則)。
  • 狀態目錄agentDir):驗證設定檔、模型登錄檔和 per-agent 設定。
  • Session 儲存區(聊天歷史 + 路由狀態),位於 ~/.openclaw/agents/<agentId>/sessions

驗證設定檔是 per-agent 的。每個 agent 讀取自己的:

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

主要 agent 的認證不會自動共享。絕對不要跨 agent 重用 agentDir(會造成認證/session 衝突)。如果想共享認證,把 auth-profiles.json 複製到另一個 agent 的 agentDir

Skills 透過每個工作區的 skills/ 資料夾實現 per-agent,共享 skills 從 ~/.openclaw/skills 取得。請參閱 Skills: per-agent vs shared

Gateway 可以託管一個 agent(預設)或多個 agent 並行。

工作區備註: 每個 agent 的工作區是預設工作目錄,不是嚴格的沙盒。相對路徑解析在工作區內,但絕對路徑可以存取主機上的其他位置,除非啟用沙盒。請參閱 Sandboxing

路徑(快速對照)

  • 設定:~/.openclaw/openclaw.json(或 OPENCLAW_CONFIG_PATH
  • 狀態目錄:~/.openclaw(或 OPENCLAW_STATE_DIR
  • 工作區:~/.openclaw/workspace(或 ~/.openclaw/workspace-<agentId>
  • Agent 目錄:~/.openclaw/agents/<agentId>/agent(或 agents.list[].agentDir
  • Sessions:~/.openclaw/agents/<agentId>/sessions

單 agent 模式(預設)

不做任何設定的話,OpenClaw 執行單一 agent:

  • agentId 預設為 main
  • Sessions 的 key 為 agent:main:<mainKey>
  • 工作區預設 ~/.openclaw/workspace(設定 OPENCLAW_PROFILE 時為 ~/.openclaw/workspace-<profile>)。
  • 狀態預設 ~/.openclaw/agents/main/agent

Agent 輔助工具

使用 agent 精靈新增一個隔離的 agent:

openclaw agents add work

然後新增 bindings(或讓精靈處理)來路由入站訊息。

驗證方式:

openclaw agents list --bindings

快速開始

步驟 1:建立每個 agent 的工作區

使用精靈或手動建立工作區:

openclaw agents add coding
openclaw agents add social

每個 agent 會有自己的工作區,含 SOUL.mdAGENTS.md 和可選的 USER.md,加上專屬的 agentDir 和位於 ~/.openclaw/agents/<agentId> 下的 session 儲存區。

步驟 2:建立頻道帳號

在你偏好的頻道上為每個 agent 建立一個帳號:

  • Discord:每個 agent 一個機器人,啟用 Message Content Intent,複製每個 token。
  • Telegram:每個 agent 透過 BotFather 建立一個機器人,複製每個 token。
  • WhatsApp:每個帳號綁定一個電話號碼。
openclaw channels login --channel whatsapp --account work

請參閱頻道指南:DiscordTelegramWhatsApp

步驟 3:新增 agent、帳號和綁定

agents.list 下新增 agent,在 channels.<channel>.accounts 下新增頻道帳號,用 bindings 把它們連起來(範例如下)。

步驟 4:重啟並驗證

openclaw gateway restart
openclaw agents list --bindings
openclaw channels status --probe

多 agent = 多人、多人格

有了多 agent,每個 agentId 都是一個完全隔離的人格

  • 不同的電話號碼/帳號(per-channel accountId)。
  • 不同的個性(per-agent 工作區檔案如 AGENTS.mdSOUL.md)。
  • 獨立的認證 + sessions(除非明確啟用,否則不會互相干擾)。

這讓多個人可以共用一台 Gateway 伺服器,同時保持各自的 AI「大腦」和資料隔離。

一個 WhatsApp 號碼,多個人(私訊分流)

你可以在一個 WhatsApp 帳號上將不同的私訊路由到不同的 agent。用發送者 E.164 格式(如 +15551234567)搭配 peer.kind: "direct" 進行匹配。回覆仍然來自同一個 WhatsApp 號碼(沒有 per-agent 的發送者身分)。

重要細節:私訊聊天會合併到 agent 的主要 session key,因此真正的隔離需要每人一個 agent

範例:

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

注意事項:

  • 私訊存取控制是全域 per-WhatsApp 帳號的(配對/允許清單),不是 per-agent。
  • 共享群組請綁定到一個 agent,或使用 Broadcast groups

路由規則(訊息如何選擇 agent)

綁定是確定性的最具體的優先

  1. peer 匹配(精確的私訊/群組/頻道 id)
  2. parentPeer 匹配(子串繼承)
  3. guildId + roles(Discord 角色路由)
  4. guildId(Discord)
  5. teamId(Slack)
  6. 頻道的 accountId 匹配
  7. 頻道層級匹配(accountId: "*"
  8. 回退到預設 agent(agents.list[].default,否則列表第一個,預設:main

如果同一層級有多個綁定匹配,設定順序中的第一個勝出。 如果一個綁定設定了多個匹配欄位(例如 peer + guildId),所有指定的欄位都必須滿足(AND 語意)。

重要的帳號範圍細節:

  • 省略 accountId 的綁定只匹配預設帳號。
  • accountId: "*" 做跨所有帳號的頻道層級回退。
  • 如果你之後為同一個 agent 新增帶有明確帳號 id 的相同綁定,OpenClaw 會升級現有的純頻道綁定為帶帳號的,而不是重複建立。

多帳號/多電話號碼

支援多帳號的頻道(如 WhatsApp)使用 accountId 識別每次登入。每個 accountId 可以路由到不同的 agent,讓一台伺服器可以託管多個電話號碼而不混淆 sessions。

如果你想在省略 accountId 時有頻道層級的預設帳號,設定 channels.<channel>.defaultAccount(可選)。未設定時,OpenClaw 回退到 default(如果存在),否則使用第一個設定的帳號 id(排序後)。

支援此模式的常見頻道包括:

  • whatsapptelegramdiscordslacksignalimessage
  • irclinegooglechatmattermostmatrixnextcloud-talk
  • bluebubbleszalozalousernostrfeishu

概念

  • agentId:一個「大腦」(工作區、per-agent 認證、per-agent session 儲存區)。
  • accountId:一個頻道帳號實例(如 WhatsApp 帳號 "personal" vs "biz")。
  • binding:透過 (channel, accountId, peer) 和可選的 guild/team id 將入站訊息路由到一個 agentId
  • 私訊聊天合併到 agent:<agentId>:<mainKey>(per-agent 的「main」;session.mainKey)。

平台範例

Discord 每個 agent 一個機器人

每個 Discord 機器人帳號對應一個唯一的 accountId。將每個帳號綁定到一個 agent,並為每個機器人設定允許清單。

{
  agents: {
    list: [
      { id: "main", workspace: "~/.openclaw/workspace-main" },
      { id: "coding", workspace: "~/.openclaw/workspace-coding" },
    ],
  },
  bindings: [
    { agentId: "main", match: { channel: "discord", accountId: "default" } },
    { agentId: "coding", match: { channel: "discord", accountId: "coding" } },
  ],
  channels: {
    discord: {
      groupPolicy: "allowlist",
      accounts: {
        default: {
          token: "DISCORD_BOT_TOKEN_MAIN",
          guilds: {
            "123456789012345678": {
              channels: {
                "222222222222222222": { allow: true, requireMention: false },
              },
            },
          },
        },
        coding: {
          token: "DISCORD_BOT_TOKEN_CODING",
          guilds: {
            "123456789012345678": {
              channels: {
                "333333333333333333": { allow: true, requireMention: false },
              },
            },
          },
        },
      },
    },
  },
}

注意事項:

  • 把每個機器人邀請到 guild 並啟用 Message Content Intent。
  • Token 放在 channels.discord.accounts.<id>.token(預設帳號可用 DISCORD_BOT_TOKEN)。

Telegram 每個 agent 一個機器人

{
  agents: {
    list: [
      { id: "main", workspace: "~/.openclaw/workspace-main" },
      { id: "alerts", workspace: "~/.openclaw/workspace-alerts" },
    ],
  },
  bindings: [
    { agentId: "main", match: { channel: "telegram", accountId: "default" } },
    { agentId: "alerts", match: { channel: "telegram", accountId: "alerts" } },
  ],
  channels: {
    telegram: {
      accounts: {
        default: {
          botToken: "123456:ABC...",
          dmPolicy: "pairing",
        },
        alerts: {
          botToken: "987654:XYZ...",
          dmPolicy: "allowlist",
          allowFrom: ["tg:123456789"],
        },
      },
    },
  },
}

注意事項:

  • 透過 BotFather 為每個 agent 建立一個機器人並複製 token。
  • Token 放在 channels.telegram.accounts.<id>.botToken(預設帳號可用 TELEGRAM_BOT_TOKEN)。

WhatsApp 每個 agent 一個號碼

啟動 gateway 之前先綁定每個帳號:

openclaw channels login --channel whatsapp --account personal
openclaw channels login --channel whatsapp --account biz

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

{
  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",
      },
    ],
  },

  // 確定性路由:第一個匹配的勝出(最具體的放前面)。
  bindings: [
    { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
    { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },

    // 可選的 per-peer 覆寫(範例:把特定群組送到 work agent)。
    {
      agentId: "work",
      match: {
        channel: "whatsapp",
        accountId: "personal",
        peer: { kind: "group", id: "[email protected]" },
      },
    },
  ],

  // 預設關閉:agent 間通訊必須明確啟用 + 設定允許清單。
  tools: {
    agentToAgent: {
      enabled: false,
      allow: ["home", "work"],
    },
  },

  channels: {
    whatsapp: {
      accounts: {
        personal: {
          // 可選覆寫。預設:~/.openclaw/credentials/whatsapp/personal
          // authDir: "~/.openclaw/credentials/whatsapp/personal",
        },
        biz: {
          // 可選覆寫。預設:~/.openclaw/credentials/whatsapp/biz
          // authDir: "~/.openclaw/credentials/whatsapp/biz",
        },
      },
    },
  },
}

範例:WhatsApp 日常聊天 + Telegram 深度工作

按頻道分流:WhatsApp 路由到快速的日常 agent,Telegram 路由到 Opus agent。

{
  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-6",
      },
    ],
  },
  bindings: [
    { agentId: "chat", match: { channel: "whatsapp" } },
    { agentId: "opus", match: { channel: "telegram" } },
  ],
}

注意事項:

  • 如果一個頻道有多個帳號,在綁定中加上 accountId(例如 { channel: "whatsapp", accountId: "personal" })。
  • 要把單一私訊/群組路由到 Opus 而其餘留在 chat,加一個帶 match.peer 的綁定;peer 匹配始終優先於頻道層級規則。

範例:同一頻道,一個 peer 到 Opus

WhatsApp 保持用快速 agent,但把一個私訊路由到 Opus:

{
  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-6",
      },
    ],
  },
  bindings: [
    {
      agentId: "opus",
      match: { channel: "whatsapp", peer: { kind: "direct", id: "+15551234567" } },
    },
    { agentId: "chat", match: { channel: "whatsapp" } },
  ],
}

Peer 綁定始終勝出,所以放在頻道層級規則之上。

家庭 agent 綁定到 WhatsApp 群組

把一個專屬的家庭 agent 綁定到單一 WhatsApp 群組,搭配 mention 閘門和更嚴格的工具原則:

{
  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]" },
      },
    },
  ],
}

注意事項:

  • 工具 allow/deny 清單指的是工具,不是 skills。如果某個 skill 需要執行二進位檔,確保 exec 被允許且二進位檔在沙盒中存在。
  • 要更嚴格的閘門,設定 agents.list[].groupChat.mentionPatterns 並保持頻道的群組允許清單啟用。

Per-Agent 沙盒與工具設定

從 v2026.1.6 開始,每個 agent 可以有自己的沙盒和工具限制:

{
  agents: {
    list: [
      {
        id: "personal",
        workspace: "~/.openclaw/workspace-personal",
        sandbox: {
          mode: "off",  // 個人 agent 不用沙盒
        },
        // 不限制工具——所有工具可用
      },
      {
        id: "family",
        workspace: "~/.openclaw/workspace-family",
        sandbox: {
          mode: "all",     // 始終使用沙盒
          scope: "agent",  // 每個 agent 一個容器
          docker: {
            // 可選的一次性設定,在容器建立後執行
            setupCommand: "apt-get update && apt-get install -y git curl",
          },
        },
        tools: {
          allow: ["read"],                    // 只允許 read 工具
          deny: ["exec", "write", "edit", "apply_patch"],    // 拒絕其他
        },
      },
    ],
  },
}

說明:setupCommand 放在 sandbox.docker 下,容器建立時只執行一次。 當解析後的 scope 是 "shared" 時,per-agent 的 sandbox.docker.* 覆寫會被忽略。

好處:

  • 安全隔離:限制不受信任 agent 的工具
  • 資源控制:沙盒特定 agent,同時讓其他 agent 在主機上執行
  • 靈活的原則:不同 agent 不同的權限

說明:tools.elevated全域且基於發送者的,不能 per-agent 設定。 如果需要 per-agent 的邊界,用 agents.list[].tools 拒絕 exec。 對於群組定向,用 agents.list[].groupChat.mentionPatterns 讓 @mention 清楚對應到目標 agent。

請參閱 Multi-Agent Sandbox & Tools 瞭解詳細範例。