You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
claude-code/docs/ja/s04-subagent.md

102 lines
4.7 KiB

# s04: Subagents (サブエージェント)
`s01 > s02 > s03 > [ s04 ] s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
> *"大きなタスクを分割し、各サブタスクにクリーンなコンテキストを"* -- サブエージェントは独立した messages[] を使い、メイン会話を汚さない。
>
> **Harness 層**: コンテキスト隔離 -- モデルの思考の明晰さを守る。
## 問題
エージェントが作業するにつれ、messages 配列は膨張し続ける。すべてのファイル読み取り、すべてのコマンド出力がコンテキストに永久に残る。「このプロジェクトはどのテストフレームワークを使っているか」という質問は5つのファイルを読む必要があるかもしれないが、親エージェントに必要なのは「pytest」という一言だけだ。
## 解決策
```
Parent agent Subagent
+------------------+ +------------------+
| messages=[...] | | messages=[] | <-- fresh
| | dispatch | |
| tool: task | ----------> | while tool_use: |
| prompt="..." | | call tools |
| | summary | append results |
| result = "..." | <---------- | return last text |
+------------------+ +------------------+
Parent context stays clean. Subagent context is discarded.
```
## 仕組み
1. 親エージェントに `task` ツールを持たせる。子は `task` を除くすべての基本ツールを持つ(再帰的な生成は不可)。
```java
// 親 Agent: 基本ツール + SubagentTool を持つ
this.chatClient = ChatClient.builder(chatModel)
.defaultSystem("You are a coding agent. "
+ "Use the task tool to delegate subtasks.")
.defaultTools(
new BashTool(),
new ReadFileTool(),
new WriteFileTool(),
new EditFileTool(),
new SubagentTool(chatModel) // 親 Agent 専用
)
.build();
```
2. サブエージェントは新しい `ChatClient` で起動し、独立したコンテキストを持つ。最終テキストだけが親に返る。
```java
@Tool(description = "Spawn a subagent with fresh context. "
+ "Use for exploration or subtasks that might pollute the main context.")
public String task(
@ToolParam(description = "The task prompt") String prompt,
@ToolParam(description = "Short description", required = false)
String description) {
// 新しい ChatClient を作成 -- これが「コンテキスト隔離」のすべて
ChatClient subClient = ChatClient.builder(chatModel)
.defaultSystem("You are a coding subagent. "
+ "Complete the task, then summarize findings.")
.defaultTools( // 基本ツール、task なし(再帰防止)
new BashTool(),
new ReadFileTool(),
new WriteFileTool(),
new EditFileTool()
)
.build();
String result = subClient.prompt()
.user(prompt)
.call()
.content();
// 最終テキストだけを返し、子 Agent のコンテキストは破棄
return (result != null) ? result : "(no summary)";
}
```
サブエージェントは複数回のツール呼び出しを実行するかもしれないが、メッセージ履歴全体は破棄される。親が受け取るのは要約テキストだけで、通常の `tool_result` として返される。Spring AI の `ChatClient.call()` が内部でツールループを管理するため、手動でイテレーション回数を制限する必要はない。
## s03 からの変更点
| コンポーネント | 変更前 (s03) | 変更後 (s04) |
|----------------|------------------|---------------------------------------|
| Tools | 5 | 5 (基本) + SubagentTool (親側のみ) |
| コンテキスト | 単一共有 | 親 + 子隔離 (独立した ChatClient) |
| Subagent | なし | `SubagentTool.task()` メソッド |
| 戻り値 | 該当なし | 要約テキストのみ |
## 試してみる
```sh
cd learn-claude-code
mvn exec:java -Dexec.mainClass=io.mybatis.learn.s04.S04Subagent
```
以下のプロンプトを試してみよう (英語プロンプトの方が LLM に効果的だが、日本語でも可):
1. `Use a subtask to find what testing framework this project uses`
2. `Delegate: read all .java files and summarize what each one does`
3. `Use a task to create a new module, then verify it from here`