サブエージェント
サブエージェントは、既存のエージェント実行から起動されるバックグラウンドのエージェント実行です。各サブエージェントは独自のセッション(agent:<agentId>:subagent:<uuid>)で実行され、終了すると、その結果を依頼元のチャットチャンネルへ通知します。各サブエージェント実行は background task として追跡されます。
スラッシュコマンド
現在のセッションに対するサブエージェント実行の確認や制御には/subagents を使用します:
/subagents list/subagents kill <id|#|all>/subagents log <id|#> [limit] [tools]/subagents info <id|#>/subagents send <id|#> <message>/subagents steer <id|#> <message>/subagents spawn <agentId> <task> [--model <model>] [--thinking <level>]
/focus <subagent-label|session-key|session-id|session-label>/unfocus/agents/session idle <duration|off>/session max-age <duration|off>
/subagents info は実行メタデータ(ステータス、タイムスタンプ、session id、transcript path、cleanup)を表示します。
sessions_history は制限付きで安全性フィルター済みの再確認ビューに使用し、
生の完全な transcript が必要な場合はディスク上の transcript path を確認してください。
起動時の動作
/subagents spawn は、内部リレーではなくユーザーコマンドとしてバックグラウンドのサブエージェントを起動し、実行終了時に依頼元チャットへ最終的な完了通知を 1 回送信します。
- spawn コマンドは非ブロッキングです。run id を即座に返します。
- 完了時に、サブエージェントはサマリー/結果メッセージを依頼元チャットチャンネルへ通知します。
- 完了通知は push ベースです。起動後は、完了を待つためだけに
/subagents list、sessions_list、sessions_historyをループでポーリングしないでください。 ステータス確認はデバッグや介入が必要なときだけ行ってください。 - 完了時、OpenClaw は、そのサブエージェントセッションが開いた追跡対象の browser tabs/processes を、通知後の cleanup フローに進む前にベストエフォートで閉じます。
- 手動起動では、配信は耐障害性があります:
- OpenClaw はまず、安定した idempotency key を使って直接
agent配信を試みます。 - 直接配信が失敗した場合は、queue routing にフォールバックします。
- queue routing も利用できない場合は、最終的に諦める前に、短い指数バックオフで通知を再試行します。
- OpenClaw はまず、安定した idempotency key を使って直接
- 完了時の配信では、解決済みの依頼元ルートを維持します:
- 利用可能な場合は、thread-bound または conversation-bound の完了ルートが優先されます
- 完了元が channel しか提供しない場合、OpenClaw は依頼元セッションの解決済みルート(
lastChannel/lastTo/lastAccountId)から不足している target/account を補い、直接配信が引き続き機能するようにします
- 依頼元セッションへの完了ハンドオフは、実行時に生成される内部コンテキスト(ユーザー作成テキストではない)であり、以下を含みます:
Result(最新の表示可能なassistant返信テキスト、なければサニタイズ済みの最新tool/toolResultテキスト)Status(completed successfully/failed/timed out/unknown)- コンパクトな runtime/token 統計
- 依頼元エージェントに対し、生の内部メタデータを転送するのではなく、通常の assistant の声で書き直すよう指示する配信命令
--modelと--thinkingは、その特定の実行の既定値を上書きします。- 完了後の詳細や出力確認には
info/logを使用します。 /subagents spawnはワンショットモード(mode: "run")です。永続的なスレッド束縛セッションには、thread: trueとmode: "session"を指定したsessions_spawnを使用してください。- ACP harness session(Codex、Claude Code、Gemini CLI)には、
runtime: "acp"を指定したsessions_spawnを使用し、ACP Agents を参照してください。
- メイン実行をブロックせずに、「調査 / 長時間タスク / 遅い tool」作業を並列化する。
- サブエージェントを既定で分離した状態に保つ(セッション分離 + 任意の sandboxing)。
- tool surface を誤用しにくく保つ。サブエージェントは既定では session tools を受け取りません。
- オーケストレーターパターン向けに、設定可能なネスト深度をサポートする。
agents.defaults.subagents.model またはエージェントごとの上書きで設定できます。
Tool
sessions_spawn を使用します:
- サブエージェント実行を開始します(
deliver: false、global lane:subagent) - その後、通知ステップを実行し、通知返信を依頼元チャットチャンネルへ投稿します
- 既定モデル:
agents.defaults.subagents.model(またはエージェントごとのagents.list[].subagents.model)を設定していない限り、呼び出し元を継承します。明示的なsessions_spawn.modelがある場合はそれが優先されます。 - 既定の thinking:
agents.defaults.subagents.thinking(またはエージェントごとのagents.list[].subagents.thinking)を設定していない限り、呼び出し元を継承します。明示的なsessions_spawn.thinkingがある場合はそれが優先されます。 - 既定の実行タイムアウト:
sessions_spawn.runTimeoutSecondsが省略された場合、OpenClaw は設定されていればagents.defaults.subagents.runTimeoutSecondsを使用し、そうでなければ0(タイムアウトなし)にフォールバックします。
task(必須)label?(任意)agentId?(任意。許可されていれば別の agent id の下で起動)model?(任意。サブエージェントのモデルを上書き。無効な値はスキップされ、tool result に警告付きで既定モデル上でサブエージェントが実行されます)thinking?(任意。サブエージェント実行の thinking レベルを上書き)runTimeoutSeconds?(設定されていればagents.defaults.subagents.runTimeoutSecondsが既定値、そうでなければ0。設定時は N 秒後にサブエージェント実行が中止されます)thread?(既定false。trueの場合、このサブエージェントセッションに対して channel thread binding を要求)mode?(run|session)- 既定は
run thread: trueでmodeが省略された場合、既定はsessionmode: "session"にはthread: trueが必要
- 既定は
cleanup?(delete|keep、既定keep)sandbox?(inherit|require、既定inherit。requireは、対象子ランタイムが sandboxed でない限り起動を拒否)sessions_spawnは channel-delivery パラメーター(target、channel、to、threadId、replyTo、transport)を受け付けません。配信には、起動された実行側からmessage/sessions_sendを使用してください。
スレッド束縛セッション
チャンネルで thread bindings が有効になっている場合、サブエージェントはスレッドに束縛されたままにできるため、そのスレッド内の後続ユーザーメッセージは同じサブエージェントセッションへルーティングされ続けます。スレッド対応チャンネル
- Discord(現在サポートされている唯一のチャンネル): 永続的な thread-bound subagent sessions(
thread: trueを指定したsessions_spawn)、手動のスレッド制御(/focus、/unfocus、/agents、/session idle、/session max-age)、およびアダプターキーchannels.discord.threadBindings.enabled、channels.discord.threadBindings.idleHours、channels.discord.threadBindings.maxAgeHours、channels.discord.threadBindings.spawnSubagentSessionsをサポートします。
thread: true(必要に応じてmode: "session"も)を指定してsessions_spawnで起動します。- OpenClaw が、そのセッション対象に対してアクティブチャンネル内でスレッドを作成または束縛します。
- そのスレッド内の返信と後続メッセージは、束縛されたセッションへルーティングされます。
/session idleを使って、非アクティブ時の自動 unfocus を確認/更新し、/session max-ageでハード上限を制御します。- 手動で切り離すには
/unfocusを使用します。
/focus <target>は、現在のスレッドをサブエージェント/セッション対象に束縛します(または新しく作成します)。/unfocusは、現在束縛されているスレッドの束縛を解除します。/agentsは、アクティブな実行と束縛状態(thread:<id>またはunbound)を一覧表示します。/session idleと/session max-ageは、focus 済みの束縛スレッドでのみ動作します。
- グローバル既定値:
session.threadBindings.enabled、session.threadBindings.idleHours、session.threadBindings.maxAgeHours - チャンネル上書きと起動時の自動束縛キーはアダプター固有です。上記のスレッド対応チャンネルを参照してください。
agents.list[].subagents.allowAgents:agentId経由で指定可能な agent id の一覧(任意のものを許可するには["*"])。既定値: 依頼元エージェントのみ。agents.defaults.subagents.allowAgents: 依頼元エージェントが独自のsubagents.allowAgentsを設定していない場合に使用される、既定の対象エージェント allowlist。- Sandbox 継承ガード: 依頼元セッションが sandboxed の場合、
sessions_spawnは sandbox なしで実行される対象を拒否します。 agents.defaults.subagents.requireAgentId/agents.list[].subagents.requireAgentId: true の場合、agentIdを省略したsessions_spawn呼び出しをブロックします(明示的なプロファイル選択を強制)。既定値: false。
sessions_spawnで現在どの agent id が許可されているか確認するにはagents_listを使用します。
- サブエージェントセッションは、
agents.defaults.subagents.archiveAfterMinutes(既定値: 60)後に自動的にアーカイブされます。 - アーカイブでは
sessions.deleteを使用し、transcript を*.deleted.<timestamp>にリネームします(同じフォルダー内)。 cleanup: "delete"は通知直後に即時アーカイブします(ただし transcript はリネームによって保持されます)。- 自動アーカイブはベストエフォートです。gateway が再起動すると保留中タイマーは失われます。
runTimeoutSecondsは自動アーカイブしません。実行を停止するだけです。セッションは自動アーカイブまで残ります。- 自動アーカイブは深さ 1 と深さ 2 のセッションに同様に適用されます。
- browser cleanup は archive cleanup とは別です。追跡対象の browser tabs/processes は、transcript/session record を保持する場合でも、実行終了時にベストエフォートで閉じられます。
ネストしたサブエージェント
既定では、サブエージェントは自分自身のサブエージェントを起動できません(maxSpawnDepth: 1)。maxSpawnDepth: 2 を設定すると 1 段階のネストを有効にでき、オーケストレーターパターン、つまり main → orchestrator sub-agent → worker sub-sub-agents を実現できます。
有効化方法
深さレベル
| Depth | Session key の形状 | 役割 | 起動可能か |
|---|---|---|---|
| 0 | agent:<id>:main | メインエージェント | 常に可能 |
| 1 | agent:<id>:subagent:<uuid> | サブエージェント(深さ 2 が許可された場合は orchestrator) | maxSpawnDepth >= 2 の場合のみ |
| 2 | agent:<id>:subagent:<uuid>:subagent:<uuid> | サブサブエージェント(leaf worker) | 不可 |
通知チェーン
結果はチェーンをさかのぼって流れます:- 深さ 2 の worker が終了 → 親(深さ 1 の orchestrator)へ通知
- 深さ 1 の orchestrator が通知を受信し、結果を統合して終了 → main へ通知
- メインエージェントが通知を受信し、ユーザーへ配信
sessions_list、sessions_history、/subagents list、またはexecの sleep コマンドを中心にしたポーリングループを作るのではなく、 子の作業は一度開始したら完了イベントを待ってください。- すでに最終回答を送信した後に子の完了イベントが到着した場合、
正しいフォローアップは厳密に無音トークン
NO_REPLY/no_replyです。
深さごとの tool policy
- 役割と制御スコープは起動時に session metadata に書き込まれます。これにより、平坦化または復元された session key が誤って orchestrator 権限を取り戻すことを防ぎます。
- 深さ 1(orchestrator、
maxSpawnDepth >= 2の場合): 子を管理できるよう、sessions_spawn、subagents、sessions_list、sessions_historyを取得します。その他の session/system tools は引き続き拒否されます。 - 深さ 1(leaf、
maxSpawnDepth == 1の場合): session tools はありません(現在の既定動作)。 - 深さ 2(leaf worker): session tools はありません。深さ 2 では
sessions_spawnは常に拒否されます。これ以上子を起動できません。
エージェントごとの起動上限
各エージェントセッション(任意の深さ)は、同時に最大maxChildrenPerAgent(既定: 5)個のアクティブな子しか持てません。これにより、単一 orchestrator からの暴走的なファンアウトを防ぎます。
カスケード停止
深さ 1 の orchestrator を停止すると、すべての深さ 2 の子も自動的に停止します:- メインチャットでの
/stopは、すべての深さ 1 エージェントを停止し、その深さ 2 の子へもカスケードします。 /subagents kill <id>は、特定のサブエージェントを停止し、その子へもカスケードします。/subagents kill allは、依頼元に対するすべてのサブエージェントを停止し、カスケードします。
認証
サブエージェントの認証は、session type ではなく agent id によって解決されます:- サブエージェントセッションキーは
agent:<agentId>:subagent:<uuid>です。 - auth store は、そのエージェントの
agentDirから読み込まれます。 - メインエージェントの auth profiles はフォールバックとしてマージされます。競合時にはエージェントの profiles がメインの profiles を上書きします。
通知
サブエージェントは通知ステップによって結果を返します:- 通知ステップは、依頼元セッションではなくサブエージェントセッション内で実行されます。
- サブエージェントが正確に
ANNOUNCE_SKIPと返信した場合、何も投稿されません。 - 最新の assistant テキストが厳密な無音トークン
NO_REPLY/no_replyの場合、 以前に可視の進捗が存在していても通知出力は抑制されます。 - それ以外の場合、配信は依頼元の深さに依存します:
- 最上位の依頼元セッションでは、外部配信付きの後続
agent呼び出し(deliver=true)を使用します - ネストした依頼元サブエージェントセッションでは、orchestrator がセッション内で子の結果を統合できるよう、内部の後続注入(
deliver=false)を受け取ります - ネストした依頼元サブエージェントセッションが消えている場合、利用可能であれば OpenClaw はそのセッションの依頼元にフォールバックします
- 最上位の依頼元セッションでは、外部配信付きの後続
- 最上位の依頼元セッションでは、完了モードの直接配信はまず束縛済みの conversation/thread route と hook override を解決し、その後、依頼元セッションの保存済み route から不足している channel-target フィールドを補います。これにより、完了元が channel しか識別しない場合でも、完了通知が正しい chat/topic に届きます。
- ネストした完了通知の構築時には、子完了の集約は現在の依頼元実行のスコープに限定されるため、過去の実行の古い子出力が現在の通知に漏れません。
- 通知返信は、channel adapters で利用可能な場合、thread/topic ルーティングを保持します。
- 通知コンテキストは、安定した内部イベントブロックへ正規化されます:
- source(
subagentまたはcron) - 子 session key/id
- 通知タイプ + task label
- 実行時 outcome(
success、error、timeout、またはunknown)から導出された status line - 最新の表示可能 assistant text、またはサニタイズ済みの最新 tool/toolResult text から選ばれた result content
- 返信するべき場合と黙るべき場合を説明する follow-up instruction
- source(
Statusはモデル出力から推測されません。実行時 outcome シグナルから取得されます。- タイムアウト時、子が tool calls までしか進んでいない場合、通知では生の tool output を再生する代わりに、その履歴を短い部分進捗サマリーへ圧縮できることがあります。
- Runtime(例:
runtime 5m12s) - トークン使用量(input/output/total)
- モデル価格設定が構成されている場合の推定コスト(
models.providers.*.models[].cost) sessionKey、sessionId、transcript path(これにより、メインエージェントはsessions_history経由で履歴を取得したり、ディスク上のファイルを確認したりできます)- 内部メタデータはオーケストレーション専用です。ユーザー向け返信は通常の assistant の声で書き直すべきです。
sessions_history は、より安全なオーケストレーション経路です:
- assistant の再確認内容は最初に正規化されます:
- thinking タグを除去
<relevant-memories>/<relevant_memories>の scaffolding blocks を除去<tool_call>...</tool_call>、<function_call>...</function_call>、<tool_calls>...</tool_calls>、および<function_calls>...</function_calls>のようなプレーンテキストの tool-call XML payload blocks を除去。きれいに閉じないまま切り詰められた payloads も含みます- 格下げされた tool-call/result scaffolding と historical-context markers を除去
<|assistant|>のような漏れたモデル制御トークン、その他の ASCII<|...|>トークン、および全角の<|...|>バリアントを除去- 壊れた MiniMax tool-call XML を除去
- credential/token に似たテキストはマスクされます
- 長いブロックは切り詰められることがあります
- 非常に大きな履歴では、古い行が削除されたり、過大な行が
[sessions_history omitted: message too large]に置き換えられたりすることがあります - 完全にバイト単位で同一の transcript が必要な場合は、ディスク上の生 transcript の確認がフォールバックです
Tool Policy(サブエージェントの tools)
既定では、サブエージェントは session tools と system tools を除くすべての toolsを取得します:sessions_listsessions_historysessions_sendsessions_spawn
sessions_history は制限付きでサニタイズ済みの再確認ビューであり、
生の transcript ダンプではありません。
maxSpawnDepth >= 2 の場合、深さ 1 の orchestrator サブエージェントは、子を管理できるよう追加で sessions_spawn、subagents、sessions_list、sessions_history を取得します。
設定による上書き:
同時実行
サブエージェントは専用のインプロセスキューレーンを使用します:- レーン名:
subagent - 同時実行数:
agents.defaults.subagents.maxConcurrent(既定値8)
停止
- 依頼元チャットで
/stopを送信すると、依頼元セッションが中止され、そこから起動されたアクティブなサブエージェント実行も停止され、ネストした子にもカスケードします。 /subagents kill <id>は、特定のサブエージェントを停止し、その子にもカスケードします。
制限事項
- サブエージェントの通知はベストエフォートです。gateway が再起動すると、保留中の「通知して戻る」作業は失われます。
- サブエージェントは依然として同じ gateway process リソースを共有するため、
maxConcurrentは安全弁として扱ってください。 sessions_spawnは常に非ブロッキングです。即座に{ status: "accepted", runId, childSessionKey }を返します。- サブエージェントコンテキストには
AGENTS.md+TOOLS.mdのみが注入されます(SOUL.md、IDENTITY.md、USER.md、HEARTBEAT.md、BOOTSTRAP.mdは含まれません)。 - 最大ネスト深度は 5(
maxSpawnDepthの範囲: 1–5)です。多くの用途では深さ 2 を推奨します。 maxChildrenPerAgentは、セッションごとのアクティブな子の数を制限します(既定値: 5、範囲: 1–20)。