Claude Codeのサブエージェント並列実行—コスト管理と設計のハマりどころ

Claude Codeのサブエージェント並列実行—コスト管理と設計のハマりどころ | mohablog

サブエージェントを49個並列で走らせたら、1回のセッションで推定8,000〜15,000ドルの請求になった—海外コミュニティで報告されていた事例です。23個のサブエージェントで3日間に47,000ドルを溶かした話も流れてきて、読んだときは背筋が凍りました。

Claude Codeのサブエージェント機能は、使いこなせば開発効率が跳ね上がります。ただ「並列実行=速い」と安易に飛びつくと、コストやコンテキスト設計の面で大事故につながりかねません。半年ほど業務に投入してきた中で見えてきた、サブエージェントを壊さずに運用するための考え方を整理します。

検証環境はClaude Code 2.0.40、macOS Sonoma、Node 20系です。

目次

サブエージェントは普通のエージェントと何が違う?

コンテキストが親と分離している

サブエージェントの本質はコンテキスト分離にあります。親エージェント(メインで動いているClaude)がTaskツールでサブエージェントを起動すると、サブエージェント側は空のコンテキストウィンドウで立ち上がります。ファイル読み込みも検索結果もすべてサブエージェントの中で閉じていて、親には最後の要約だけが戻る仕組みです。

メリットは明白で、数百MBのログファイルを読ませたいときでも、親のコンテキストを汚さずに済みます。調査結果だけ要約して戻してもらえるので、親は次のタスクに進める。これが単体で走らせる普通のエージェントとの最大の違いです。

ツール権限を絞って起動できる

各サブエージェントはtoolsフィールドで使えるツールを明示できます。たとえばコードレビュー専用のサブエージェントにはRead/Grep/Globだけ持たせて、EditやBashは外す。これで「調べるだけのつもりだったのに勝手にファイルを書き換えられた」という事故を防げます。

権限を絞るという発想はセキュリティ設計の基本ですが、AIエージェントに対してこれを自然にかけられるのはサブエージェントの大きな魅力だと思います。

呼び出しは親エージェントが判断する

明示的に「code-reviewerサブエージェントで確認して」と指示する使い方もありますが、記述文(descriptionフィールド)をうまく書けば、親エージェントが自律的に「これはサブエージェントに委譲したほうがよさそう」と判断して起動してくれます。

公式ドキュメントによると、この自動ルーティングはdescriptionのマッチングで決まります。descriptionを曖昧に書くと呼ばれない、書きすぎると何でもかんでも呼ばれる、というバランスを取る必要があります。

サブエージェントを作る—.claude/agents/のYAMLフロントマター

プロジェクトスコープとユーザースコープの違い

サブエージェントはMarkdownファイルで定義します。配置先は2パターンです。

  • .claude/agents/: プロジェクトローカル。チームで共有したいならGitに乗せる
  • ~/.claude/agents/: 個人ユーザー用。すべてのプロジェクトで使える

同名のファイルがあった場合はプロジェクトスコープが優先されます。チームで使いたいものはリポジトリに、自分専用の便利エージェントはホームに、という分け方が素直です。

最低限書くべきフロントマター項目

まずアンチパターンから。以下はNGな書き方です。

---
name: reviewer
---

コードをレビューしてください。

これだと親エージェントが「このサブエージェントはいつ呼ぶべきか」を判断できず、ほとんど自動呼び出しされません。

最低限、以下の項目はそろえるべきです。

---
name: security-reviewer
description: Git差分のセキュリティレビューを実施。SQLインジェクション、XSS、機密情報漏洩の有無を確認する。コード変更があった後に呼ぶ。
tools: Read, Grep, Glob, Bash
model: sonnet
---

あなたはセキュリティレビュー専門のエージェントです。
与えられたGit差分に対して、OWASP Top 10に該当する脆弱性がないか確認してください。

出力形式:
- 検出した脆弱性: 該当ファイル:行番号 / 内容 / 深刻度(High/Medium/Low) / 修正案
- 問題なし: 「レビュー完了、問題なし」と返す

実行結果として、親エージェントが「コード変更があった」と認識すると、以下のようにサブエージェントを呼び出してくれます。

● Task(security-reviewer)
  ⎿  Done (4 tool uses · 12.3k tokens · 45s)

  検出した脆弱性:
  - api/users.py:42 / ユーザー入力を直接SQLクエリに連結 / High
    修正案: パラメータバインディングを使う
  - (以下省略)

toolsとmodelを指定して暴走を防ぐ

toolsを省略するとサブエージェントは親と同じツールをすべて使えます。便利ではあるのですが、レビュー専門のつもりが勝手にコードを書き換えた、というケースに遭遇したことがあります。最初は原因が分からず、ログを見返してやっと気づきました。

modelも重要で、常にOpusを使う必要はありません。軽量な調査タスクはHaikuやSonnetに振り分けることでコストは大きく変わります。後のセクションで詳しく扱います。

並列実行で速くなるケース・ならないケース

並列に向いている「独立した読み取り作業」

並列実行が活きるのは、タスク同士に依存関係がなく、かつ読み取りが中心のケースです。具体的には以下のようなものが該当します。

  • 複数のドキュメントやコードベースを横断して調査する
  • ログファイルの期間別分析(1月分と2月分を同時に)
  • 複数の観点からのコードレビュー(セキュリティ/パフォーマンス/可読性を並列で)

たとえばリポジトリの全体構造を把握したいとき、サブエージェント3つを「APIレイヤー担当」「DBレイヤー担当」「フロントエンド担当」として同時に起動すると、1つずつ順番に調べるより体感で3倍近く速くなります。

並列に向かない「書き込み・状態依存の作業」

並列に走らせてはいけないのは、書き込み系タスクや相互依存のあるタスクです。

  • 同じファイルを編集する可能性のあるリファクタリング
  • マイグレーションファイルの追加(ファイル名衝突のリスク)
  • 前段の結果が次段の入力になるパイプライン処理

書き込みタスクを並列にすると、マージ競合と「片方の変更が消える」系の事故が起きやすいです。書き込みは基本的に直列で走らせるほうが安全だと思います。

実測: 並列数は3〜5が現実的

「じゃあ並列にできるやつは全部並列にすればいいのか」というと、そうでもありません。10個並列で起動したプロジェクトで起きたのは以下のような現象です。

  • 親の要約処理がボトルネック化(10件の要約を順に処理して逆に遅い)
  • API側のレート制限に引っかかる
  • トークン消費が単純に10倍

公式ブログや海外コミュニティでの観測でも、同時実行3〜5個が現実的なラインとされています。6個以上並列にするときは、本当に必要か一度立ち止まったほうがいいです。

コスト暴走を防ぐ3つの設計ルール

ルール1: サブエージェント内で再帰的に呼び出させない

一番危険なのは、サブエージェントのシステムプロンプトに「必要に応じてさらにサブエージェントを起動して」と書いてしまうパターンです。

---
name: deep-investigator
description: 深い調査を実施する
tools: Read, Grep, Glob, Task
---

大規模な調査を行ってください。必要に応じてサブエージェントを並列起動し、結果を統合してください。

これを走らせると、サブエージェントがさらにサブエージェントを起動し、それらがまたサブエージェントを起動し…という指数関数的な増殖が起きます。冒頭の「49個起動」のような事例は、だいたいこのパターンが原因です。

対策はシンプルで、サブエージェントのtoolsからTaskを除外すること。

---
name: deep-investigator
tools: Read, Grep, Glob
---

実行結果として、サブエージェント内から追加のエージェント起動ができなくなり、連鎖的な増殖を構造的に防げます。

ルール2: 長時間タスクはmodelを下げる

サブエージェントのmodelフィールドで、使うモデルを個別指定できます。

タスク推奨モデル理由
大規模な設計判断・複雑な推論Opus精度が必要
コードレビュー・要約Sonnetコスト性能バランスが良い
ファイル検索・単純な分類Haiku速くて安い

「Opusで考え、Sonnetで動かす」という設計も一般化しつつあり、親エージェントだけOpus、下位のサブエージェントはSonnetに固定する運用は効率が良いです。

ルール3: 並列数の上限を明文化する

チームで使う場合、並列実行の上限をCLAUDE.mdなどに書いておくと事故が減ります。

# Claude Code運用ルール
- サブエージェントの並列起動は同時5個まで
- Taskツールは Plan系・Explore系のサブエージェントのみ付与
- ルート直下以外のディレクトリから起動しない

これとClaude CodeのCLAUDE.md設計 — チーム開発ルールを統一する仕組みで紹介したパターンを組み合わせると、チーム全体で安全な使い方に寄せられます。

Skills・スラッシュコマンドとの使い分け

3つの機能を比較表で整理

Claude Codeには似た「再利用ユニット」が複数あって紛らわしいです。ざっくり整理するとこうなります。

機能コンテキストツール権限向くユースケース
サブエージェント親と分離個別設定可判断・調査の委譲、並列実行
Skills親と共有親と同じドメイン知識の注入
スラッシュコマンド親と共有親と同じプロンプト定型化

コンテキストが分離するかどうかが、設計上もっとも大きな違いです。コスト観点でも、サブエージェントは親と別コンテキストを持つぶん「固定費」が高めで、軽い定型処理に使うとオーバーヘッドのほうが大きくなります。

サブエージェントが向くのは「判断を委譲したいとき」

経験的な指針として、サブエージェントが本領を発揮するのは以下のような場面です。

  • 結論を出すまでに大量のファイル探索・ログ読み込みが必要
  • 親コンテキストに戻したいのは「結論」だけで、過程は要らない
  • 複数の独立した観点を同時に処理したい

Skillsやコマンドで済むなら無理に使わない

逆に、以下のようなケースはSkillsやカスタムスラッシュコマンドで十分なことが多いです。

  • 毎回同じプロンプトを送りたい(コマンドで定型化)
  • 特定のドメイン知識やコーディング規約を読み込ませたい(Skills)
  • 数秒で終わる軽いタスク

選択の指針は「新しいコンテキストが必要か?」。必要ならサブエージェント、不要ならSkillsやコマンド。これが一番迷わない判断基準だと感じています。

実務でハマりがちなパターンと対処法

親に返ってくる結果が薄くて使えない

よくあるのが、サブエージェントの出力形式を指定しないまま呼び出して、「作業完了しました」レベルのふわっとした要約しか返ってこないケースです。

対策として、サブエージェントのシステムプロンプトに「出力形式」を明示しましょう。

---
name: log-analyzer
description: エラーログを分析して根本原因の候補を返す
---

出力形式は以下を厳守:
1. 発生頻度の高いエラー上位3件(時刻と件数)
2. 各エラーの推定原因
3. 確認すべきコードパス(ファイル:行番号)
4. 関連するスタックトレースの要約

実行結果として、親に戻る情報がかなり構造化されて、後続のタスクにそのまま使えるようになります。

1. 発生頻度の高いエラー上位3件
   - [14:32-14:45] DB connection timeout: 23件
   - [14:40-14:55] NullPointerException at UserService: 12件
   - [15:02-15:10] Redis timeout: 8件
2. 推定原因
   - DB接続プール枯渇の可能性。max_connectionsの設定を確認
   - UserService#findById のnullチェック漏れ
3. 確認すべきコードパス
   - src/services/user_service.py:87
   - config/database.yml

サブエージェントが同じファイルを同時編集して競合

並列実行で複数のサブエージェントに編集権限を持たせると、同じファイルに対する編集が競合して、あとから走った方の変更で前の変更が上書きされるケースがあります。

対策は2つあります。

  • 編集は親エージェントが担当し、サブエージェントは「編集案のテキストを返す」までに役割を限定する
  • どうしても並列編集したい場合は、サブエージェントごとに担当ファイルを事前に分割する

前者のほうが安全で、基本はこちらに倒すのがおすすめです。

並列デバッグが難しい—ログ設計で備える

3つのサブエージェントが並列で動いて、うち1つの出力だけが期待と違う—というとき、どのサブエージェントがどの判断をしたか追いにくいのは地味に痛いです。

対策として、サブエージェント内で重要な判断は必ずログに残す指示を入れておきます。

各ステップで、判断した内容と根拠を「[判断] ...」「[根拠] ...」の形式で出力してください。

実行結果として、並列の出力それぞれに判断プロセスが残り、あとから差分を追いやすくなります。

[判断] src/auth/login.py:45 の入力検証を優先で修正する
[根拠] CVSS Highのインジェクション脆弱性で、他のMedium指摘より先に対処すべき

並列実行の全体像を把握したい場合は、Claude Codeのコンテキスト管理術—トークン消費を抑える7つの工夫で触れたコンテキスト節約の考え方も合わせて参考にすると、トータルのトークン消費を抑えやすくなります。

まとめ

Claude Codeのサブエージェントは、使い所を見極めると開発体験を大きく変えてくれる機能です。一方で、何も考えずに並列実行するとコスト面でもコンテキスト管理でも大事故を起こします。

要点を整理するとこうなります。

  • コンテキスト分離が最大の特徴。親に戻すのは結論だけ
  • toolsでツールを絞り、Taskを付けると再帰起動のリスクがあるので扱いに注意
  • 並列実行は3〜5個が現実的。書き込み系タスクは基本直列
  • modelでコスト最適化。Opus固定は過剰、Sonnet/Haikuを使い分ける
  • 判断委譲が要るならサブエージェント、定型化ならコマンド、知識注入ならSkills
  • 出力形式を必ず指定。並列デバッグ対策にログ指示を入れておく

大規模な作業で時間を稼ぎたいときほど、設計に時間をかける—これがサブエージェントと付き合う上での基本姿勢だと思います。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次