「この Task(...)、何を返してほしいか書いてある?」――Claude Code Agent で subagent を呼ぶ箇所が増えてくると、ある時点でレビューが詰まります。
vendor/ を触られても困る、token cap も書いてない、出力 format は「結果を報告して」レベル。1スキルあたり数個ある dispatch を、毎レビュー口頭で揃えるのは現実的ではないわけです。
playpark の Skills リポジトリでは Skill が70本を超えたタイミングでこの「dispatch ばらつき問題」が無視できなくなり、呼び出しプロンプトの必須要素を仕様化して lint で機械的に担保する という対処に切り替えました(口頭レビューに頼っていた頃の私たちにこれを見せたい)。本記事はその設計記録です。ベースは Anthropic が公開している Multi-agent research system の知見なので、汎用的に使えるはずです。
この記事で学べること
- Subagent 呼び出しで品質を決める 5つのプロンプト要素
- どの種類のタスクを どの subagent に投げるか の routing 表
- 全 SKILL.md を走査して 5要素を強制する lint の作り方
- 「token cap 未指定」が引き起こす実害と、その潰し方
前提:subagent は context isolation のための道具
「並列実行で速くなるやつ」と思われがちですが、実際は違います。Claude Code の Task tool はまず、メインセッションから別プロセスのエージェントを起動するための仕組みなのですが、呼び出した側のコンテキストに返ってくるのは subagent の最終出力だけ。途中の Read / Grep / WebFetch のログはメインに流れ込みません。
つまり subagent は「結果だけ欲しい・途中経過はメインに見せたくない探索や生成」を切り出すための道具なんですよね。並列実行はあくまで副産物で、まずこの context isolation を理解しておくのがおすすめです。
ただ、便利なぶん雑に呼ぶと痛い目に遭います。
雑な dispatch が壊すもの
5要素ルールを入れる前のリポジトリで実際に起きていたパターンを並べます。
| 症状 | 原因 |
|---|---|
| 重複作業 | Objective に「調べる」とだけ書く。終了条件が決まっていないので subagent は延々と探す |
| トークン浪費 | 「簡潔に」とだけ書く。語数上限を機械が解釈できない |
| 余計な書き込み | Tools の禁止指定がない。探索のつもりが Edit してくる |
node_modules/ 大爆発 | Boundary に除外が書かれていない。ヒット件数が膨らんで context があふれる |
| パース失敗 | Output format が「結果を報告して」レベル。返答を JSON.parse できない |
どれも「subagent が悪い」と思いきや、根は 呼び出しプロンプトの仕様不足 にあります。Anthropic の Multi-agent research system 解説でも、delegation 品質が成否の大半を決めると報告されているので、ここは正面から潰しに行く価値があります。
5要素ルール:必須プロンプト構造
playpark Skills では、Task / Agent / subagent_type を含む全ての SKILL.md に対して、以下5要素を プロンプト内に必ず含める ことを規約化しました。
1. Objective(単一の明確なゴール)
「X を調べる」ではなく、「Y が A か B かを判定する」「Z のリストを返す」と書きます。完了条件が自明であることが条件です。
- Good:
src/auth/配下でjwt.verifyを呼ぶ箇所を特定し、それぞれが try/catch で囲まれているか判定する - Bad: JWT の使い方を調べる
2. Output format(期待する構造)
JSON schema、Markdown のセクション構成、語数上限を明示します。これがないと、後段で結果を機械的に扱えません。
JSON: { files: [{ path, has_try_catch, line }] }
「結果を報告してください」だと、返ってくるものが毎回違います。同じ subagent に同じ依頼を二度投げて、別の体裁で返ってきた経験があるとこれは効きます(つまり、呼び出し側の指定不足)。
3. Tools(使用可能 tool と禁止 tool)
探索 heavy なタスクなら Bash / Write / Edit を明示的に禁止 します。副作用の余地を残さない、というのが運用上のコツです。
使用可: Read, Grep, Glob
禁止: Bash, Write, Edit, WebFetch
4. Boundary(触ってはいけない境界)
ファイルツリーの除外(vendor/, node_modules/, dist/)、git 操作禁止、ネットワーク禁止などを書きます。境界を書かないと、subagent は「気を利かせて」周辺を触りに行きます。
5. Token cap(トークン上限)
「簡潔に」は token cap ではありません(正直、これでうまくいくと思っていた時期がありました)。語数・件数・ファイル数のいずれかで 計測可能な上限 を書きます。
- 出力: 1500 語以内
- 最大探索ファイル数: 20
- ヒットは上位 10 件まで
実運用上、この5番目を入れた瞬間に dispatch あたりの平均 token 消費が目に見えて落ちました。逆に言えば、入れるまでは無自覚に垂れ流していたわけです。
呼び出しテンプレート
5要素を一発で書ける Markdown テンプレートを共通参照に置いて、各 skill から参照する形にしています。
Task(
subagent_type: "general-purpose",
description: "Short 3-5 word description",
prompt: """
## Objective
[単一の明確なゴール]
## Output format
[JSON schema / Markdown section / 語数上限]
## Tools
- 使用可: Read, Grep, Glob
- 禁止: Bash, Write, Edit, WebFetch
## Boundary
- 除外: vendor/, node_modules/, dist/
- 禁止: commit, git 操作, ネットワーク
- scope: <対象ファイル/ディレクトリ>
## Token cap
- 出力: 1500 語以内
- 最大探索ファイル数: 20
"""
)
このテンプレを _shared/references/subagent-dispatch.md に置き、skill-creator が新規 skill を作る時に Subagent Dispatch Rules セクションを自動で挿入する形にしました。新しい skill を書く人が「規約を知らない」状態を構造的になくす狙いです。
Routing:どのタスクをどの subagent に投げるか
5要素を満たしていても、種類の合わない subagent に投げると効率が落ちます。タスク性質ごとの推奨 routing を表にしてあります。
| タスク性質 | 推奨 subagent | 理由 |
|---|---|---|
| 探索 heavy(Read/Grep/Glob 多用、結果の summary だけ欲しい) | Explore agent または Haiku 系 | token 重い探索をメインから隔離 |
| 実装系(コード生成・編集・リファクタ) | general-purpose | バランス型、tool 制約が緩い |
| plan 系(設計・計画立案) | Plan agent | 推論品質を優先 |
| review 系(コードレビュー・critique) | code-reviewer agent | 批判観点の質 |
| 並列調査(複数仮説の同時検証) | general-purpose × N | 独立タスクの並列化 |
判断軸は4つだけ覚えておけば十分です。
- 出力が大きいか? → Yes なら Explore/Haiku に隔離して summary だけメインに戻す
- 副作用を伴うか? → Write/Edit/Bash を使うなら general-purpose
- 推論深度が重要か? → Yes なら Plan / code-reviewer
- 複数仮説を並列検証したいか? → Yes なら同一メッセージ内で複数 Task
なお Claude Code はサブスクリプション課金(Pro / Max)で、5時間あたりの利用枠を複数の subagent が消費します。「並列だから速い」は間違いではないのですが、general-purpose subagent(Sonnet)を 5並列で投げると、枠の溶け方も素直に5倍。「速くなったはずなのに 5時間枠が午前中で尽きた」となると、本末転倒ですよね。Routing は速度だけでなく、5時間枠を使い切らないための運用判断でもあります。
lint で機械的に担保する
ルールを文書に書いただけで本当に揃うかというと、どうなの? 現実は、レビューがゆるい日にしれっとすり抜けます。playpark Skills では tests/subagent-dispatch-lint.sh を入れて、CI の push / pull_request トリガーで全 SKILL.md を走査するようにしました。
検査項目はシンプルです。
- canonical reference (
_shared/references/subagent-dispatch.md) に5要素と routing 表があるか - skill 作成ガイドに5要素と routing 表があるか
- skill-creator のテンプレートに5要素と routing 表があるか
- 全 SKILL.md を走査し、
Task(/Agent(/subagent_typeのいずれかを含む skill は## Subagent Dispatch Rulesセクションと5要素を全て含むこと
4が肝です。「dispatch 構文を含むかどうか」で対象を自動検出するので、新規 skill が増えても lint 側の修正は不要です。
# 抜粋
mapfile -t ALL_SKILLS < <(
find "$REPO_ROOT" \
-type d \( -name node_modules -o -name .git -o -name _shared -o -name _lib \) -prune \
-o -type f -name 'SKILL.md' -print \
| sort
)
for skill_md in "${ALL_SKILLS[@]}"; do
if ! grep -qE '(Task\(|Agent\(|subagent_type)' "$skill_md"; then
continue
fi
# Subagent Dispatch Rules セクションと5要素の存在を検査
...
done
GitHub Actions の workflow は .github/workflows/lint.yml にまとめてあり、main / dev への push と pull request で走ります。違反があれば違反ファイル一覧を出して exit 1 になるので、PR は赤くなります。
規約導入の副作用:Skill のリファクタが進む
5要素ルールが入ったとき、いくつかの skill が lint で落ちました(最初は「ルールが厳しすぎたか?」と疑ったのですが、違いました)。直す過程で気づいたのは、5要素を素直に書こうとすると、もとの Skill のロジック自体が 「結局このタスクで何を返してほしいんだっけ?」を再定義する作業 になる、ということです。
たとえばある探索系 skill では、Objective を書こうとして「ここで欲しいのは file path のリストか、それとも違反箇所の判定か」が決まっていないことが露呈し、結果的にスキル本体の I/O 設計を整理することになりました。
つまり、委譲品質を整えると、それを使う側の責務も整うわけです。lint は単なるチェッカーではなく、Skill の I/O 設計を強制する道具 として機能していました。
まとめ
Claude Code Agent の subagent 委譲は、便利な一方で「呼び出しプロンプトのばらつき」が品質ボトルネックになります。playpark Skills では次の3つで構造的に揃えました。
- 必須5要素(Objective / Output format / Tools / Boundary / Token cap)をプロンプトに固定
- タスク性質ごとの subagent routing 表を canonical reference に置き、skill-creator から参照
- 全 SKILL.md を走査する lint で CI に組み込み、新規 skill にも自動で適用
レビューの口頭ガイドが lint と reference の更新で済むようになり、subagent 起因のトークン浪費も体感で減りました。委譲をスケールさせたい段階に来たら、5要素を「全 skill 共通の最低ライン」にするのが効くはずです。
リポジトリ全体の作りや他の skill との連携は、Skillsを「ポータブル資産」にする設計 と Skills設計パターン上級編 でも触れています。Claude Code Agent の使い分け論についてはAgent Teamで複数AIを並列協調させる設計もあわせてどうぞ。



