エージェント連携

サブエージェント

サブエージェントは、既存のエージェント実行から生成されるバックグラウンドのエージェント実行です。それらは独自のセッション (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 配信を試みます。
    • 直接配信が失敗した場合、キュールーティングにフォールバックします。
    • キュールーティングも利用できない場合、アナウンスは最終的な諦めの前に短い指数バックオフで再試行されます。
  • リクエスタセッションへの完了ハンドオフは、ランタイム生成の内部コンテキスト(ユーザー作成テキストではない)であり、以下を含みます:
    • Result (assistant 応答テキスト、またはアシスタント応答が空の場合は最新の toolResult)
    • Status (completed successfully / failed / timed out / unknown)
    • コンパクトなランタイム/トークン統計
    • リクエスタエージェントに生の内部メタデータを転送せず、通常のアシスタントの声調で書き直すよう指示する配信命令
  • --model--thinking は、その特定の実行のデフォルトを上書きします。
  • 完了後の詳細と出力を検査するには info/log を使用します。
  • /subagents spawn はワンショットモード (mode: "run") です。永続的なスレッドバインドセッションの場合は、thread: truemode: "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? (デフォルト falsetrue の場合、このサブエージェントセッションのチャネルスレッドバインドをリクエストします)
  • mode? (run|session)
    • デフォルトは run
    • thread: truemode が省略された場合、デフォルトは session になります
    • mode: "session" には thread: true が必要です
  • cleanup? (delete|keep、デフォルト keep)
  • sandbox? (inherit|require、デフォルト inheritrequire はターゲット子ランタイムがサンドボックス化されていない限りスポーンを拒否します)
  • sessions_spawn はチャネル配信パラメータ (target, channel, to, threadId, replyTo, transport) を受け入れません。配信の場合は、スポーンされた実行から message/sessions_send を使用してください。

スレッドバインドセッション

チャネルでスレッドバインドが有効になっている場合、サブエージェントはスレッドにバインドされたままにできるため、そのスレッド内のフォローアップユーザーメッセージは同じサブエージェントセッションにルーティングされ続けます。

スレッド対応チャネル

  • Discord(現在唯一のサポートチャネル):永続的なスレッドバインドサブエージェントセッション (sessions_spawnthread: 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 をサポートします。

クイックフロー:

  1. thread: true(およびオプションで mode: "session")を指定して sessions_spawn でスポーンします。
  2. OpenClawはアクティブチャネル内でそのセッションターゲットにスレッドを作成またはバインドします。
  3. そのスレッド内の応答とフォローアップメッセージは、バインドされたセッションにルーティングされます。
  4. /session idle を使用して非活動時の自動アンフォーカスを検査/更新し、/session max-age を使用してハードキャップを制御します。
  5. 手動でデタッチするには /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 = タイムアウトなし)
      },
    },
  },
}

深度レベル

深度セッションキー形状役割スポーン可能?
0agent:<id>:mainメインエージェント常に
1agent:<id>:subagent:<uuid>サブエージェント(深度2許可時のオーケストレータ)maxSpawnDepth >= 2 の場合のみ
2agent:<id>:subagent:<uuid>:subagent:<uuid>サブサブエージェント(リーフワーカー)不可

アナウンスチェーン

結果はチェーンを遡って流れます:

  1. 深度2ワーカー完了 → 親(深度1オーケストレータ)にアナウンス
  2. 深度1オーケストレータがアナウンスを受け取り、結果を統合し、完了 → メインにアナウンス
  3. メインエージェントがアナウンスを受け取り、ユーザーに配信

各レベルは直接の子からのアナウンスのみを見ます。

深度別ツールポリシー

  • 深度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_list
  • sessions_history
  • sessions_send
  • sessions_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)。

エージェント送信ACPエージェント