Chapter 9

第9章: 計画とサブエージェント ── 骨組みと分岐

小さな頼みごとは、もう驚くほど器用にこなす。 「fibonacci.py のバグを直して」── 3 ステップで的確に直ってくる。

ところが、こう頼んだとたんに様子がおかしくなる。

「認証まわりをまるごとリファクタして、テストも通しておいて」

最初の 1 ファイルは丁寧に直す。 ところが途中から、関係ないファイルを開き始める。 気づくと「修正完了しました」と言い切って戻ってくるが、テストは赤いまま

小さな仕事はできる。大きな仕事になると、急に迷子になる。

同じ LLM、同じ道具、同じハーネス。何が足りないのか。

9.1 そもそも、ループだけだと「次の一手」しか考えない

第3章で見た think → act → observe の三拍子は、エージェントの強みの源泉だった。 やりながら考える。ためしてから直す。──「先に完璧な計画を立てる」よりも、現代のコーディングエージェントは やりながら考える ほうが向いている、と書いた。

ただし、ここには 見落とされがちな性質 がひとつある。

ループは、毎ターン “目の前の一手” を生成しているだけだ。

ループ自体には、「全体としてどこを目指していて、いま何合目にいるか」を見渡す機構が組み込まれていない。

小さなタスクならこれで十分だ。次の一手がそのままゴールに直結する からだ。 ところが大きなタスクではこうはいかない。

「認証まわりをリファクタ」 = ① モデル層を直す → ② リポジトリ層を直す → ③ サービス層を直す → ④ ルーター層を直す → ⑤ テストを直す → ⑥ 動作確認

各ステップが終わらないと次に進めない。6 個の手を、順序を守って、しかも全体像を見失わずに 打つ必要がある。 ここで「次の一手」しか見ていないループは、よくこんな失敗をする。

これは 全体俯瞰の不在 から来る病だ。

人間のエンジニアは、複雑なタスクに着手するとき、手を動かす前にメモを書く。 TODO リストでも、ホワイトボードでも、付箋でも構わない。

「① → ② → ③ の順でやる、いま①」と 外に書き出すからこそ 、途中で脇道に逸れても戻ってこられる。 エージェントにも、同じ仕掛けが要る。

9.2 解決策 ── 計画と実行を分離する

ここでぶっきらぼうな解決策が出てくる。

そもそも、考えるフェーズと、動くフェーズを分けてしまえばいい。

エージェントに、まず 計画だけ立てさせる。手は出させない。 その計画を人間(あるいはエージェント自身)が眺めて、納得できたら 実行フェーズに切り替える。実行中は計画を参照して、脇道に逸れたら計画に戻る。

ループだけ (素のエージェント)think → act → observe毎ターン “次の一手” を考える全体像を持たないまま動き続ける→ 大きなタスクで脇道に逸れる無関係な関数を直し始める途中で何の話か見失うテストを動かさず完了宣言よくある失敗モード計画と実行を分離① 計画フェーズ道具を封じて、計画だけ立てる② 実行フェーズ計画を見ながら手を動かす承認(人間 or 自動)必要なら書き換え脇道に逸れても計画に戻れる
図 9.1 — ループだけのエージェント (左) と、計画 → 実行を分けたエージェント (右)。後者は計画を外部メモとして持つので、途中で道に迷いにくい。

これは要するに、ループの上にもう一段「計画」というレイヤーを差し込む ことだ。 ハーネスは、計画フェーズの間は Write / Edit / Bash のような副作用ツールを通さない。LLM は「Read で調べて、自然言語で計画書を出す」ことしかできなくなる。 承認されてはじめて、実行モードに切り替わる。

「先に骨組みを書く」が効くのは、脱線防止・進捗の見える化・停止判断の明確化 ── 三つを同時に手に入れられるからだ。

  • 脱線防止: 計画と外れたことをやり始めても、計画を読み直せば戻れる
  • 進捗の見える化: 残りの作業が外に書き出されているので、人間も LLM 自身も俯瞰できる
  • 停止判断の明確化: 「計画の全項目が終わったか?」で止めどきを決められる

9.3 プロダクトでの実装 ── Plan モードと TodoWrite

「計画と実行を分ける」という同じ発想は、各プロダクトで少しずつ違う形で現れる。

Claude Code は二段構えだ。

計画ツール (TodoWrite 系)

LLM が複雑なタスクに取りかかるとき、やることリストを明示的なテキストとして書き出す ための専用ツール。書いた瞬間に、そのリストは LLM 自身のコンテキストに残り、次のターン以降の判断材料になる。Claude Code の TodoWrite、Cursor のチェックリスト表示、Aider の TODO 注釈などが同じ系譜。

CursorCodex CLI にも、似た仕掛けがある。明示的な「モード切り替え」を持たないものもあるが、システムプロンプトの中で「複雑なタスクではまずプランを書き出してから着手しろ」と指示することで、同じ動きを誘導している。 Devin のように、ジョブを受け取った直後に Plan を Slack に投稿してから実行に入る タイプもある。

実装の表面は違うが、骨は同じだ。「ループの上に、計画というもう一段のレイヤーを置く」 こと。

ここで重要な気づきがある。 計画フェーズで生成される計画書は、ハーネス側が解釈する特殊な構造ではなく、ただの自然言語のテキスト であることが多い。

なのに、なぜ書かせるだけで挙動が改善するのか?

それはテキストとして書かれた瞬間、その計画は LLM 自身の以降のコンテキストに乗る からだ (第7章のコンテキストウィンドウの話)。書かれていないものは、次のターンには思い出せない。 「考えたら書く」だけで、自己レビュー・記憶・俯瞰が一度に手に入る ── これが計画ツールの不思議な威力の正体だ。

9.4 計画は書き換える前提で運用する

「計画を立てるなら最初に完璧に立てるべき」── そう思いたくなる。 だが現代のエージェントの設計は、その逆を行く。

計画は実行中に書き換えてよい。むしろ書き換える前提で設計されている。

実装に入ってから「あ、このファイル構造、想定と違った」「思ったよりリポジトリ層が密結合だった」と気づくことは普通にある。 そのとき LLM は、TodoWrite を呼んで サブタスクのリストを書き換える。途中までの進捗はそのままに、残りのステップを現実に合わせて差し替える。

これは ── ループだけのエージェントが脇道に逸れていく挙動とは、似ているようでまったく違う

計画なしで脇道に逸れる計画を更新して進む
無関係なファイルを触り始める関連ファイルが想定外に多いと気づき、リストに足す
何をやっていたか忘れる残りのサブタスクを参照して戻ってくる
「完了しました」で打ち切る残ったサブタスクを意識して、次に進む

両者の差は 「外部にメモがあるかどうか」 だけ。メモがあれば現実とのズレを反映して進める。なければ、ズレに呑まれて脇道に消える。

ここまでが、ループに 骨組み を入れる話だ。続いて、ループに 分岐 を入れる話に移る。

9.5 ループの中にループを呼ぶ ── サブエージェント

もう一度、最初のシーンに戻ってみる。

「認証まわりをまるごとリファクタして」── 計画を立てて 6 段のサブタスクに切ったとしても、まだ問題が残ることがある。 たとえばこんなとき。

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

計画を立てて順に処理すること自体はできる。だが調査が後半に進むにつれて、最初の方のパッケージの調査結果がコンテキストに居座り続け、机の上が散らかっていく (第7章で扱った文脈の物理)。 気づくと、12 個目の調査は最初の方に比べて記述がやせ細っている。

ここで誰かが思いつく。

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

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

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

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

仕掛けは拍子抜けするほどシンプルだ。 Claude Code でいえば、サブエージェントの正体は Task という名前のツールを呼んだだけ ── つまり第5章の function calling と何も変わらない。

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

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

ループの中にループを呼ぶ ── 再帰的な発想だが、構造は単純だ。

9.6 親子ループの絵 ── 三つのご利益

親と子のループを並べて描くと、こう見える。

親ループ机は軽いまま子ループ A「packages/a を調査」独立コンテキスト15 回ツール呼び子ループ B「packages/b を調査」独立コンテキスト22 回ツール呼び子ループ C「packages/c を調査」独立コンテキスト18 回ツール呼び親に返るのは「結論テキスト 3 本」だけ
図 9.2 — 親ループと、入れ子になった子ループたち。子の中の試行錯誤は親には見えない。親の机に乗るのは結論だけ。

ここから、サブエージェントの 三つのご利益 が見える。

ご利益 1: コンテキストの隔離 子の中で 30 回ツールを呼ぼうが、20 ファイル読もうが、親の机には何も増えない。返るのは結論のテキスト 1 本だけ。 長いタスクで品質が落ちる主因は、第7章で見たコンテキストウィンドウの圧迫だった。サブエージェントは、その圧迫を 構造で回避 する道具だ。

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

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

シーケンシャルに「a → b → c」と回すより、所要時間が ほぼ 1/N になる (API レート制限の範囲で)。

ご利益 3: 専門化 ここまでは「同じ Claude を分身させる」話だった。もう一歩進むと、役割ごとに違うシステムプロンプトと違う道具セット を渡したくなる。

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

Claude Code の /agents コマンドや、プロジェクトの .claude/agents/ 配下に専門エージェントを定義しておけば、親は「code-reviewer でこの変更を見て」と一言指示するだけでよくなる。

実務メモ

よくある誤解として、「サブエージェントは別モデルが走っている」と思っている人がいる。 プロダクトによる が、Claude Code の現状の挙動を見るかぎり、親と同じ LLM を別のループで回しているだけ であることが多い。賢さの源泉は別モデルではなく、「別コンテキスト・別システムプロンプト・別道具セット」という 環境の違い にある。

9.7 サブエージェントの代償 ── 親はサブの中を直接見ない

サブエージェントは万能ではない。最大の代償は 透明性の喪失 だ。

子の中で:

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

落とし穴

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

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

実務上の対策はいくつかある。

つまりサブエージェントは「便利な万能分身」ではなく、「親の机を散らかさずに済む代わりに、中で何が起きたかは諦める」 という設計上の取引きとして使う道具だ。

9.8 計画とサブエージェントは、同じ系譜の発明

最後にもう一度、本章の二つの仕掛けを並べておく。

仕掛け何を入れた?効くしくみ
計画 (Plan / TodoWrite)ループの に「考える層」を入れた全体像を外部メモにしてループに参照させる
サブエージェント (Task)ループの に「別ループ」を入れた重い文脈を別の机に逃がして、親を軽く保つ

向きは違うが、どちらもループに対して「もう一段の構造」を導入する という点で兄弟だ。 平坦なループのままでは、文系・他分野エンジニアの読者が最初に驚いた「動く」体験はできても、大きな仕事に挑むと必ず破綻する

計画とサブエージェント ── この二つは、ループに 骨と分岐 を入れて、大きな仕事に耐えうる形へ進化させる発明だった。

私は最初、Plan モードは「面倒な確認ステップ」だと思っていた。早く動かしたいのに、なぜわざわざ計画を読まされるのかと。 ところが何度も使っているうちに、計画フェーズで提示された TodoWrite のリストを眺める数十秒が、実行中に発覚する大事故を防ぐ最大の保険 だと分かってきた。

サブエージェントも同じだ。最初は「並列で速い」が嬉しいが、本当のご利益は 親の机が散らからない こと。長い仕事を任せたエージェントが、最後まで集中力を保ってくれる ── この体感は、コンテキスト圧迫の苦しみを一度味わった人にしか分からない。

二つとも地味な機構なのに、体感を一段引き上げる 不思議な発明だ。

9.9 この章の振り返り

この章で読めるツイート / ブログ

次章ではいよいよ本書のクライマックスに入る。 ここまで積み上げてきたループ・道具・文脈・計画・サブエージェント ── 全部を組み上げてもなお残る、三大病 と、それを抑える最後の砦としての HITL の話だ。