◉CLAUDE LABEN
●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/Claude Code
⟐ Claude Code/2026-04-24中級

Claude Code のサブエージェントが結果を返さない時の診断手順

Claude Codeのサブエージェントが結果を返さない・止まったように見えるときの診断フローです。症状を分類する最初の3つの質問、ツール呼び出しの無限ループ、エラーが親に伝わらないパターン、出力スキーマの不在による内容ズレ、.claude/agents/のリロードまでコード例つきで解説します。

claude-code132subagent4troubleshooting61debug4

Claude Code のサブエージェントを本格的に使い始めると、必ずと言っていいほど遭遇するのが「いつまで経っても結果が返ってこない」「ログには何も出ていないのに処理が止まっている」という状況ではないでしょうか。最初は何が起きているのか見当もつかず、とりあえず Ctrl+C で中断するしかありません — 私もそうでした。

サブエージェントは便利な機能ですが、親エージェント側から見ると一種のブラックボックスになりがちです。ここでは、実際に何十回と詰まりながらたどり着いた「どこから調べるか」の判断フローを、症状ごとに整理して共有します。

症状で分類する — 最初の3つの質問

闇雲にログを眺めても時間を失うだけです。まずは次の3つを自問してください。

  • サブエージェントは すぐに終わっている か、動きっぱなし か
  • 出力はある か、何も出ていない か
  • 親側に エラーが伝わっている か、サイレントに止まっている か

この3軸で症状を分けると、原因の候補が一気に絞れます。

  • 即終了 × 出力なし × エラーあり → プロンプトや権限が不足している可能性
  • 長時間稼働 × 出力なし × エラーなし → ツール呼び出しループや、コンテキスト逼迫
  • 終了済み × 出力あり × エラーなし → プロンプト解釈のズレ
  • 長時間稼働 × 出力あり × エラーなし → 親側でのストリーム処理の不備

ログを見る前にやること — 状態を保存する

診断に入る前に、現在のセッション状態を壊さないように保存します。復旧してから「再現しなくなった」では原因が追えません。

# セッションログを追記監視で開く(診断中も保存され続ける)
tail -f ~/.claude/logs/session-$(date +%Y%m%d)*.log > /tmp/cc-debug.log &
 
# 実行中のサブエージェント関連プロセスを確認
ps aux | grep -E "claude-(agent|code)" | grep -v grep
 
# 親エージェント側の現在の conversation を JSON に書き出す
claude --export-conversation /tmp/cc-conv.json

この状態を取った上で、はじめて /subagent stop <name> で停止してください。取らずに停止すると、なぜ止まっていたかの痕跡がまとめて消えます。

パターン1: 「動いているが何も出ていない」 — ツール呼び出しの無限ループ

経験上、最も多いのがこのパターンです。サブエージェントが同じツールを何度も呼び出して、親側から見ると「動いているけど進んでいない」ように見えます。

セッションログで次のように同じツール呼び出しが連続していたら確定です。

[subagent:tester] -> Bash: "npm test"  (turn 7)
[subagent:tester] -> Bash: "npm test"  (turn 8)
[subagent:tester] -> Bash: "npm test"  (turn 9)

原因は多くの場合、サブエージェントが 失敗の分析プロセスを持っていない ことです。テストが失敗したのに、原因を特定する前にもう一度同じテストを実行してしまう。対策はプロンプト側で「失敗時は原因を3つ列挙してから次の手を決める」と明示し、max_turns を 15 程度に制限することです。

---
# .claude/agents/tester.md
name: tester
tools: Bash, Read
max_turns: 15
---
 
あなたはテスト実行サブエージェントです。以下の手順を守ってください。
 
1. テストを1回だけ実行する
2. 失敗した場合、失敗したテスト名と原因の仮説を3つ列挙する
3. 検証可能な仮説を1つだけ選び、コードを読んで裏を取る
4. 修正すべき箇所が見つかったら「修正提案」セクションに記述する
5. 同じテストを再実行する前に、必ず「なぜ前回失敗したか」を書く

max_turns を指定しておけば、ループに入っても15ターンで強制終了します。ログに max_turns reached と出た場合、ツール呼び出しのループが起きていたことが確定します。

パターン2: 「いつの間にか終わっている」 — エラーが親に伝わらない

サブエージェント内で起きたエラーが、親エージェントから見ると「正常終了」に見えることがあります。たとえばファイル書き込みに失敗したのに、サブエージェントが最終出力として「完了しました」とだけ返してしまうケースです。これは文字通りサイレント障害で、気づくのが翌日ということもあります。

対策は、サブエージェント側で 構造化された終了レポート を必須にすることです。親のプロンプトに次のような制約を書いておきます。

{
  "status": "success | partial | failed",
  "files_modified": ["src/utils/retry.ts"],
  "tests_passed": true,
  "unresolved_issues": [],
  "next_action_recommended": "..."
}

「最終出力は必ずこのJSON形式で、どれか1つでも欠けたら失敗扱いにする」と明示すれば、曖昧な「完了しました」を信じる必要がなくなります。失敗した作業があった場合は status を "partial" または "failed" とし、unresolved_issues に具体的な問題を列挙させます。

親側では status を機械的に判定できるため、オーケストレーション全体の信頼性が一段上がります。

パターン3: 「結果は返るが内容がズレている」 — 出力スキーマの不在

サブエージェントが何かを返すものの、親が期待する形ではない場合、原因はほぼ確実にプロンプトが「何を返すか」を指定していないことです。

対策は2つあります。

  1. サンプル出力を1つ以上示す。説明ではなく実例で示した方が、解釈のブレが劇的に減ります
  2. 親側でバリデーションを走らせる。期待したスキーマに合わなければ、1度だけリトライする設計にします
// 親エージェント側の擬似コード
const result = await runSubagent('refactor-agent', task);
const parsed = tryParseJSON(result);
 
if (!parsed || !parsed.status) {
  // スキーマ違反 — 欠けているフィールドを具体的に伝えてリトライ
  return await runSubagent('refactor-agent', {
    ...task,
    retry_reason: 'status フィールドが欠けています。必ず前回示したJSON形式で返してください',
  });
}
 
// リトライは1回だけ。それ以上は設計を疑う段階
return parsed;

リトライを無制限にすると、今度は無限ループの原因になります。1回に制限するのがコツです。

それでも動かないとき — .claude/agents/ のリロード

設定ファイルを変更したのに挙動が変わらない場合、サブエージェント定義がキャッシュされている可能性があります。

# agent 定義のキャッシュをクリア(開発中は毎回やって損はない)
rm -rf ~/.claude/cache/agents/
 
# 念のためセッションを新規作成する
claude --new-session

より踏み込んだ制御を設計するなら、Claude Code サブエージェントのオーケストレーション で複数エージェント構成時の役割分担を扱っています。長時間セッションでコンテキストが壊れるケースは 長時間セッションのコンテキスト保全 と、ツール連鎖が詰まるケースは Claude Code Hooks の本番デバッグ手法 と組み合わせて読むと、症状から原因への道筋が短くなります。

個人開発で Dolice Labs の自動投稿をサブエージェントに任せていたとき、私自身いちばん消耗したのが、この「返ってこない」沈黙でした。エラーが出れば調べようがありますが、無言で止まると原因の当たりすらつきません。max_turns と終了レポートの構造化を入れてからは、少なくとも「どこで止まったか」が必ず残るようになりました。

次に試すこと

今日の作業で詰まっているサブエージェントがあれば、まずは max_turns を定義ファイルに追加してください。これだけでループ起因の「戻ってこない」症状の大半は可視化できます。

そこまで終わったら、次は終了レポートをJSON構造化するところまで進めてみてください。出力のフォーマットが固定化されるだけで、「何が起きているか分からない」状況そのものが起きにくくなります。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

⟐ Claude Code2026-05-24
Claude Code で連続する Edit が連鎖的に失敗するときの直し方 — old_string が消える・重複する問題
Claude Code が同じファイルへ Edit を連続で投げると、2件目以降が突然『not found』や『not unique』で落ちることがあります。原因は順序依存とコンテキスト二重化で、Read 再実行と分割パッチで救えます。
⟐ Claude Code2026-05-10
Claude Code の Glob と Grep が0件を返すときの原因切り分け
Claude Code の Glob/Grep ツールがファイルを見つけられないとき、.gitignore除外・隠しファイル・パターン記法の落とし穴を切り分け、適切な代替手段で確実に発見する手順をまとめます。
⟐ Claude Code2026-05-10
Claude Code の Read が大きなファイルを最後まで読まないとき — PARTIAL view の受け取り方と offset / limit の設計
Read が大きなファイルを途中までしか返さないとき、Claude Code は PARTIAL view の通知を出しています。通知の受け取り方と、行数ではなくバイト予算で offset / limit を決める方法を、実測値とともにお伝えします。