サブエージェント
サブエージェントは、既存のエージェント実行から生成されるバックグラウンドのエージェント実行です。それらは独自のセッション (agent:<agentId>:subagent:<uuid>) で実行され、完了すると、その結果をリクエスタのチャットチャネルに アナウンス して戻します。
スラッシュコマンド
/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 は実行メタデータ(ステータス、タイムスタンプ、セッションID、トランスクリプトパス、クリーンアップ)を表示します。
スポーン動作
/subagents spawn は、内部リレーではなくユーザーコマンドとしてバックグラウンドサブエージェントを開始し、実行が終了するとリクエスタチャットに1回の最終完了更新を送信します。
- スポーンコマンドは非ブロッキングです。即座に実行IDを返します。
- 完了時、サブエージェントは要約/結果メッセージをリクエスタのチャットチャネルにアナウンスして戻します。
- 手動スポーンの場合、配信は耐障害性があります:
- OpenClawは最初に安定したべき等キーで直接
agent配信を試みます。 - 直接配信が失敗した場合、キュールーティングにフォールバックします。
- キュールーティングも利用できない場合、アナウンスは最終的な諦めの前に短い指数バックオフで再試行されます。
- OpenClawは最初に安定したべき等キーで直接
- リクエスタセッションへの完了ハンドオフは、ランタイム生成の内部コンテキスト(ユーザー作成テキストではない)であり、以下を含みます:
Result(assistant応答テキスト、またはアシスタント応答が空の場合は最新のtoolResult)Status(completed successfully/failed/timed out/unknown)- コンパクトなランタイム/トークン統計
- リクエスタエージェントに生の内部メタデータを転送せず、通常のアシスタントの声調で書き直すよう指示する配信命令
--modelと--thinkingは、その特定の実行のデフォルトを上書きします。- 完了後の詳細と出力を検査するには
info/logを使用します。 /subagents spawnはワンショットモード (mode: "run") です。永続的なスレッドバインドセッションの場合は、thread: trueとmode: "session"を指定したsessions_spawnを使用します。- ACPハーネスセッション(Codex、Claude Code、Gemini CLI)の場合は、
runtime: "acp"を指定したsessions_spawnを使用し、ACPエージェント を参照してください。
主な目的:
- メイン実行をブロックせずに「調査 / 長いタスク / 遅いツール」作業を並列化する。
- デフォルトでサブエージェントを分離する(セッション分離 + オプションのサンドボックス化)。
- 誤用しにくいツール表面を維持する:サブエージェントはデフォルトでセッションツールを取得しません。
- オーケストレータパターンのための設定可能なネスト深度をサポートする。
コスト注意:各サブエージェントは独自のコンテキストとトークン使用量を持ちます。重いまたは繰り返しのタスクでは、サブエージェントにはより安価なモデルを設定し、メインエージェントは高品質モデルのままにします。これは agents.defaults.subagents.model またはエージェントごとのオーバーライドで設定できます。
ツール
sessions_spawn を使用します:
- サブエージェント実行を開始します (
deliver: false、グローバルレーン:subagent) - 次にアナウンスステップを実行し、アナウンス応答をリクエスタのチャットチャネルに投稿します
- デフォルトモデル:呼び出し元を継承します(
agents.defaults.subagents.model(またはエージェントごとのagents.list[].subagents.model)を設定していない場合)。明示的なsessions_spawn.modelは依然として優先されます。 - デフォルト思考レベル:呼び出し元を継承します(
agents.defaults.subagents.thinking(またはエージェントごとのagents.list[].subagents.thinking)を設定していない場合)。明示的なsessions_spawn.thinkingは依然として優先されます。 - デフォルト実行タイムアウト:
sessions_spawn.runTimeoutSecondsが省略された場合、OpenClawは設定されていればagents.defaults.subagents.runTimeoutSecondsを使用します。それ以外の場合は0(タイムアウトなし)にフォールバックします。
ツールパラメータ:
task(必須)label?(オプション)agentId?(オプション;許可されていれば別のエージェントIDの下でスポーン)model?(オプション;サブエージェントモデルを上書きします;無効な値はスキップされ、サブエージェントはデフォルトモデルで実行され、ツール結果に警告が表示されます)thinking?(オプション;サブエージェント実行の思考レベルを上書きします)runTimeoutSeconds?(設定されていればデフォルトはagents.defaults.subagents.runTimeoutSeconds、それ以外は0;設定すると、サブエージェント実行はN秒後に中止されます)thread?(デフォルトfalse;trueの場合、このサブエージェントセッションのチャネルスレッドバインドをリクエストします)mode?(run|session)- デフォルトは
run thread: trueでmodeが省略された場合、デフォルトはsessionになりますmode: "session"にはthread: trueが必要です
- デフォルトは
cleanup?(delete|keep、デフォルトkeep)sandbox?(inherit|require、デフォルトinherit;requireはターゲット子ランタイムがサンドボックス化されていない限りスポーンを拒否します)sessions_spawnはチャネル配信パラメータ (target,channel,to,threadId,replyTo,transport) を受け入れません。配信の場合は、スポーンされた実行からmessage/sessions_sendを使用してください。
スレッドバインドセッション
チャネルでスレッドバインドが有効になっている場合、サブエージェントはスレッドにバインドされたままにできるため、そのスレッド内のフォローアップユーザーメッセージは同じサブエージェントセッションにルーティングされ続けます。
スレッド対応チャネル
- Discord(現在唯一のサポートチャネル):永続的なスレッドバインドサブエージェントセッション (
sessions_spawnにthread: true)、手動スレッド制御 (/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を使用して非活動時の自動アンフォーカスを検査/更新し、/session max-ageを使用してハードキャップを制御します。- 手動でデタッチするには
/unfocusを使用します。
手動制御:
/focus <target>は現在のスレッド(またはスレッドを作成)をサブエージェント/セッションターゲットにバインドします。/unfocusは現在バインドされているスレッドのバインドを解除します。/agentsはアクティブな実行とバインド状態 (thread:<id>またはunbound) をリストします。/session idleと/session max-ageはフォーカスされたバインドスレッドに対してのみ動作します。
設定スイッチ:
- グローバルデフォルト:
session.threadBindings.enabled,session.threadBindings.idleHours,session.threadBindings.maxAgeHours - チャネルオーバーライドとスポーン自動バインドキーはアダプタ固有です。上記の スレッド対応チャネル を参照してください。
現在のアダプタの詳細については、設定リファレンス と スラッシュコマンド を参照してください。許可リスト:
agents.list[].subagents.allowAgents:agentIdを介してターゲットにできるエージェントIDのリスト (["*"]で任意を許可)。デフォルト:リクエスタエージェントのみ。- サンドボックス継承ガード:リクエスタセッションがサンドボックス化されている場合、
sessions_spawnはサンドボックス化されていない状態で実行されるターゲットを拒否します。
ディスカバリー:
agents_listを使用して、現在sessions_spawnで許可されているエージェントIDを確認します。
自動アーカイブ:
- サブエージェントセッションは、
agents.defaults.subagents.archiveAfterMinutes(デフォルト:60)後に自動的にアーカイブされます。 - アーカイブは
sessions.deleteを使用し、トランスクリプトを*.deleted.<timestamp>に名前変更します(同じフォルダ)。 cleanup: "delete"はアナウンス後すぐにアーカイブします(名前変更によりトランスクリプトは保持されます)。- 自動アーカイブはベストエフォートです。ゲートウェイが再起動すると、保留中のタイマーは失われます。
runTimeoutSecondsは自動アーカイブしません。実行を停止するだけです。セッションは自動アーカイブまで残ります。- 自動アーカイブは深度1と深度2のセッションに同様に適用されます。
ネストされたサブエージェント
デフォルトでは、サブエージェントは独自のサブエージェントをスポーンできません (maxSpawnDepth: 1)。maxSpawnDepth: 2 を設定することで、1レベルのネストを有効にできます。これにより、オーケストレータパターンが可能になります:メイン → オーケストレータサブエージェント → ワーカーサブサブエージェント。
有効化方法
{
agents: {
defaults: {
subagents: {
maxSpawnDepth: 2, // サブエージェントが子をスポーンできるようにする(デフォルト: 1)
maxChildrenPerAgent: 5, // エージェントセッションごとの最大アクティブ子数(デフォルト: 5)
maxConcurrent: 8, // グローバル同時実行レーンキャップ(デフォルト: 8)
runTimeoutSeconds: 900, // 省略時の sessions_spawn のデフォルトタイムアウト(0 = タイムアウトなし)
},
},
},
}
深度レベル
| 深度 | セッションキー形状 | 役割 | スポーン可能? |
|---|---|---|---|
| 0 | agent:<id>:main | メインエージェント | 常に |
| 1 | agent:<id>:subagent:<uuid> | サブエージェント(深度2許可時のオーケストレータ) | maxSpawnDepth >= 2 の場合のみ |
| 2 | agent:<id>:subagent:<uuid>:subagent:<uuid> | サブサブエージェント(リーフワーカー) | 不可 |
アナウンスチェーン
結果はチェーンを遡って流れます:
- 深度2ワーカー完了 → 親(深度1オーケストレータ)にアナウンス
- 深度1オーケストレータがアナウンスを受け取り、結果を統合し、完了 → メインにアナウンス
- メインエージェントがアナウンスを受け取り、ユーザーに配信
各レベルは直接の子からのアナウンスのみを見ます。
深度別ツールポリシー
- 深度1(オーケストレータ、
maxSpawnDepth >= 2の場合):sessions_spawn,subagents,sessions_list,sessions_historyを取得し、子を管理できます。他のセッション/システムツールは拒否されたままです。 - 深度1(リーフ、
maxSpawnDepth == 1の場合):セッションツールなし(現在のデフォルト動作)。 - 深度2(リーフワーカー):セッションツールなし —
sessions_spawnは深度2では常に拒否されます。それ以上の子をスポーンできません。
エージェントごとのスポーン制限
各エージェントセッション(任意の深度)は、同時に最大 maxChildrenPerAgent(デフォルト:5)のアクティブな子を持つことができます。これにより、単一のオーケストレータからの暴走的なファンアウトを防ぎます。
カスケード停止
深度1オーケストレータを停止すると、そのすべての深度2の子が自動的に停止します:
- メインチャットでの
/stopはすべての深度1エージェントとその深度2の子をカスケード停止します。 /subagents kill <id>は特定のサブエージェントとその子をカスケード停止します。/subagents kill allはリクエスタのすべてのサブエージェントとその子をカスケード停止します。
認証
サブエージェント認証は、セッションタイプではなくエージェントIDによって解決されます:
- サブエージェントセッションキーは
agent:<agentId>:subagent:<uuid>です。 - 認証ストアはそのエージェントの
agentDirからロードされます。 - メインエージェントの認証プロファイルはフォールバックとしてマージされます。エージェントプロファイルは競合時にメインプロファイルを上書きします。
注:マージは加算的であるため、メインプロファイルは常にフォールバックとして利用可能です。エージェントごとの完全に分離された認証はまだサポートされていません。
アナウンス
サブエージェントはアナウンスステップを介して報告します:
- アナウンスステップはサブエージェントセッション内(リクエスタセッション内ではない)で実行されます。
- サブエージェントが正確に
ANNOUNCE_SKIPと返信した場合、何も投稿されません。 - それ以外の場合、配信はリクエスタの深度に依存します:
- トップレベルのリクエスタセッションは、外部配信 (
deliver=true) によるフォローアップagent呼び出しを使用します - ネストされたリクエスタサブエージェントセッションは、内部フォローアップインジェクション (
deliver=false) を受け取り、オーケストレータがセッション内で子の結果を統合できるようにします - ネストされたリクエスタサブエージェントセッションがなくなった場合、OpenClawは利用可能であればそのセッションのリクエスタにフォールバックします
- トップレベルのリクエスタセッションは、外部配信 (
- 子完了の集約は、ネストされた完了結果を構築する際に現在のリクエスタ実行にスコープされ、古い以前の実行の子出力が現在のアナウンスに漏れるのを防ぎます。
- アナウンス応答は、チャネルアダプタで利用可能な場合、スレッド/トピックルーティングを保持します。
- アナウンスコンテキストは安定した内部イベントブロックに正規化されます:
- ソース (
subagentまたはcron) - 子セッションキー/ID
- アナウンスタイプ + タスクラベル
- ランタイム結果から派生したステータス行 (
success,error,timeout, またはunknown) - アナウンスステップからの結果コンテンツ(または欠落している場合は
(no output)) - 返信するか黙っているかを説明するフォローアップ命令
- ソース (
Statusはモデル出力から推測されません。ランタイム結果シグナルから来ます。
アナウンスペイロードには、最後に統計行が含まれます(ラップされていても):
- ランタイム(例:
runtime 5m12s) - トークン使用量(入力/出力/合計)
- モデル価格設定が構成されている場合の推定コスト (
models.providers.*.models[].cost) sessionKey,sessionId, およびトランスクリプトパス(メインエージェントがsessions_historyで履歴を取得したり、ディスク上のファイルを検査できるように)- 内部メタデータはオーケストレーション専用です。ユーザー向けの返信は通常のアシスタントの声調で書き直されるべきです。
ツールポリシー(サブエージェントツール)
デフォルトでは、サブエージェントはセッションツールとシステムツールを除くすべてのツールを取得します:
sessions_listsessions_historysessions_sendsessions_spawn
maxSpawnDepth >= 2 の場合、深度1オーケストレータサブエージェントは追加で sessions_spawn, subagents, sessions_list, sessions_history を受け取り、子を管理できます。設定でオーバーライド:
{
agents: {
defaults: {
subagents: {
maxConcurrent: 1,
},
},
},
tools: {
subagents: {
tools: {
// deny が優先
deny: ["gateway", "cron"],
// allow が設定されている場合、許可のみになります(deny は依然として優先)
// allow: ["read", "exec", "process"]
},
},
},
}
同時実行性
サブエージェントは専用のインプロセスキューレーンを使用します:
- レーン名:
subagent - 同時実行数:
agents.defaults.subagents.maxConcurrent(デフォルト8)
停止
- リクエスタチャットで
/stopを送信すると、リクエスタセッションが中止され、そこからスポーンされたアクティブなサブエージェント実行が停止し、ネストされた子にカスケードします。 /subagents kill <id>は特定のサブエージェントとその子を停止します。
制限事項
- サブエージェントアナウンスはベストエフォートです。ゲートウェイが再起動すると、保留中の「アナウンスバック」作業は失われます。
- サブエージェントは依然として同じゲートウェイプロセスリソースを共有します。
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)。