3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Codeのサブエージェントを作ってみて分かったこと

3
Posted at

目的

Claudeの記事を色々見ていると、「エージェント同士でやり取りし、人間は最初の指示を出すだけであとは全部Claudeがやってくれる」という事例を見かけました。自分もこれを実現したいと思い、実装用とレビュー用のサブエージェントを作成しました。

指示を出すだけでClaude同士がやり取りし、実装からレビューまで完了させてくれる状態を目指した記録です。

1. サブエージェントとは何なのか

サブエージェントとは、メインの会話とは別に、独立したコンテキストウィンドウで動作する特化型のAIアシスタントです。

サブエージェントを使うことで、以下のようなメリットが得られます。

  • メインの会話コンテキストを消費せずに調査や実装を行える(コンテキストの節約)
  • レビューなど役割を特化させ、今までのやりとりに引きずられずに評価ができる
  • 軽量なモデルを指定して処理させることでコストを抑えられる

また、Claude Codeにはあらかじめ組み込みのサブエージェントが用意されています。
代表的なものは以下の3つです。

エージェント モデル トリガー(呼ばれるきっかけ) 用途
Explore メイン会話から継承 Claudeがコードベースの検索・理解が必要と判断したとき 高速な読み取り専用のコードベース探索
Plan メイン会話から継承 プランモード中、実装前にコードベースを理解する必要があるとき 計画立案のための調査(読み取り専用)
general-purpose メイン会話から継承 探索と実装の両方が必要な複雑なマルチステップタスクのとき 複雑な調査・複数ステップの操作・コード変更

自分で定義したサブエージェントのことは「カスタムサブエージェント」と呼びます。

2. 作成するにはどうしたらいいのか

カスタムサブエージェントは、Markdownファイルのフロントマター(メタデータ)と本文(システムプロンプト)で構成されています。

フロントマターの主なフィールド

フィールド 必須 内容
name 小文字とハイフンの一意な識別子
description Claudeがこのサブエージェントに委譲するかどうかの判断材料
tools - 使用を許可するツール(省略時は全て継承)
disallowedTools - 使用を禁止するツール
model - sonnet / opus / haiku / inherit など(デフォルトはinherit)
permissionMode - default / acceptEdits / plan など
maxTurns - 停止するまでの最大ターン数
skills - 起動時にプリロードするスキル
mcpServers - このサブエージェント専用のMCPサーバー
hooks - ライフサイクルフック(PreToolUse等)
memory - 永続メモリのスコープ(user/project/local)
isolation - worktreeにするとgit worktreeで分離実行

必須なのはnamedescriptionだけで、他は省略可能です。特にdescriptionは、メインスレッドが「このタスクはこのサブエージェントに任せるべきか」を自動判断する材料になるため、具体的に書くほど誤発火を防げます。

今回は、実装を担当するjava-developerと、そのレビューを担当するjava-reviewerの2つを作成しました。想定していた流れは以下の通りです。

指示を出す(私) → 実装(java-developer) → コミット(java-developer) → PR作成(java-developer)
→ レビュー(java-reviewer) → 指摘修正(java-developer) → マージ(java-reviewer)

3. 作成したけどうまくいかなかった

作成したサブエージェントを使って、こう指示を出しました。

未実装の箇所を洗い出し実装を進めてください。

すると、java-developerサブエージェントは使ってくれたものの、そこで止まってしまい、レビューへの受け渡しは行われませんでした。結局、「次はレビューして」と自分で指示を出す必要があり、想像していた「指示は最初の一回だけ」という理想になりませんでした。

原因を調べていくうちに、これは単に「フローを書き忘れていた」からではなく、サブエージェントの仕組み上そもそもできないと分かりました。

サブエージェントは、他のサブエージェントを呼び出す権限を持ちません(無限に入れ子になるのを防ぐための仕様上の制約です)。

つまり、java-developerの中に「実装が終わったらjava-reviewerを呼んで」と書いたとしても、java-developer自身がjava-reviewerを起動することはできません。進行管理(オーケストレーション)は常にメインスレッドが担う必要があった、というのが本当の原因でした。

4. サブエージェントについて知識を得た結果わかったこと

調べていく中で、サブエージェントを使うべき場面・避けるべき場面について整理できました。

使うべき場面

  • メインの会話の文脈に引きずられず「まっさらな目」で評価してほしいとき(例:実装者とは別コンテキストでのコードレビュー)
  • お互いが触るファイルが重複せず、独立して進められるとき(例:3つの独立したAPIを同時に実装する)
  • 構造化されたワークフローの一部として使うとき(例:調査→計画→実装のように段階が分かれており、メインスレッドが進行管理役に徹し、各段階を割り振る設計にできる場合)

使わないほうがいい場面

  • タスクが単純・日常的で、メインの会話でそのまま片付く
  • 1つの機能の実装を、レイヤー単位(Entity/Service/Controllerなど)で複数サブエージェントに分割する。サブエージェントは互いの成果物を直接参照できないため、分割するとメインスレッドが「Aの成果物をBに伝える」という橋渡しを逐一行う必要が生じ、かえってコストが増える
  • サブエージェントの仕組みを理解していない

「指示一回だけ」に近づけるには

私がやりたかった「一回の指示で最後まで完了する」を実現するには、サブエージェント側に書くのではなく、メインスレッドにオーケストレーションの指示を書く必要がありました。

まとめ

  • サブエージェントは独立したコンテキストで動く特化型アシスタントで、コンテキストの節約・役割の特化に向いている
  • サブエージェント同士は直接やり取りできない。進行管理は常にメインスレッド側の仕事
  • 「指示一回で最後まで」を実現したいなら、サブエージェントの中身ではなく、メインスレッド側のオーケストレーション設計を作り込む必要がある
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?