# v3: サブエージェント機構 **約450行。+1ツール。分割統治。** v2で計画を追加。しかし「コードベースを探索してから認証をリファクタリング」のような大きなタスクでは、単一のエージェントはコンテキスト制限に達する。探索で20ファイルが履歴にダンプされる。リファクタリングで集中を失う。 v3は**Taskツール**を追加:分離されたコンテキストで子エージェントを生成。 ## 問題 単一エージェントのコンテキスト汚染: ``` メインエージェント履歴: [探索中...] cat file1.py -> 500行 [探索中...] cat file2.py -> 300行 ... さらに15ファイル ... [リファクタリング中...] 「あれ、file1の内容は?」 ``` 解決策:**探索をサブエージェントに委任**: ``` メインエージェント履歴: [Task: コードベースを探索] -> サブエージェントが20ファイルを探索 -> 返却: "認証はsrc/auth/、DBはsrc/models/" [クリーンなコンテキストでリファクタリング] ``` ## エージェントタイプレジストリ 各エージェントタイプが能力を定義: ```python AGENT_TYPES = { "explore": { "description": "検索と分析のための読み取り専用", "tools": ["bash", "read_file"], # 書き込みなし "prompt": "検索と分析。変更しない。簡潔な要約を返す。" }, "code": { "description": "実装のためのフルエージェント", "tools": "*", # すべてのツール "prompt": "効率的に変更を実装。" }, "plan": { "description": "計画と分析", "tools": ["bash", "read_file"], # 読み取り専用 "prompt": "分析して番号付き計画を出力。ファイルを変更しない。" } } ``` ## Taskツール ```python { "name": "Task", "description": "集中したサブタスクのためにサブエージェントを生成", "input_schema": { "description": "短いタスク名(3-5語)", "prompt": "詳細な指示", "agent_type": "explore | code | plan" } } ``` メインエージェントがTaskを呼び出す → 子エージェントが実行 → 要約を返す。 ## サブエージェント実行 Taskツールの心臓部: ```python def run_task(description, prompt, agent_type): config = AGENT_TYPES[agent_type] # 1. エージェント固有のシステムプロンプト sub_system = f"You are a {agent_type} subagent.\n{config['prompt']}" # 2. フィルタリングされたツール sub_tools = get_tools_for_agent(agent_type) # 3. 分離された履歴(重要: 親コンテキストなし) sub_messages = [{"role": "user", "content": prompt}] # 4. 同じクエリループ while True: response = client.messages.create( model=MODEL, system=sub_system, messages=sub_messages, tools=sub_tools ) if response.stop_reason != "tool_use": break # ツールを実行、結果を追加... # 5. 最終テキストのみを返す return extract_final_text(response) ``` **重要な概念:** | 概念 | 実装 | |------|------| | コンテキスト分離 | 新しい`sub_messages = []` | | ツールフィルタリング | `get_tools_for_agent()` | | 専門化された振る舞い | エージェント固有のシステムプロンプト | | 結果の抽象化 | 最終テキストのみ返却 | ## ツールフィルタリング ```python def get_tools_for_agent(agent_type): allowed = AGENT_TYPES[agent_type]["tools"] if allowed == "*": return BASE_TOOLS # Taskなし(デモでは再帰なし) return [t for t in BASE_TOOLS if t["name"] in allowed] ``` - `explore`: bashとread_fileのみ - `code`: すべてのツール - `plan`: bashとread_fileのみ サブエージェントはTaskツールを取得しない(このデモでは無限再帰を防ぐ)。 ## 進捗表示 サブエージェント出力はメインチャットを汚染しない: ``` あなた: コードベースを探索して > Task: コードベースを探索 [explore] コードベースを探索 ... 5ツール, 3.2秒 [explore] コードベースを探索 - 完了 (8ツール, 5.1秒) 見つかったものはこちら: ... ``` リアルタイム進捗、クリーンな最終出力。 ## 典型的なフロー ``` ユーザー: "認証をJWTを使うようにリファクタリング" メインエージェント: 1. Task(explore): "認証関連のすべてのファイルを見つける" -> サブエージェントが10ファイルを読む -> 返却: "認証はsrc/auth/login.py、セッションは..." 2. Task(plan): "JWT移行を設計" -> サブエージェントが構造を分析 -> 返却: "1. jwtライブラリを追加 2. トークンユーティリティを作成..." 3. Task(code): "JWTトークンを実装" -> サブエージェントがコードを書く -> 返却: "jwt_utils.pyを作成、login.pyを更新" 4. 変更を要約 ``` 各サブエージェントはクリーンなコンテキストを持つ。メインエージェントは集中を保つ。 ## 比較 | 側面 | v2 | v3 | |------|----|----| | コンテキスト | 単一、増大 | タスクごとに分離 | | 探索 | 履歴を汚染 | サブエージェントに含まれる | | 並列性 | なし | 可能(デモにはなし) | | 追加コード | 約300行 | 約450行 | ## パターン ``` 複雑なタスク └─ メインエージェント(コーディネーター) ├─ サブエージェントA (explore) -> 要約 ├─ サブエージェントB (plan) -> 計画 └─ サブエージェントC (code) -> 結果 ``` 同じエージェントループ、異なるコンテキスト。これがすべてのトリック。 --- **分割統治。コンテキスト分離。** [← v2](./v2-構造化プランニング.md) | [READMEに戻る](../README_ja.md) | [v4 →](./v4-スキル機構.md)