「調べ終わりました」。サブエージェントを走らせた画面には、そう読める文章が並びます。ところが、子が実際に目を通した量と、親の手元に残った量は同じではありません。
親へ返るのは、子が書いた最終テキストの要約です。開いたファイルの中身も、途中で引っかかった例外も、要約に選ばれなければそこで消えます。消えたという事実は、画面のどこにも出ません。
この記事は、サブエージェントの結果統合で情報が落ちる地点を特定し、統合を確定させる前に止めるところまでを扱います。素材は2026-08-02時点のClaude Code公式ドキュメントの記載です。
こんなふうに調べていませんか
- 並列で走らせた結果を1つにまとめたが、抜けが無いと言い切れない
- 子のログを見に行きたいが、どこに何が残るのかを知らない
- 検査は書いた。ただ、走らせ忘れたときに気づく方法がない
この記事を読み終えたときに手に入るもの
- 結果統合で情報が落ちる地点を、公式仕様の裏付きで説明できるようになります
- 件数と事実の両方を突き合わせる検査を、自分の手で書けるようになります
- 欠落したままの統合を、実行前に止める仕掛けが手に入ります
結論30秒でわかる、この記事の結論
- 親へ返るのは要約です。子が読んだ内容そのものではありません。
- 落ちる地点は分かっているので、確保・突合・遮断の順に手を打てます。
- 件数の一致は入口の条件にすぎず、事実が消えたことは件数には現れません。
聞き手は、入社2年目でそもそもから確かめたい若葉さんと、自分の手で動かしている高梨課長です。答えるのは鈴木さん(本誌監修)です。
01サブエージェントの結果統合を検証しないと、何が消えるんですか?
若葉さん子のエージェントが「調べ終わりました」と返してきたら、その中身は全部、親に渡っているんですよね。
鈴木さんそこは伝言ゲームに近いと思っています。読んだ人が要点だけを口で伝えるので、伝えなかった部分は、はじめから無かったことになります。
サブエージェントは、任せた分だけ働きます。ただし親へ返るのは、子が書いた最終テキストの要約です(出典: Claude Code公式ドキュメント「sub-agents」)。
公式ドキュメントの例示では、子が読んだファイルは6,100トークン分でした。親へ戻る結果は420トークンです(出典: 同「context-window」)。ドキュメント自身が代表的な数値だと注記しており、いつもこの比になるわけではありません。
それでも、約14分の1まで縮む例が公式に載っているという事実は動きません。縮んだぶんに何が入っていたかは、親からは見えないままです。
本記事で扱うのは、次の3つです。
- 情報が落ちる地点を、公式仕様の裏付きで特定する
- 統合の前に、子の生データを確保して件数と事実を突き合わせる
- 欠落したままの統合を、SubagentStopフックで止める
サブエージェントの基本設計はサブエージェント設計|委譲の線引きと3つの失敗で、定義ファイルの書き方はClaude Codeサブエージェント定義|渡る情報4点と権限の絞り方で扱っています。本記事はその先、結果を受け取ったあとだけに絞ります。
02サブエージェントに任せた情報は、どの地点で落ちるんですか?
前提となる検証環境は、Claude Code公式ドキュメント(sub-agents・hooks・context-window、2026-08-02時点の記載)です。落ちる地点は、次の4つに整理できます。
| # | 地点 | 何が起きるか | 出典 |
|---|---|---|---|
| 1 | 要約による圧縮 | 子は作業の全部ではなく、最終テキストの要約だけを親へ返す | 公式ドキュメント(sub-agents) |
| 2 | ネストした子の二重要約 | 孫エージェントの結果は中間の子で一度要約され、その要約だけが親へ届く | 同上 |
| 3 | 並列本数によるコンテキスト逼迫 | 詳細な結果を返す子を大量に走らせると、親側のコンテキストを消費する | 同上 |
| 4 | APIエラーによる打ち切り | レート制限や過負荷で子が途中終了すると、そこまでの出力しか戻らない | 同上 |
情報を圧縮して保持する設計は、結果統合に限った話ではありません。スキル本文の再注入も、1スキルあたり5,000トークン、合計25,000トークンを超えると、古いものから落とされます(出典: 同上)。
この4つを、気づき方の側から並べ直すと、表では見えないものが出てきます。数を数えれば分かるのか、中身を照らさないと分からないのか。この2軸に置くと、片方の区画が空になります。
空くのは「数では分かるのに、中身を照らしても見えない」区画です。数が合わないなら、中身の側にも同じ欠けが出るからです。
つまり数の一致は、中身の突き合わせに含まれてしまいます。数だけを見て安心すると、いちばん起こりやすい落ち方である要約の圧縮を、丸ごと見送ることになります。
この章のまとめ
件数の一致は、統合してよい理由にはなりません。事実が消えたかどうかは、件数の側には現れないためです。
03AIエージェントの生データは、結果統合の前にどこで確保するんですか?
高梨課長消えたかどうかを確かめるには、消える前のものが要りますよね。それはどこに残っているんでしょう。
鈴木さん子ごとに別のファイルが残ります。親の会話が圧縮されても、そちらは影響を受けない作りです。ただ、置きっぱなしにはできません。
Claude Codeは、サブエージェントが完了すると、そのエージェントIDを親へ渡します(出典: Claude Code公式ドキュメント)。生データは~/.claude/projects/{project}/{sessionId}/subagents/以下に保存され、ファイル名はagent-{agentId}.jsonlです。
まず、実際に何本のtranscriptが存在するかを数えます。
# 公式ドキュメントで示されている保存パターンに沿って数える
ls ~/.claude/projects/<project>/<sessionId>/subagents/ \
| grep -c '^agent-.*\.jsonl$'この値が、統合前チェックで使う「受領できた結果の数」になります。
| 項目 | 値・仕様 | 出典 |
|---|---|---|
| 保存パス | ~/.claude/projects/{project}/{sessionId}/subagents/ | Claude Code公式ドキュメント |
| ファイル名 | agent-{agentId}.jsonl | 同上 |
| 既定の保持期間 | 30日(cleanupPeriodDays) | 同上 |
| エージェントIDの入手経路 | サブエージェント完了時に親へ渡される | 同上 |
| メインの会話が圧縮されても | transcriptは別ファイルのため影響を受けない | 同上 |
保持期間があるので、確保には期限があります。検証は完了直後に回すか、必要な行だけを先に別の場所へ写します。複数体を並列で使う構成でも、この手順はそのまま当てはまります。
04件数と事実は、サブエージェントの結果統合の前にどう突き合わせるんですか?
突き合わせは2種類です。1つは件数、もう1つは事実そのものです。
transcriptの内部フォーマットは1行1JSONの会話ログですが、行ごとのキー構成は公開されていません。そこでキー名を決め打ちにせず、各行の文字列値をすべて拾って正規表現にかける実装にします。
import json, re, sys
from pathlib import Path
NUM = re.compile(r"\d+(?:,\d{3})*(?:\.\d+)?\s*(?:%|件|本|秒|分|回|体|トークン|層|日)")
PATH = re.compile(r"[\w./-]+\.(?:py|md|json|jsonl|ya?ml)")
def walk_strings(obj):
if isinstance(obj, str):
yield obj
elif isinstance(obj, dict):
for v in obj.values():
yield from walk_strings(v)
elif isinstance(obj, list):
for v in obj:
yield from walk_strings(v)
def extract_facts(text):
return set(NUM.findall(text)) | set(PATH.findall(text))
def facts_in_transcript(path):
facts = set()
for line in path.read_text().splitlines():
try:
obj = json.loads(line)
except json.JSONDecodeError:
continue
for s in walk_strings(obj):
facts |= extract_facts(s)
return facts
if __name__ == "__main__":
transcripts_dir, final_doc = Path(sys.argv[1]), Path(sys.argv[2])
dispatched = int(sys.argv[3])
final_text = final_doc.read_text()
files = list(transcripts_dir.glob("agent-*.jsonl"))
print(f"dispatched={dispatched} transcripts_found={len(files)}")
for f in files:
missing = facts_in_transcript(f) - extract_facts(final_text)
if missing:
print(f"{f.name}: MISSING {sorted(missing)}")このスクリプトは、子の生データにあった数値・件数表現・ファイルパスのうち、まとめ上げた文章に一度も出てこないものをMISSINGとして並べます。数が消えた場合だけでなく、事実が消えた場合も同じ経路で拾えます。
この章のまとめ
件数は「そろったか」を見る道具、事実の突合は「中身が残ったか」を見る道具です。役割が違うので、片方がもう片方の代わりにはなりません。
05数が合わないとき、AIエージェントはサブエージェントの起動そのものに失敗しているんですか?
出力の形は次のようになります(値は架空で、形式だけを示します)。
dispatched=4 transcripts_found=4
agent-a1b2c3.jsonl: MISSING ['3層', 'settings.json']dispatchedとtranscripts_foundが食い違うときは、統合を始める前に理由を特定します。同時実行上限(既定20体)やセッション累計上限(既定200体)に達すると、新規の起動自体が失敗します(出典: Claude Code公式ドキュメント)。この場合の食い違いは、起動できていない子がいるというサインになります。
たとえるなら、朝礼の点呼です。名簿に載っている人数がdispatched、実際に並んだ人数がtranscripts_foundにあたります。ここが食い違っているなら、まだ探す段階で、持ち物を確かめる段階ではありません。
数がそろったら次へ進みます。ただしそれは「全員が帰ってきた」ことの確認であって、「全員が手ぶらではない」ことの確認ではありません。
06サブエージェントの結果統合を、検証し忘れないようにするにはどうするんですか?
手で走らせるかぎり、実行し忘れる余地が残ります。そこで、子が完了するSubagentStopイベントに検査を載せます(出典: Claude Code公式ドキュメント「hooks」)。
{
"hooks": {
"SubagentStop": [
{
"matcher": "vault-researcher",
"hooks": [
{ "type": "command", "command": "./scripts/check_result_integration.sh" }
]
}
]
}
}matcherにはサブエージェントのnameを指定します。フックはJSONを標準入力で受け取り、agent_id・agent_type・last_assistant_messageなどのフィールドを含みます(出典: 同上)。
#!/bin/bash
INPUT=$(cat)
LAST_MSG=$(echo "$INPUT" | jq -r '.last_assistant_message // empty')
if ! echo "$LAST_MSG" | grep -q '^RESULT_COUNT:'; then
echo '{"decision":"block","reason":"RESULT_COUNTの明記が無く、統合前チェックを実行できません"}'
exit 0
fi
exit 0decisionにblockを返すか終了コード2を返すと、サブエージェントの終了そのものを止められます(出典: 同上)。止めるほどではないときは、hookSpecificOutput.additionalContextで注記だけを足すこともできます。
07フックが空振りするのは、AIエージェントの結果のうち何を読んでいるからですか?
高梨課長フックは書いたのに、判定が空振りすることがあります。どこを疑えばいいでしょうか。
鈴木さん読みに行く先を疑っています。ファイルを直接開く実装だと、まだ書かれていない最後の一言を、見落とすことがあります。
agent_transcript_path(サブエージェント自身の会話ログ)は、非同期に書き込まれます。フックが発火した時点では、最新のメッセージがまだ書かれていないことがあります。
SubagentStopが受け取るtranscript_pathは、親セッション側のtranscriptを指します。名前は似ていますが、別のものです。
公式ドキュメントは、Stopフックのtranscript_pathについて、Stop時点で最終メッセージを含む保証がないと明記しています。SubagentStopでも理由は同じで、last_assistant_messageを読むほうが安全です(出典: Claude Code公式ドキュメント「hooks」)。
08孫までいるサブエージェント構成でも、同じ検証で足りるんですか?
足りません。サブエージェントが自分の子(孫)をさらに生む構成では、要約が二重にかかります。
孫の作業内容は中間の子の中で要約され、その要約だけが親へ戻ります。トップの子だけにフックを絞ると、この中間の圧縮が検証の外へ出ます。
既定の深さ上限は、v2.1.219以降で3層です。それ以前は、v2.1.172〜v2.1.216が5層固定、v2.1.217〜v2.1.218が既定1層でした(出典: 同上)。
積み上げて見ると、上へ行くほど手元に残る文字が減ります。土台の孫がいちばん多く読み、親がいちばん少なく受け取ります。段を1つ増やすことは、たたむ回数を1つ増やすことと同じです。
対処は、対象のagent_typeを広げるか、各層に同じフックを掛けるかです。どちらでも構いませんが、層が増えたときに掛け忘れないのは後者です。
この章のまとめ
深さ上限のような既定値は変わります。深さ上限だけでも、v2.1.217で5層から1層へ、v2.1.219で1層から3層へと2回変わりました。検証環境の欄は都度更新します。
09結果統合の検証ができたと、AI社員の運用ではどう判定するんですか?
判定は感覚ではなく、外から見える形で決めます。次の6点がすべて満たされていれば、この検証は機能しています。1つでも外れていれば、統合を確定させる前に見直します。
6点は、並び順にも意味があります。前半は数と中身、中盤は仕組みと期限、後半は構造と実装です。前が崩れたまま後ろだけを整えても、効き目は出ません。
このチェックリストで拾えないものも2つあります。1つは、子が最初から読んでいなかった情報です。もう1つは、読んだのに要約にも生データにも残らなかった判断です。前者は指示の設計、後者は子側の書かせ方の問題で、結果統合の検証とは別に手を打ちます。
10上書き事故とサブエージェントの情報欠落は、生成AIの現場でどう違うんですか?
若葉さん並列で動かすと事故が起きる、という話はよく聞きます。これも同じものですか。
鈴木さん別のものとして扱っています。書き込みがぶつかっていなくても、統合の設計だけで情報は落ちるからです。
複数のAIエージェントが同じファイルへ同時に書き込んで上書きする事故は、ここで扱う情報欠落とは別の問題です。そちらはAIエージェント並列実行の競合|上書き事故を止める3点で扱っています。
ディレクター・ワーカー設計の記事は、統合の失敗を重複・抜け・上書きの3パターンに整理しています。本記事が扱う情報欠落は、そのどれにも当たりません。担当範囲が正しく割れていても、要約という工程だけで情報は落ちます。
重なっているのは「同時に動かしている」という条件だけです。ここが同じなので同じ事故に見えますが、直し方は共有できません。競合の対策を入れても、要約で消えた行は戻りません。
11明日から、サブエージェントの結果統合の検証はどこから始めるんですか?
順番があります。確保できていないものは突き合わせられず、突き合わせの中身が決まっていないものは自動化できません。
最初の一歩は、いま走らせている構成で、transcriptが何本残っているかを数えるところです。数えてみると、起動したつもりの子が起動していない、という食い違いが先に出てくることがあります。
そこが片づいたら、まとめ上げた文章と照らします。照らす材料は、数値とファイルパスから始めると判定がぶれません。最後に、その照合を完了のイベントへ載せます。
12よくある質問
結果統合の検証は、サブエージェントを何体から使うときに要りますか
子が1体でも要約は起きるため、検証そのものが無駄になることはありません。ただし手間に見合うのは、独立した子を複数並列で走らせ、統合の判断が難しくなる場面です。まず1本の構成で検査を書いてみて、並列に広げるときにそのまま持ち込む順番が扱いやすいと考えています。
SubagentStopフックでdecision: blockを返すと、子は終了できなくなりませんか
いいえ。公式ドキュメントは、SubagentStopでのblockまたは終了コード2を、サブエージェントの終了を防ぐ動作だと説明しています。フック側で再試行の回数に上限を決め、上限に達したらblockを返さない設計にしておきます。止まったまま戻らない状態を作らないための組み合わせです。
transcriptファイルは、いつまでに確認すればよいですか
既定では30日で削除されます(出典: Claude Code公式ドキュメント)。長く残したい場合は、検証が終わった時点で必要な行だけを別の場所へ写します。全文を抱え込む必要はありません。判定に使った数値とパスの周辺だけを残しておけば、後から経緯をたどれます。
孫までいるサブエージェント構成でも、結果統合の検証は同じ方法で足りますか
足りません。トップの子だけにフックを掛けると、孫の要約が中間の子で圧縮されたあとの状態しか検証できません。対象のagent_typeを広げるか、各層に同じフックを掛ける設計にします。段の数は設定で変わるので、いま何段で動いているかを先に確かめてください。
検証で使うPythonスクリプトは、Claude Code以外の環境でも使えますか
使えます。スクリプトはtranscriptファイルと最終成果物のテキストを読み比べるだけなので、他のマルチエージェント基盤が吐くログ形式に合わせて、正規表現の部分を調整すれば動きます。拾う対象は、その現場でいちばん消えると困る表記に入れ替えてください。
件数が合っているのに、事実だけが消えていることはありますか
あります。それがいちばん多い落ち方です。子はすべて完走し、ログもそろっているのに、要約に選ばれなかった行だけが落ちます。件数の一致は「子が全員帰ってきた」ことしか示しません。持ち帰った中身が残っているかは、文章と照らして初めて分かります。
13まとめ|今日やる3つのこと
親へ返るのは要約でした。落ちる地点は4つに整理でき、そのうち数だけでは気づけないものが大半でした。だから、確保・突合・遮断の順に手を打ちます。
この順で手をつけます
走らせている構成で、残っているtranscriptの本数を数える
起動できていない子が、ここで先に出ます
まとめ上げた文章と子の生データを照らし、消えた記述を名指しする
数値とパスから始めると判定がぶれません
その照合を
SubagentStopへ載せ、わざと欠落させて止まるか見る載せただけでは、まだ止まる保証がありません
AI検索では、こう聞かれています
サブエージェントの結果は、親にどこまで返ってくるんですか?
「サブエージェントの結果統合を検証しないと、何が消えるんですか?」の章で説明しています
結果統合で情報が落ちるのは、どこですか?
「サブエージェントに任せた情報は、どの地点で落ちるんですか?」の章で4つに整理しています
SubagentStopフックで、統合の前に止められますか?
「サブエージェントの結果統合を、検証し忘れないようにするにはどうするんですか?」の章で扱っています
孫までいる構成でも、同じ検証で足りますか?
「孫までいるサブエージェント構成でも、同じ検証で足りるんですか?」の章にあります
次に読むなら、この記事です