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

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 を除くすべての基本ツールを持つ(再帰的な生成は不可)。
// 親 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();
  1. サブエージェントは新しい ChatClient で起動し、独立したコンテキストを持つ。最終テキストだけが親に返る。
@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() メソッド
戻り値 該当なし 要約テキストのみ

試してみる

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