Chapter 9

第9章: サブエージェント ─ コンテキストを分裂させる

ある朝、こんな指示を Claude Code に出してみる。

「この monorepo の 12 個のパッケージを順に調べて、依存関係の地図を作って」

しばらくして戻ってくると、最初の方のパッケージの分析は丁寧だが、後半に進むにつれて記述がやせ細っている。 最後にはこんな弁解が混じる ── 「context が長くなったので、残りは要約で済ませます」。

調査の品質が、残りトークン数の関数になっている。 人間がやれば、調べる対象ごとに新しいノートを開くだろう。 エージェントも同じことができる ── それが本章の主役、サブエージェント だ。

9.1 そもそも、なぜ「一人で全部やる」と詰まるのか

第4章で見たとおり、LLM の context window は有限だ。 入力 + 出力 + これまでの会話 + ツール結果が、すべて一つの帯に詰め込まれる。

長いタスクで何が起きるか:

長いタスクの最大の敵は「賢さ不足」ではない。“見ているものの多さ” だ。

人間でも、机の上に資料を 100 件積み上げた状態で意思決定はできない。 エージェントの限界も、ほぼ同じ場所に来る。

ここで素直に思いつくのが、こうだ:

「調査は別の Claude に任せて、結論だけ受け取れば、こっちの机は散らからない」

これがサブエージェントの動機だ。

9.2 サブエージェントの正体 ── 新しいコンテキストで動く別の Claude

サブエージェントは、難しい言葉でいうと「新しい LLM セッションを立ち上げ、別のシステムプロンプトと別のコンテキストで動かす仕組み」だ。

平たくいうと:

サブエージェント (sub-agent)

親エージェントから起動される、別コンテキストの Claude。親の会話履歴を引き継がず、ゼロから始まる新しいセッションを持ち、タスクを終えると 結論のテキストだけ を親に返す。親はサブの内部で起きたことを直接見ない。

ここで重要な誤解を一つ潰しておく。

サブエージェントは 別プロセス・別マシン で動いているわけではない。 親のループから見れば、サブエージェントは 「Task」という名前のツールを呼んだだけ だ。

ここで道具立てを一つ補足しておく。Claude Code には Task という名前のツール ── サブエージェント起動専用のツール があらかじめ用意されている (第6章のツール一覧でも顔を出した)。親はこの Task ツールを呼ぶことで、新しい Claude セッションを起動する。

つまり構造は単純で、第2章の function calling と何も変わらない:

  1. 親 Claude が「Task ツールを呼びたい (引数: 調査タスクの説明)」と出力する
  2. ハーネスがそれを受け取り、内部で新しい Claude セッション を起動する
  3. そのセッションが独立に think → act → observe を回す
  4. 結果テキストがハーネス経由で親に 「ツール実行結果」として 渡る
  5. 親はそれを観測して、続きを考える

サブエージェントは「魔法の並列処理」ではなく、親の agentic loop における一つの ToolCall に過ぎない。 特殊なのは、その ToolCall の中身が「ファイルを読む」ではなく「別の Claude を一回まるごと走らせる」ことだけ。

このシンプルさが、Claude Code の設計の良さでもある。

9.3 なぜ「コンテキストを分裂させる」と効くのか

サブエージェントの真価は、親の context を太らせない ことにある。

親の机の上に積まれるのは、サブが返した 最終結論のテキスト 1 本だけ。 サブが内部で 30 回ツールを呼んでいようと、20 ファイル読んでいようと、親の目には入らない。

親エージェントcontext: 軽いままsub-agent A「packages/a を調査」独立 context15 回ツール呼び出しsub-agent B「packages/b を調査」独立 context22 回ツール呼び出しsub-agent C「packages/c を調査」独立 context18 回ツール呼び出し親に返るのは「結論テキスト 3 本」だけ
図 9.1 — 並列起動されたサブエージェント。それぞれが独立した context を持ち、結論だけを親に返す。

机の比喩に戻ると、こうなる:

一人でやる場合サブエージェントに分ける場合
親の机に資料が 12 パッケージぶん積み上がる親の机には「12 件の要約レポート」だけ
後半にいくほど序盤の資料に圧迫されるサブはそれぞれ自分の机を持つので干渉なし
残りトークン量で品質が落ちるサブごとに新品の context window

これが context isolation の効能だ。

context isolation

親と子のコンテキストが完全に分離されていること。子の中の試行錯誤・失敗・大量のツール出力が、親の context window を圧迫しない。サブエージェントの最大の利点。

9.4 並列起動 ── 1 メッセージで複数 Task

サブエージェントの嬉しさは context 分離だけではない。

第2章で見たように、LLM は 1 回の応答で複数のツール呼び出しを並べる ことができる。 これをサブエージェント起動に応用すると、こうなる:

親 Claude の 1 メッセージに Task(packages/a 調査)Task(packages/b 調査)Task(packages/c 調査) の三つを並べる → ハーネスは三つの Claude セッションを 本当に並行起動 する → 結果が揃ったら、まとめて親に戻す

シーケンシャルに「a を調べる → 終わったら b → 終わったら c」と回すより、所要時間がほぼ 1/N になる (ネットワーク・API レート制限の範囲で)。

複数のドキュメントから情報を集める、複数のファイルに同じパターン修正を入れる、複数のテスト戦略を比較する ── これらは並列サブエージェントの典型的な出番だ。

逆に 「A の結果を見てから B を決める」 ような直列依存があるタスクは、並列にしても意味がない。設計するときは「依存関係があるか」を最初に問う。

9.5 専門エージェント ── 役割ごとに違う Claude を持つ

ここまでは「同じ Claude を分身させる」話だった。 もう一歩進むと、役割ごとに別の system prompt と別の道具セット を渡したくなる。

たとえば:

専門エージェント役割道具セット (例)
code-reviewerコード変更の品質と安全性をレビューRead、Grep、Glob (書き込み禁止 ── 詳しくは次章 permissions で)
explorerコードベースを探索して構造を地図化Read、Grep、Glob、Bash (読み取りのみ)
researcherWeb や社内ドキュメントから情報収集WebFetch、WebSearch
test-runnerテストを書いて走らせるRead、Write、Edit、Bash

それぞれに専用の system prompt を書いておけば、親は呼ぶときに code-reviewer でこの変更を見て」 と一言指示すればよい。 サブの中の Claude は、その役だけの心構えと道具 で考える。

これは人間のチームに似ている。 PM が全工程を一人でやる代わりに、レビュアー・調査担当・実装担当 に分ける ── 役の境界と道具の境界を明確にすると、それぞれが自分の仕事に集中できる。

エージェントの世界でも同じ原理が効く。「全部できる万能 Claude」より、「役を絞った専門 Claude」のほうが個別タスクでは強い ことが多い。

専門エージェントの定義は、ユーザー側の設定ファイル (詳細は第Ⅱ部「コマンド: 拡張機能」の /agents で扱う) や、プロジェクトの .claude/agents/ 配下に書いて共有できる。

9.6 リスク ── 親はサブの中で何が起きたか分からない

サブエージェントは万能の道具ではない。最大のリスクは 透明性の喪失 だ。

サブの中で:

これらは、親には 基本的に見えない。返ってくるのは結論テキスト一本だけだから。

落とし穴

サブエージェントは「親のデバッグ性を犠牲にして、context の節約と並列性を買う」トレードオフだ。

うまく仕事した時は嬉しい。だが結果が変だった時、原因究明は格段に難しくなる。 特に「サブが幻覚を含む結論を返し、親がそれを信じて次の手を打つ」と、エラーは見えない場所で連鎖する。

実務上の対策は、こうなる:

これは第10章 (権限とブラスト半径) の話と地続きで、取り返しのつかない操作はサブに任せない という原則につながる。

9.7 この章の振り返り

この章で読めるようになるツイート / ブログ

次章では、サブエージェントを含むすべてのエージェントが直面する別の問題に進む ── rm -rf を実行しようとした時、誰が止めるのか?」。 取り返しのつかない操作と権限の話、permissions の章だ。