「もし、調査の途中で Claude が脱線せず、最後まで一気に走り切ってくれたら便利だと思いませんか?」
Claude Code を使い込むほど、私は同じパターンで詰まるようになりました。
「認証周りのファイルを 5 つ読んで」「テストを走らせて」「失敗したログを grep して該当箇所を抜き出して」と、ひとつのセッション中に作業の毛色が違うものを次々と頼みます。最初のうちは順調です。しかし 1 時間も経つと、Claude の返事が少しずつ怪しくなります。
「そういえば最初に頼んだ作業はなんでしたっけ?」
「先ほど読んだログでは、ええと…」
context window(Claude が一度に頭に入れていられる情報量の上限)の半分が、もう参照しない grep の結果や test の出力で埋まっている。残りの半分で本来やりたいことを進めようとして、Claude もこちらも、だんだん薄味になっていきます。
これは Claude のせいではありません。全部を一人で抱えさせているこちらの設計の問題です。
この記事では、その違和感の正体と、Anthropic が用意した処方箋である Subagents(サブエージェント)について書きます。
問題の立て方が間違っている
「いらない情報をどう context から追い出すか?」と考えている時点で、たぶん問題の立て方が違います。
正しい問いはこうです。
「専門タスクを誰にやらせるか?」
メインの会話を「自分」、Claude を「優秀なアシスタント」と捉えると、/compact でメモを整理させたり、長文を要約させたりという発想になります。これは間違っていませんが、まだ一人芝居です。
Subagent は、メインの会話とは 別の context window で動く専門家 です。メインから「これ調べておいて」と投げると、別部屋で作業し、終わったら 最終レポートだけが戻ってくる。途中の grep 結果も、読み込んだ大量のコードも、向こうの部屋に置きっぱなしです。
前回の記事で扱った Skill が「同じプロンプトを 3 回コピペしている自分」への処方箋だったのに対し、Subagent は 「同じ専門家ロールを 3 回呼んでいる自分」 への処方箋です。
| 道具 | 切り出す対象 | 呼ぶ単位 |
|---|---|---|
| Skill | 手順(プロンプト) | 文字列を context に追加 |
| Subagent | 人(context window と権限を持つ実行単位) | 別 context で実行し要約だけ返す |
進化させるべきは Claude の記憶力ではなく、仕事の振り分け方 です。
なぜ「全部メインに置く」と壊れるのか
Claude Code の context window は有限です。システムプロンプト、CLAUDE.md、現在のファイル、過去のやり取り、ツール結果がすべてここに積まれます。
ここに「結果は要らないのに proof of work(作業証跡)が大きい」タスクが混ざると、後半の判断品質が一気に落ちます。grep で 200 件ヒットした結果、テストランナーが吐いた 1,000 行のスタックトレース、find . -name '*.ts' の数千ファイル一覧。これらは「次の判断のために 1 行の要約」が欲しいだけなのに、生のままメインに残ってしまう のが致命的です。
公式 docs はこの問題を直球で書いています(公式 docs “Create custom subagents”)。
“Use one when a side task would flood your main conversation with search results, logs, or file contents you won’t reference again: the subagent does that work in its own context and returns only the summary.”
「サイドタスクが、もう参照しない検索結果・ログ・ファイル内容でメイン会話を埋め尽くしそうなときに使ってください。サブエージェントは自分の context でその作業を行い、要約だけを返します。」
ここで起きていることを図にするとこうです。
sequenceDiagram participant U as ユーザー participant M as メイン会話<br/>(自分の context) participant S as Subagent<br/>(別 context) U->>M: 「テストを走らせて失敗箇所を抜き出して」 M->>S: Agent ツールで委譲<br/>(指示と必要な context だけ渡す) Note over S: 別の context で<br/>npm test 実行<br/>1,000 行のログを読む<br/>失敗テストを特定 S-->>M: 「失敗 3 件: A, B, C<br/>原因は X」<br/>(要約のみ) M->>U: 「失敗 3 件あります...」
メイン会話に積まれたのは「失敗 3 件: A, B, C / 原因は X」だけ。1,000 行のログは Subagent の context で消費され、戻ってきません。これが context を守るための基本設計です。
ここから先は Subagent との付き合い方を 2 つの道に分けて 整理します。
- Part 1: まず built-in を使い倒す ─ Claude Code に最初から入っている専門家を呼ぶ話
- Part 2: 同じロールを 3 回呼んだら自作する ─ 自分のリポ用の専門家を作る話
ほとんどのケースは Part 1 だけで片付きます。Part 2 が必要になるのは「同じ専門家を 3 回呼んだ」と気づいた瞬間からです。順に行きます。
Part 1: まず built-in を使い倒す
自分でファイルを書く前に、Claude Code には すでに使える Subagent が同梱されている ことを知っておきましょう。Part 1 は自作なし、コマンド 0 行、設定 0 行で始められる話だけです。
公式の built-in を把握する
公式 docs の Built-in subagents セクション を読むと、メインタブで紹介されているのは次の 3 つです。
| 名前 | モデル | ツール | 用途 |
|---|---|---|---|
Explore | Haiku | 読み取り専用(Write, Edit 不可) | コードベース探索・grep・ファイル発見 |
Plan | メイン会話を継承 | 読み取り専用 | plan モード中のリサーチ |
general-purpose | メイン会話を継承 | 全ツール | 探索+実装が必要な複雑タスク |
これに加えて、同 docs の “Other” タブに statusline-setup と claude-code-guide の 2 つが記載されています。コミュニティの整理(shanraisshan/claude-code-best-practice の subagents 表)では、これら 5 つを「Official 5」としてまとめています(執筆時点)。
呼び分けの目安はシンプルです。
| やりたいこと | 呼ぶべき built-in |
|---|---|
| 大量ファイルの探索・grep・「どこで使われている?」 | Explore |
| 実装に入る前のリサーチ | Plan(plan モードに入れば自動委譲) |
| 探索しながら実装もする複合タスク | general-purpose |
私が日常で一番使うのは Explore です。「リポ全体から getUserById を呼んでいる箇所を全部洗い出して」というような 読むだけ・grep するだけ の依頼は、メイン会話で直接やるとファイル本体が次々と context に積まれます。代わりに
Explore subagent を使って、リポ全体で
getUserByIdを呼んでいる箇所をvery thoroughで洗い出して。
と頼むと、Explore が Haiku の速さで走り、戻ってくるのは「呼び出し箇所一覧と簡潔なコメント」だけです。メインの context は汚れません。
very thorough は Explore に渡せる 探索の徹底度(thoroughness level) の指定です。quick(限定的)/medium(バランス)/very thorough(包括的)の 3 段階があり(公式 docs “Built-in subagents”)、指定しなければ Claude が文脈から自動で選びます。「網羅性を優先してくれ」と明示したいときだけ付ければよく、Explore は Haiku で動くので very thorough でもメインで grep させるよりずっと速くて安いです。
罠1: なんでもメイン会話に詰め込む
「ちょっと grep するだけ」「テストを 1 回走らせるだけ」が積もります。1 セッションの後半、Claude が「最初の指示を整理させてください」と言い出したら、それは context が掃き溜めになっているサイン です。
判定はシンプルです。「これから Claude にやらせる作業の出力を、自分は後で読み返すか?」と自問する。読み返さないものは Subagent の仕事です。
罠2: 複雑なリサーチを一人でやらせる
「authentication と database と API の構成を一通り把握しておいて」とまとめて頼んだことがあれば、心当たりがあるはずです。メイン会話は 3 つの調査を直列でこなし、それぞれの中間メモが全部残ります。
公式 docs の “Run parallel research” にはっきり書かれています(公式 docs)。
“For independent investigations, spawn multiple subagents to work simultaneously.”
「独立した調査は、複数のサブエージェントを起こして同時に走らせます。」
具体的には次のように頼みます。
認証・データベース・API の 3 モジュールを、それぞれ別の Explore subagent で並列にリサーチして。各エリアにつき 1 段落で要約だけ返して。
3 つの Explore が並列で走り、メインには 3 段落の要約だけが戻ります。直列でやったときの 3 倍速で、context は 1/10 です。
呼び出しの 3 段階を覚える
サブエージェントは明示的に呼べます。公式 docs の “Invoke subagents explicitly” (明示的にサブエージェントを呼び出す) には 3 段階あります(公式 docs)。
- 自然言語で名前を出す: 「test-runner subagent を使って、失敗しているテストを直して」 ─ Claude が判断する
- @-mention(
@を打って候補から選ぶ呼び出し方): 「@”code-reviewer (agent)” 認証周りの変更を見て」 ─ 確実にその subagent が走る --agent <name>でセッション全体を subagent モードにする:claude --agent code-reviewer─ メインスレッド自体がその subagent の system prompt とツール制限と model を引き継ぐ
3 つ目はちょっと驚くと思いますが、公式 docs にはっきり書かれています。
“Pass –agent <name> to start a session where the main thread itself takes on that subagent’s system prompt, tool restrictions, and model”
「--agent <name>を渡すと、メインスレッド自体がその subagent の system prompt、ツール制限、モデルを引き継いだセッションが立ち上がります。」
「今日は code-reviewer モードで仕事する日」のような切り替えができるわけです。プロジェクトの .claude/settings.json に "agent": "code-reviewer" と書けば、そのプロジェクトの 全セッションのデフォルトが code-reviewer になります。
chain と parallel を使い分ける
複雑なワークフローでは、subagent を順番に呼ぶ(chain)か、並列に呼ぶ(parallel)かを意識します。
chain: code-reviewer で問題箇所を洗う → optimizer で直す parallel: 3 領域を 3 つの Explore で同時にリサーチ → メインで統合
公式 docs の “Common patterns” にある通り、chain は 依存関係がある作業 に、parallel は 独立した調査 に向きます(公式 docs)。
なお、公式 docs には警告も同居しています。
“Running many subagents that each return detailed results can consume significant context.”
「詳細な結果を返す subagent をたくさん走らせると、メイン会話の context を大量に消費します。」
並列で 5 つ走らせて、それぞれが 2,000 字の要約を返したら、メインに 10,000 字が一気に積まれます。並列度 × 1 件あたりの戻り量 で考えるのが安全です。
ここまでで Part 1 はおしまいです。built-in 5 つを呼び分けて、明示呼び出しと並列・直列を意識すれば、Subagent の効果の 8 割は出ます。残りの 2 割が「自作」の世界です。
Part 2: 同じロールを 3 回呼んだら自作する
Part 1 の built-in だけで多くは片付きます。では、いつ自作するべきか。同じ依頼パターンを 3 回投げたら、それは自作のタイミング です。
04 の Skill 記事では「同じプロンプトを 3 回コピペしたら Skill にする」と書きました。Subagent も同じ判定です。「コードを書き終えるたびに general-purpose に「コードレビューして」 を投げている」「テストが落ちるたびに Explore で grep して該当箇所を抜き出して を投げている」と気づいたら、専門家として独立させたほうが速いし、context も汚れません。
ここから先の 5 ステップは、最初の自作 subagent を作って育てる手順です。
ステップ1: 最小構成で動かす(公式の code-reviewer をコピー)
公式 docs の “Example subagents” にそのまま掲載されている、最小に近い実装です(公式 docs)。
.claude/agents/code-reviewer.md を作ります。
---
name: code-reviewer
description: コード品質・セキュリティ・保守性の専門レビュアー。コードを書いた直後/編集した直後に積極的に呼び出してください。
tools: Read, Grep, Glob, Bash
model: inherit
---
あなたはコード品質とセキュリティの高い基準を守る、シニアのコードレビュアーです。
呼び出されたときの動き:
1. git diff で直近の変更を確認する
2. 変更されたファイルに絞って読む
3. すぐにレビューを始める
レビューのチェックリスト:
- コードが明快で読みやすい
- 関数名・変数名が適切
- 重複コードがない
- エラーハンドリングが妥当
- シークレットや API キーがハードコードされていない
- 入力バリデーションが入っている
- テストカバレッジが十分
- パフォーマンス上の懸念に対処している
フィードバックは優先度別に整理して返してください:
- 致命的な問題(必ず修正)
- 警告(修正すべき)
- 改善提案(検討の余地あり)
修正方法の具体例も併記してください。これを git にコミットすれば、チーム全員が「コードを書き終えたら自動的にレビューが入る」状態になります。description に「コードを書いた直後/編集した直後に積極的に呼び出してください」と書いてあるので、Claude は実装後の流れで勝手に呼びにいきます(公式の英語例は 公式 docs “Example subagents” を参照)。
ファイルを置いただけだと、起動中のセッションには反映されません。公式 docs に注記がある通り、Subagent はセッション開始時に読み込まれる ので、追加・編集したら一度セッションを再起動するか、/agents 画面から登録すれば即時反映されます。
ステップ2: frontmatter は最初 3 フィールドだけでよい
公式 docs の Supported frontmatter fields を数えると、必須 2 フィールドと任意 14 フィールドで、合計 16 フィールド が用意されています(コミュニティの整理である shanraisshan の Frontmatter 表 でも同じ 16 フィールドが集計されています)。
最初から全部使う必要はありません。実用上は次の 3 つから始めます。
「公式の code-reviewer をコピーして、自分のリポに合わせて中身を直す」だけなら、name, description, tools の 3 つしか触りません。残り 13 は 必要が出てから足す で十分です。
flowchart LR F["frontmatter (16)"] --> A["必須 (2)<br/>name<br/>description"] F --> B["まず追加 (1)<br/>tools"] F --> C["挙動を変えたいとき<br/>model<br/>permissionMode<br/>maxTurns<br/>disallowedTools"] F --> D["別 context を持たせる<br/>skills<br/>mcpServers<br/>memory<br/>isolation"] F --> E["運用補助<br/>hooks<br/>background<br/>effort<br/>color<br/>initialPrompt"]
たとえば「この subagent は Haiku で十分」と判断したら model: haiku を足す。「Bash 経由で .git を触らせたくない」と思ったら disallowedTools: Write, Edit を加える。順番に育ててください。
ステップ3: description は「機能」ではなく「発火タイミング」で書く
自作 subagent でいちばん事故が起きやすいのが description です。「何ができるか」で書きがちで、これだと Claude は「いつ呼ぶべきか」を判断できません。
# 弱い description description: ファイルリファクタリングヘルパー
description は Claude が委譲のタイミングを見極めるための材料 だからです(公式 docs “Understand automatic delegation”)。
# 強い description description: コードレビューの専門家。コードの品質、セキュリティ、保守性を積極的にレビューします。コードを作成または変更した後はすぐに使用してください。
「積極的に」「すぐに使用してください」のように 発火条件と発火タイミング を入れておくと、Claude が自動委譲しやすくなります。
私たちが会話で書くプロンプトも、subagent の description も、日本語で構いません。Claude は description のキーワードを読み取って委譲タイミングを判断するので、「コードを書いた直後に呼んでください」のような日本語でも、英語の “Use immediately after writing code” でも、ちゃんと拾ってくれます。日本のチームで使うなら、レビュアー自身が読んで意味がわかる日本語にしておくほうがメンテしやすいです。
ちなみに自動委譲を期待しないケース(あえて手動で呼びたいとき)は、description から「積極的に」「すぐに呼んでください」のような発火フレーズを抜く、という調整もできます。
ステップ4: tools を必ず絞る(フックも合わせて)
frontmatter の tools を省略すると、その subagent は メイン会話のすべてのツールを継承 します(公式 docs “Available tools”)。
「ログを読むだけのつもりだった subagent が、なぜか Edit 権限も Bash も持っていて、勝手にファイルを書き換えた」という事故は、ここから生まれます。
絞り方は 2 通りです。
# 方法1: 許可リスト(allowlist)で絞る tools: Read, Grep, Glob, Bash
# 方法2: 拒否リスト(denylist)で全継承から削る disallowedTools: Write, Edit
両方を指定した場合、disallowedTools が先に適用され、その後 tools で残ったプールが絞られます。両方に書かれたツールは消されます(同じく公式 docs の “Available tools” に明記)。
私の運用ルールはこうです。読むだけの subagent は allowlist で必要最小だけ、作業もする subagent は denylist で危険なものだけ落とす。前者は事故率を下げ、後者は柔軟性を残します。
tools だけでは表現できない制御は PreToolUse フックで
「Bash がリストに入っているなら好き放題できるのでは?」と思うかもしれませんが、これに対する公式の答えが PreToolUse フック です。たとえば「DB に SELECT しか投げさせたくない」場合、公式 docs の “Database query validator” 例ではこう書かれています。
--- name: db-reader description: 読み取り専用のデータベースクエリ実行担当。データ分析やレポート生成のときに呼んでください。 tools: Bash hooks: PreToolUse: - matcher: "Bash" hooks: - type: command command: "./scripts/validate-readonly-query.sh" --- あなたは読み取り権限しか持たないデータベースアナリストです。データに関する質問には SELECT クエリだけで答えてください。書き込み系の操作は受けたら断ってください。
PreToolUse フックで指定したスクリプトが、Bash コマンドが実行される前に走ります。スクリプトは標準入力から JSON でコマンド内容を受け取り、INSERT / UPDATE / DELETE などが含まれていれば exit code 2 で止めます。
#!/bin/bash # ./scripts/validate-readonly-query.sh INPUT=$(cat) COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty') if echo "$COMMAND" | grep -iE '\b(INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|TRUNCATE)\b' > /dev/null; then echo "Blocked: Only SELECT queries are allowed" >&2 exit 2 fi exit 0
「Bash は許すが書き込み系は止める」という細かい制御は、tools だけでは表現できません。フックを噛ませることで初めて成立します。
ステップ5: 置き場所を選ぶ
Skill のときと同じ罠です。subagent には 5 つの置き場所があり、公式 docs の “Choose the subagent scope” に整理されています。
flowchart TD A[Subagent の置き場所] --> B["Managed settings<br/>(組織管理)"] A --> C["--agents CLI flag<br/>(当該セッションのみ)"] A --> D[".claude/agents/<br/>(プロジェクト)"] A --> E["~/.claude/agents/<br/>(自分の全プロジェクト)"] A --> F["plugin の agents/<br/>(plugin 配布先)"] B -.同名衝突時 1番強い.-> G["同名なら<br/>強いほうが勝つ"] C -.同名衝突時 2番.-> G D -.同名衝突時 3番.-> G E -.同名衝突時 4番.-> G F -.同名衝突時 5番.-> G
| 場所 | スコープ | 優先度 |
|---|---|---|
| Managed settings | 組織全体 | 1(最強) |
--agents CLI flag | 当該セッションのみ | 2 |
.claude/agents/ | プロジェクト | 3 |
~/.claude/agents/ | 自分の全プロジェクト | 4 |
Plugin の agents/ | plugin 配布先 | 5(最弱) |
チーム全員に同じ subagent を使ってほしいなら プロジェクト直下の .claude/agents/ に置いて、git にコミット します。これでリポジトリを clone した全員が同じ subagent を使えます。
~/.claude/agents/ に置くと、自分の全プロジェクトでは使えますが チームメンバーの環境には届きません。「いいレビュアー作ったよ」と Slack に流しても誰も使えません。
ついでに plugin の subagent には公式 docs に明示された制限があります(公式 docs の Note)。hooks, mcpServers, permissionMode の 3 フィールドは plugin から読み込むときに無視されます。プラグイン化する想定なら、この 3 つは別ファイルに分けて運用したほうが事故が減ります。
個人的告白
ここまで偉そうに書きましたが、私もまだ subagent を使い切れているとは言えません。Skill と subagent と main、どこで切るのが最適かは、毎週のように小さな移動を繰り返しています。
「これは subagent に切り出すか?」「いや、main で 1 回しか使わないから main で十分か?」「と思ったが 3 回目に呼んでいるな、もう subagent 化するか」と、行き来が続きます。
でも、ひとつだけハッキリしたことがあります。メイン会話のスクロールを 1 時間後に見返したくないと感じたら、それは subagent を使うべきだったサイン だということです。
専門家を呼べる人は、結局 1 人で全部やる人より速い。Claude Code でも、その当たり前は同じです。
TL;DR
Part 1: まず built-in を使い倒す
- 公式 docs に名前が記載されている built-in は少なくとも 5 つ ─ Explore / Plan / general-purpose(メインタブ)と statusline-setup / claude-code-guide(Other タブ)
- メイン会話で grep / テスト / 大量ファイル読みをしているなら、それは Subagent を使うサイン
- 独立した調査は parallel(複数 Explore を並列)、依存ありの作業は chain(順番に呼ぶ)
- 明示呼び出しは 3 段階: 自然言語 / @-mention /
--agentでセッション全体を切替
Part 2: 同じロールを 3 回呼んだら自作する
- 自作のサインは「同じ依頼パターンを 3 回投げた」とき
- frontmatter は 必須 2 + 任意 14 の合計 16 フィールド。最初は
namedescriptiontoolsの 3 つで十分 - description は「機能」ではなく 「発火タイミング」(「コードを書いた直後に呼んでください」など)で書く。日本語でも英語でも動く
toolsを省略するとメインの全ツールを継承。副作用ありなら必ず allowlist で絞る。細かい制御はPreToolUseフック- 配置: チーム共有は
.claude/agents/(git コミット)、個人は~/.claude/agents/、強制は managed settings
パイソンエンジニア部
