Repository navigation
Count Claude subagents named only in the structured tool result - #2777
Conversation
…sult Foreground Explore and Plan results never print "agentId:" in their text, so their tokens and files were missing from checkpoints. toolUseResult.agentId names the agent for every Agent result; it now wins for its tool call, and the text is read only for results that name none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Require "toolUseResult" as well as "agentId" before decoding a line, so subagent progress lines are not decoded; pin that a non-object toolUseResult still falls back to the text; refresh a stale comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Filtering after deduplication can discard legitimate fallback agents, omitting their tokens and modified files.
1 open finding
What changed in this PR
Fixes missing Claude foreground subagent tokens and modified files in checkpoint metadata.
Changes:
- Discovers structured agent IDs across all result statuses.
- Prefers structured IDs, with trailer-based text fallback.
- Adds parsing and token/file aggregation regression tests.
| File | Description |
|---|---|
| cmd/entire/cli/agent/claudecode/transcript.go | Updates subagent discovery and text fallback precedence. |
| cmd/entire/cli/agent/claudecode/transcript_test.go | Tests structured results, precedence, and session aggregation. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 1cbb38f. Configure here.
A structured result without a tool_result block marked the empty tool_use_id as named, which would skip the text of any other result that also lacks one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… IDs A later structured result quoting an earlier text-only agent's ID took over that agent's entry in the last-wins text map, and the named-result filter then dropped it, losing the agent's tokens and files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…red-subagent-ids # Conflicts: # cmd/entire/cli/agent/claudecode/transcript.go


https://entire.io/gh/entireio/cli/trails/1574
Problem
Foreground Explore and Plan subagents in Claude Code are missing from checkpoints. Their tokens never reach
subagent_tokens, and their transcripts are never searched for modified files.spawnedAgentIDsfinds subagents from theagentId: <id>line in an Agent tool result's text. Foreground Explore and Plan results are a hand-back report with no such line. This is verified on Claude Code 2.1.289, 2.1.294, 2.1.296 and 2.1.300. Sosubagents/agent-<id>.jsonlis never read. In one run that was about 52k tokens, roughly 40% of the session.The SubagentStop hook doesn't make up for it: a foreground agent that changed no files gets no task record.
Foreground general-purpose results and background (
async_launched) results still print the line, so they were counted correctly.Fix
Every Agent result line names its agent in the structured
toolUseResult.agentId, whatever its status. The forked-skill scan already read that field forstatus: "forked".toolUseResult.agentIdfor every status. Empty or path-unsafe IDs are ignored.agentId:text is never read, because the text can quote other agents' IDs.agentId:, which is the trailer Claude Code appends, instead of the first.Both callers,
CalculateTotalTokenUsageandExtractAllModifiedFiles, go throughspawnedAgentIDs, so they are unchanged. Subagent transcripts are keyed by agent ID, so an agent found both ways is still read once. The parent's own usage counts only assistant lines, so it can't absorb a subagent's.Tests
TestStructuredAgentCountsTowardSession: a table with a forked-skill case and a foreground-agent case. Each goes through both tokens and modified files. The foreground case fails on main.TestToolResultAgentIDs: covers every status, follow-ups, inline skills, empty and unsafe IDs, and assistant lines.TestSpawnedAgentIDs_StructuredIDWinsOverText: checks that a quoted ID never wins, including in a follow-up, and that results with no structured ID, or with a non-objecttoolUseResult, fall back to the text.TestExtractAgentIDFromText: a new row where the report quotes another ID before the trailer.Recorded transcripts
CalculateTotalTokenUsagewas run on six recorded sessions. Values are input / cache creation / cache read / output / API calls, with ground truth taken from the subagent transcripts after deduplicating by message id:Live check (Claude Code 2.1.300, Codex 0.156.1)
Each run went through the whole path in a fresh scratch repo:
entire enable, then the agent prompt with real hooks, thengit commit, then reading the checkpoint metadata. Each agent ran once with a binary built from main and once with this branch. Live numbers vary from run to run, so each run is compared with its own ground truth.token_usagesubagent_tokensspawn_agentchildspawn_agentchildCodex counts child threads through its SubagentStart/SubagentStop ledger, which this change doesn't touch. It behaves the same on both binaries: exact subagent tokens, the child's task record, and
docs/red.mdattributed.Follow-up
Factory Droid has its own text-only
ExtractSpawnedAgentIDs(factoryaidroid/transcript.go). It hasn't been checked for the same gap.🤖 Generated with Claude Code
Note
Medium Risk
Changes how spawned subagent transcripts are resolved for token usage and modified-file extraction; incorrect parsing could mis-attribute session metadata, but scope is limited to Claude Code transcript parsing with extensive new tests.
Overview
Fixes missing foreground Explore/Plan (and other) Claude subagents in checkpoints by discovering agent IDs from structured
toolUseResult.agentIdon tool results, not only fromagentId:text or forked-skillstatus: "forked".forkedSkillAgentIDsis replaced bytoolResultAgentIDs, which scans any user tool result withtoolUseResult.agentId(completed, async_launched, forked, etc.), tracks whichtool_use_ids were named structurally, and keeps the first launcher per agent ID.spawnedAgentIDsmerges those IDs first, then falls back to text parsing only for results that did not name an agent structurally (older transcripts).extractAgentIDFromTextnow takes the lastagentId:in the result text so quoted IDs in the report body do not win over Claude’s trailer line.Tests cover structured-vs-text precedence, follow-ups, foreground agents in token/file aggregation, and the last-
agentId:behavior.Reviewed by Cursor Bugbot for commit 1cbb38f. Configure here.