Multi-Agent Routing
目的: 1つの実行中のGateway内で、複数の_分離された_エージェント(それぞれ別のworkspace +agentDir + sessions)と、複数のチャネルアカウント(例: 2つのWhatsApp)を扱うことです。受信メッセージはbindingsによってエージェントへルーティングされます。
「1つのエージェント」とは何か
agent とは、次のものをそれぞれ独自に持つ、完全にスコープ分離された頭脳です。- Workspace(ファイル、AGENTS.md/SOUL.md/USER.md、ローカルノート、personaルール)。
- 認証プロファイル、モデルレジストリ、エージェント単位の設定を格納する状態ディレクトリ(
agentDir)。 ~/.openclaw/agents/<agentId>/sessions配下のセッションストア(チャット履歴 + ルーティング状態)。
sessions_history はここでも、より安全なセッション横断の再想起経路です。これは生のトランスクリプトダンプではなく、境界づけられたサニタイズ済みビューを返します。assistantの再想起では、redaction/truncationの前に、thinkingタグ、<relevant-memories> の足場、プレーンテキストのtool-call XMLペイロード(<tool_call>...</tool_call>、<function_call>...</function_call>、<tool_calls>...</tool_calls>、<function_calls>...</function_calls>、切り詰められたtool-callブロックを含む)、格下げされたtool-callの足場、漏洩したASCII/全角のモデル制御トークン、不正なMiniMax tool-call XMLが取り除かれます。
メインエージェントの認証情報は自動では共有されません。エージェント間で agentDir を再利用してはいけません(認証/セッションの衝突を引き起こします)。認証情報を共有したい場合は、auth-profiles.json を別のエージェントの agentDir にコピーしてください。
Skillsは、各エージェントのworkspaceと ~/.openclaw/skills などの共有ルートから読み込まれ、設定されている場合は有効なエージェントskill allowlistでフィルタリングされます。共有のベースラインには agents.defaults.skills、エージェント単位の置き換えには agents.list[].skills を使います。詳しくは
Skills: per-agent vs shared と
Skills: agent skill allowlists を参照してください。
Gatewayは1つのagent(デフォルト)または複数のagentを並行してホストできます。
Workspaceに関する注意: 各エージェントのworkspaceは厳格なサンドボックスではなく、デフォルトのcwdです。相対パスはworkspace内で解決されますが、サンドボックスを有効にしていない限り、絶対パスはホスト上の他の場所へ到達できます。詳しくは
Sandboxing を参照してください。
パス(簡易マップ)
- Config:
~/.openclaw/openclaw.json(またはOPENCLAW_CONFIG_PATH) - 状態ディレクトリ:
~/.openclaw(またはOPENCLAW_STATE_DIR) - Workspace:
~/.openclaw/workspace(または~/.openclaw/workspace-<agentId>) - Agent dir:
~/.openclaw/agents/<agentId>/agent(またはagents.list[].agentDir) - Sessions:
~/.openclaw/agents/<agentId>/sessions
シングルエージェントモード(デフォルト)
何もしなければ、OpenClawは単一のagentとして動作します。agentIdのデフォルトはmainです。- Sessionsは
agent:main:<mainKey>としてキー付けされます。 - Workspaceのデフォルトは
~/.openclaw/workspaceです(OPENCLAW_PROFILEが設定されている場合は~/.openclaw/workspace-<profile>)。 - 状態のデフォルトは
~/.openclaw/agents/main/agentです。
Agent helper
agentウィザードを使って、新しい分離されたagentを追加します。bindings を追加します(またはウィザードに任せます)。
次で確認します。
クイックスタート
各agentのworkspaceを作成
ウィザードを使うか、手動でworkspaceを作成します。各agentには、
SOUL.md、AGENTS.md、オプションの USER.md を含む独自のworkspaceに加え、専用の agentDir と ~/.openclaw/agents/<agentId> 配下のセッションストアが作成されます。agents、accounts、bindingsを追加
agents.list にagentsを、channels.<channel>.accounts にチャネルアカウントを追加し、bindings でそれらを接続します(例は以下)。複数のagents = 複数の人、複数の人格
複数のagents を使うと、各agentId は完全に分離されたpersonaになります。
- 異なる電話番号/アカウント(チャネルごとの
accountId単位)。 - 異なる人格(
AGENTS.mdやSOUL.mdなどのエージェント単位workspaceファイル)。 - 分離された認証 + sessions(明示的に有効化しない限り相互干渉なし)。
エージェント間のQMD memory検索
あるagentから別のagentのQMDセッショントランスクリプトを検索したい場合は、agents.list[].memorySearch.qmd.extraCollections に追加コレクションを指定します。
すべてのagentが同じ共有トランスクリプトコレクションを継承すべき場合にのみ、
agents.defaults.memorySearch.qmd.extraCollections を使ってください。
1つのWhatsApp番号、複数の人(DM分割)
異なるWhatsApp DM を、1つのWhatsAppアカウントのまま別々のagentsへルーティングできます。送信者のE.164(例:+15551234567)に対して peer.kind: "direct" でマッチさせます。返信は引き続き同じWhatsApp番号から送られます(agent単位の送信者IDはありません)。
重要な詳細: direct chatはagentのmain session keyに集約されるため、真の分離には1人につき1agentが必要です。
例:
- DMアクセス制御はWhatsAppアカウント単位でグローバルです(pairing/allowlist)。agent単位ではありません。
- 共有グループについては、そのグループを1つのagentにバインドするか、Broadcast groups を使ってください。
ルーティングルール(メッセージがどのagentを選ぶか)
bindingsは決定的で、最も具体的なものが優先されます。peerマッチ(正確なDM/group/channel id)parentPeerマッチ(スレッド継承)guildId + roles(Discordロールルーティング)guildId(Discord)teamId(Slack)- チャネルの
accountIdマッチ - チャネルレベルのマッチ(
accountId: "*") - デフォルトagentへのフォールバック(
agents.list[].default、なければリストの最初の要素、デフォルト:main)
peer + guildId)を設定している場合、指定されたすべてのフィールドが必要です(AND セマンティクス)。
重要なaccountスコープの詳細:
accountIdを省略したbindingは、デフォルトアカウントのみにマッチします。- すべてのアカウントに対するチャネル全体のフォールバックには
accountId: "*"を使います。 - 後から同じagentに対して同じbindingを明示的なaccount id付きで追加した場合、OpenClawは既存のチャネルのみのbindingを複製せず、accountスコープ付きにアップグレードします。
複数のaccounts / 電話番号
複数accounts をサポートするチャネル(例: WhatsApp)では、各ログインを識別するためにaccountId を使います。各 accountId は異なるagentへルーティングできるため、1つのサーバーで複数の電話番号を扱ってもsessionsが混ざりません。
accountId 省略時のチャネル全体のデフォルトアカウントを使いたい場合は、
channels.<channel>.defaultAccount を設定します(任意)。未設定の場合、OpenClawは default が存在すればそれに、なければ設定済みaccount idの先頭(ソート順)にフォールバックします。
このパターンをサポートする一般的なチャネルには次が含まれます。
whatsapp,telegram,discord,slack,signal,imessageirc,line,googlechat,mattermost,matrix,nextcloud-talkbluebubbles,zalo,zalouser,nostr,feishu
概念
agentId: 1つの「頭脳」(workspace、エージェント単位の認証、エージェント単位のセッションストア)。accountId: 1つのチャネルアカウントインスタンス(例: WhatsAppアカウント"personal"と"biz")。binding:(channel, accountId, peer)と、必要に応じてguild/team idによって、受信メッセージをagentIdへルーティングします。- direct chatは
agent:<agentId>:<mainKey>(agent単位の「main」、session.mainKey)に集約されます。
プラットフォーム別の例
agentごとのDiscord bot
各Discord botアカウントは一意のaccountId に対応します。各accountをagentへバインドし、botごとにallowlistを維持します。
- 各botをguildへ招待し、Message Content Intentを有効にしてください。
- トークンは
channels.discord.accounts.<id>.tokenに置きます(デフォルトaccountはDISCORD_BOT_TOKENも使えます)。
agentごとのTelegram bot
- BotFatherでagentごとに1つのbotを作成し、それぞれのトークンをコピーしてください。
- トークンは
channels.telegram.accounts.<id>.botTokenに置きます(デフォルトaccountはTELEGRAM_BOT_TOKENも使えます)。
agentごとのWhatsApp番号
Gatewayを起動する前に各accountをリンクします。~/.openclaw/openclaw.json(JSON5):
例: WhatsAppの日常チャット + Telegramの深い作業
チャネル単位で分割します。WhatsAppは日常向けの高速agentへ、TelegramはOpus agentへルーティングします。- チャネルに複数accountsがある場合は、bindingに
accountIdを追加してください(例:{ channel: "whatsapp", accountId: "personal" })。 - 1つのDM/groupだけをOpusへルーティングし、残りはchatのままにしたい場合は、そのpeerに対する
match.peerbindingを追加してください。peerマッチは常にチャネル全体ルールより優先されます。
例: 同じチャネルで、1つのpeerだけをOpusへ
WhatsAppは高速agentのままにしつつ、1つのDMだけをOpusへルーティングします。WhatsAppグループにバインドされたfamily agent
専用のfamily agentを1つのWhatsAppグループにバインドし、mentionによるゲートとより厳しいtoolポリシーを設定します。- Toolのallow/denyリストはskillsではなくtoolsに対するものです。skillがバイナリを実行する必要がある場合は、
execが許可されていて、そのバイナリがsandbox内に存在することを確認してください。 - より厳密に制御したい場合は、
agents.list[].groupChat.mentionPatternsを設定し、チャネルのgroup allowlistを有効のままにしてください。
エージェント単位のSandboxとTool設定
各agentは独自のsandboxとtool制限を持てます。setupCommand は sandbox.docker 配下にあり、コンテナ作成時に1回だけ実行されます。
解決後のscopeが "shared" の場合、agent単位の sandbox.docker.* 上書きは無視されます。
利点:
- セキュリティ分離: 信頼できないagentsに対してtoolsを制限
- リソース制御: 特定のagentsだけをsandbox化し、他はホスト上で実行
- 柔軟なポリシー: agentごとに異なる権限を設定
tools.elevated はグローバルかつ送信者ベースであり、agent単位には設定できません。
agent単位の境界が必要な場合は、agents.list[].tools を使って exec を拒否してください。
グループ対象指定には agents.list[].groupChat.mentionPatterns を使うと、@mentionが意図したagentへ明確に対応します。
詳しい例は Multi-Agent Sandbox & Tools を参照してください。
関連
- Channel Routing — メッセージがagentsへルーティングされる仕組み
- Sub-Agents — バックグラウンドagent実行の起動
- ACP Agents — 外部コーディングハーネスの実行
- Presence — agentのpresenceと可用性
- Session — セッション分離とルーティング