大きな問題を新たに起動した agent に任せる
「Process isolation gives context isolation for free.」子 agent が泥仕事をこなし、親 agent はきれいな summary だけを受け取る。
親 agent のジレンマ
Claude Code に「この10万行の Rust リポジトリがどのように並行処理を扱っているか調べて」と頼んだとしよう。直感的なアプローチ:自分で ls、cat、grep してメインコンテキストで一通り検索する。
問題:この探索で messages[] に30件ほどの tool_result が積み上がり、各件が数千 token にのぼる。いざ回答を書き始めるころには、コンテキストは探索の過程で埋め尽くされている——あと数ステップで上限に達し、回答は散漫になる。
s04 の解決策:探索タスクを新しい agent に丸投げする。新しい agent は messages=[] から起動し、自分のペースで探索して、最後にsummary だけを親 agent に返す。親のコンテキストに増えるのは「task ツールを一回呼んだ、結果は XXX」の一行だけ——すっきりしている。
def run_subagent(prompt: str) -> str: sub_messages = [{"role":"user", "content": prompt}] # 新しい context for _ in range(30): # 安全上限、暴走防止 response = client.messages.create(..., messages=sub_messages, tools=CHILD_TOOLS, ...) ... # 最後のテキストだけ返す、中間の推論はすべて破棄 return "".join(b.text for b in response.content if hasattr(b, "text"))
親子コンテキストの比較
この widget は実際のタスク「このリポジトリで deprecated API を使っている箇所をすべて列挙する」をシミュレートする。2つの戦略で実行できる:(A) 親 agent が自分で行う、(B) subagent を spawn する。最終的な2つのコンテキストのサイズを左右で比較しよう。
CHILD_TOOLS:子 agent が使えるツール
s04 の実装で見落としやすい細部がある:子 agent はtask ツールを持っていない。
# 子 agent は基本ツールのみ、孫を spawn できない CHILD_TOOLS = [bash, read_file, write_file, edit_file] # 親 agent には task ツールが追加されている PARENT_TOOLS = CHILD_TOOLS + [task]
なぜか?再帰的な spawn がツリー状に爆発するのを防ぐためだ。subagent がさらに4つの sub-subagent を spawn し、それを繰り返すと、あっという間に数十の並行呼び出しが走り、token と API のレート制限の両方が崩壊する。s04 の約束:spawn はフラットで、親→子の一層だけ。Claude Code の実装もこれに倣っている——Task tool の中から Task tool を呼ぶことは禁止されている。
見えること・見えないこと
責任の整理:以下の問いについて T(正しい)か F(間違い)かを考えよう。