CH 13 · サブエージェントとマルチ Agent 编排
この章の目標
タスクが大きすぎてもつれすぎても、1 つの Agent に最後まで頑張らせる代わりに、いくつかのピースに分けて複数のサブエージェントを並列に走らせ、終わったら結果を集める。この章ではっきりさせます:なぜマルチ Agent なのか、dsh のサブエージェントはどんな形か、それから「タスク分割 → 並列委托 → 結果マージ」を実操作し、最後にツールファミリ全種を棚卸しします。
なぜマルチ Agent:シングルスレッドの 3 つの難所
1 つの Agent が最初から最後まで突き進むと、3 つの問題にぶつかります:
| 難所 | 症状 |
|---|---|
| 文脈汚染 | タスクの途中で、初期ステップ、中間結果、エラーが同じセッションに積み上がり、モデルは「今どの情報が最も重要か」を段々見分けられなくなる |
| 並列化できない | 情報検索、ドラフト書き、コードレビュー —— 3 つのことはキューに並ぶしかなく、次の 1 つは前が終わらないと動けない |
| 軌道から逸れていく | 長いタスクでモデルは誤った経路にハマりやすく、同じ失敗ルートを繰り返し、トークンを浪費する |
マルチ Agent の発想はまさにその対症療法です:文脈隔離。各サブエージェントは自分のタスクに関連する文脈だけを持ち、メイン Agent が分割・派遣・収集します。トークン消費は制御可能で、各ステップは軌跡でレビューできます。
重要な事実:サブエージェントもプラグイン
まず安心材料:サブエージェントは dsh が隠してある別物ではなく、プラグインです —— CH 08 の「すべてはプラグイン」をもう一度裏付けます。サブエージェントは現行の Agent ツールではすでに標準で、Claude Code、Codex にもこの能力があります;唯一の違いは dsh ではやはりプラグインとして存在することです —— 欲しいなら使う、欲しくなければ全体を差し替えられる。
設定ツリーでは、委托契約 ctx.subagents が見え、その仕事は「誰がサブエージェントになれるか」を登録することだけです。次に異なる provider プラグインが具体的なバックエンドをそこに取り付けます:
| プラグイン | 実行内容 |
|---|---|
subagent-spawn-in-process | 全新インプロセスサブエージェント(独立文脈) |
subagent-fork-in-process | 親セッションの完了履歴からサブエージェントを「派生」 |
subagent-acp | Agent Client Protocol を利用、プロセス外 ACP 互換 Agent を受け入れる |
subagent-codex | 実物の Codex(公式 app-server プロトコル)を走らせる |
subagent-claude-code | 実物の Claude Code(公式 Agent SDK)を走らせる |
subagent-dsh-sdk | TypeScript SDK 経由で別の完全 Harness を起動 |
メインエージェントは何が見えるか?いくつかの「モデル可視ツール」です。web 設定ツリーを開くと、デフォルトは:
| ツール | 機能 | デフォルト |
|---|---|---|
subagent | サブエージェントを派遣、continuable モード | on |
subagent_fork | 親セッションの記憶付きで派遣、ワンショット | on |
ralph | 各ラウンドで新サブエージェントに差し替え、同じ目標を推進 | on |
workflow | スクリプトを書いて複数のサブタスクを並列编排 | off(デフォルト無効) |
send_message | 指定サブエージェントに追従指示を送る | off(デフォルト無効) |
interrupt_agent | サブエージェントの現ラウンドを中断 | off(デフォルト無効) |
list_agents | 現サブエージェントと状態を一覧 | off(デフォルト無効) |
つまり箱から出してすぐ、subagent、subagent_fork、ralph を直接呼び出せます。他のツールはデフォルトでオフで手動で有効化が必要か、「continuable モード」でのみ意味を持ちます —— 次節でそれぞれどこに現れるかを扱います。
spawn vs fork:2 つの「オープニング」
最もよく使う 2 つのサブエージェント、違いはただ 1 点:親セッションの履歴を持っていくかどうか。
subagent(spawn):全新文脈。サブエージェントはメインエージェントが何を話していたか知らず、今回与えた指示にただ従う。トークンを節約、独立したタスクに適する。subagent_fork(fork):親セッションの完了部分を継承。サブエージェントは「ここまで何を分析していたか」を知っており、そこから続けられる。重複文脈でコストが少し増、前の結論の上に積み上げるタスクに適する。
一点留意:dsh は「継承するかどうか」をツール説明に直接書きます —— spawn 系ツールの説明は「この会話は見えない」、fork 系は「進行中のターンは見えない」と。つまり、指示文の中で文脈を繰り返すかどうかはモデル自身が分かっています。
一行で覚える
subagent はパラシュートで新しい同僚を降ろすイメージで、彼が持っているのはあなたの口頭のタスクブリーフだけ; subagent_fork は議事録を渡すイメージで、「さっきのとこから続けて」。
実操作:初めての並列サブエージェント
並列で、3 つのサブエージェントを起動し、それぞれ:
deepseek-harnessリポジトリのpackages/ディレクトリ構成を整理し、各能力ファミリが何をするかを説明;- ルート README がカバーする中核概念を要約;
docs/配下のサブエージェント関連ドキュメントを見つけ、列挙。 3 つとも終わったら、結果を 1 つのサマリに統合。
この文の 3 つの要素、どれか欠けても収集つかなくなります:
| 要素 | なぜ必要か |
|---|---|
| タスク分割ルール | 「どのピースに分けるか」をモデルに伝える、ないと勝手に推測 |
| 待機機構(全部終わるまで待つ) | これがなければ、メインエージェントはあるサブエージェントが終わる前に不完全な結果をまとめ始めるかもしれない |
| 出力要件(サマリに統合) | これがなければ、3 つのサブエージェントがそれぞれ生のテキストを投げ返し、自分で繋ぎ合わせる羽目に |
送信後、会話でモデルが立て続けに複数の subagent 呼び出しをするのが見えます —— それが派遣です。デフォルトの continuable モードでは、モデルは「並列可能なものをまずまとめて送り、自分の作業は続ける」となり、最初のサブエージェントが返るのを待ちません。

一部のサブエージェントが先に終わっても問題ありません —— メインエージェントは残りを待ち続け、すべて揃ってからまとめに入ります:


フォアグラウンド / バックグラウンド / Continuable:3 つの実行モード
サブエージェントは「派遣して結果を待つ」だけではありません。「待つか、話し続けるか」によって 3 モードに分かれます:
| モード | 使いどき | 見える形 |
|---|---|---|
| フォアグラウンド・ワンショット | 次のステップが即この結果に依存 | サブエージェントの最終テキストが返るまで待つ |
| バックグラウンド Job(ワンショット BG) | 待つ必要はない、後で回収 | started background subagent job <id>、job_output で回収、job_kill で停止 |
| Continuable サブエージェント | 追従指示を送る必要がある、行ったり来たり | started subagent <childId>、後でメッセージを送れる |
デフォルトの subagent は continuable モード:デフォルトではバックグラウンドに派遣され、メインエージェントは自分の作業をする;サブエージェントが終わったら、コールバック通知が「完了、結果はこちら」を届けます。次のステップが本当に結果を必要とするときだけ、モデルはフォアグラウンド待機に切り替えます。
continuable サブエージェントをもっと制御したいときは、send_message(追従指示)、interrupt_agent(現ラウンドを中断、破棄せず再開可)、list_agents(サブエージェントと状態を一覧)を有効化する必要があります。多くのシナリオで使わないのでデフォルトでオフ —— 「高度能力、必要になったらオンに」という扱い。
workflow と ralph:2 つの「オーケストレーション」ツール
「分割して並列で走らせる」以外に、dsh にはより構造化されたオーケストレーション種別が 2 つ、どちらもプラグインです:
| ツール | 機能 | 適する場面 |
|---|---|---|
workflow | モデルに小さな编排スクリプトを書かせ、agent() / parallel() / pipeline() でサブタスクをファンアウト、最後に結果を返す | 大量タスク、固定構造、実行順の精密制御が必要(例:ドキュメント 10 件を一気に分析) |
ralph | 各ラウンドで新サブエージェントに差し替え同じ目標を推進、各ラウンド終了時に次のラウンドへの引継ぎレポートを書く | 多ラウンド改良、ループに陥りやすい、創造的またはデバッグ系タスク |
ralph はデフォルトでオン(subagent は spawn を使用、最大 64 ラウンド)。workflow はデフォルトでオフ —— そのスクリプトは別スレッドで動き、「オーケストレーション制約」であってセキュリティサンドボックスではないため、明確なバッチシナリオでのみオンにする価値があります。
::: tl;dr 日常の並列 → subagent; 前の結論から続けたい → subagent_fork; 構造化バルク → workflow(デフォルトオフ); ループに陥らない反復改良 → ralph。 :::
よくある落とし穴
| 落とし穴 | 避け方 |
|---|---|
| 複数サブエージェントが同時に同じファイルに書く | 並列タスクは読み取り(検索、分析、レビュー)を優先;書きはメインエージェントに全結果を集めて 1 回で書かせる |
| 指示に「全部終わるまで待つ」を書き忘れた | 派遣時に待機機構を含める、ないとメインエージェントが中途半端な結果で作業を始める |
| タスクを細かすぎに分割 | 各サブエージェントには起動オーバーヘッドがある;5 分のタスクを 10 サブエージェントに分けると実際には遅くなる;「独立して意味のある 1 ことを完遂する」単位まで分割 |
| サブエージェントが無限ネスト | 委譲深度に上限あり(デフォルト 3、0 で禁止);「メインエージェント → サブエージェント」のスター型トポロジが最も安定 |
この章で学んだこと
下の項目を自力で達成できれば合格です:
- [ ] 単一 Agent の長いタスクの 3 つの難所を言え、マルチ Agent のコア価値(文脈隔離)を言える
- [ ] サブエージェントもプラグインであることを知っている:
ctx.subagentsが委譲契約、spawn / fork が最もよく使う 2 つのバックエンド - [ ]
subagent(全新文脈)とsubagent_fork(親セッションの完了履歴付き)を区別できる - [ ] 「タスク分割 + 全完了待機 + 結果マージ」の並列サブエージェントを少なくとも 1 回走らせ、軌跡でサブエージェント呼び出しを見た
- [ ] フォアグラウンド、バックグラウンド Job、continuable サブエージェントモードの違いを言える
- [ ]
workflow、ralph、send_message、interrupt_agent、list_agentsがそれぞれ何をするか知っている
