多 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.md、AGENTS.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
請參閱頻道指南:Discord、Telegram、WhatsApp。
步驟 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.md和SOUL.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)
綁定是確定性的,最具體的優先:
peer匹配(精確的私訊/群組/頻道 id)parentPeer匹配(子串繼承)guildId + roles(Discord 角色路由)guildId(Discord)teamId(Slack)- 頻道的
accountId匹配 - 頻道層級匹配(
accountId: "*") - 回退到預設 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(排序後)。
支援此模式的常見頻道包括:
whatsapp、telegram、discord、slack、signal、imessageirc、line、googlechat、mattermost、matrix、nextcloud-talkbluebubbles、zalo、zalouser、nostr、feishu
概念
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 瞭解詳細範例。