Subagent transcripts record usage before responses finish (output_tokens too low, stop_reason null) in 2.1.293
Summary
In Claude Code 2.1.293 (Claude desktop app, Code tab), background subagent transcripts record each response's message.usage while the response is still streaming. The final usage is never written, so usage.output_tokens in the transcript is far too low for most responses. In 2.1.289 the final usage was written.
Environment
- Claude Code 2.1.293 (compared with 2.1.289)
- Claude desktop app, Code tab (
entrypoint: "claude-desktop") - Background subagents launched with the Agent tool (
.meta.json:requestShape: "background",requestNonInteractive: true) - macOS
Steps to reproduce
- In the Claude desktop app (Code tab) on Claude Code 2.1.293, start a session and launch a background subagent with the Agent tool. Give it a task that makes a few tool calls and writes a long final report (for example: read three files and summarise them in about 500 words).
- When it finishes, open
~/.claude/projects/<project>/<session>/subagents/agent-<id>.jsonl. - Group
type: "assistant"records byrequestIdand look at the last record of each request. - Repeat on 2.1.289.
Expected
Each response's final usage (after message_delta) is written to the transcript, with message.stop_reason set and the full message.usage.output_tokens. This is what 2.1.289 does, and what the main session transcript does in 2.1.293.
Actual (2.1.293)
- Each content block of a response is written as its own
assistantrecord. All records of one response sharerequestId,message.idand the samemessage.usage. - For most requests, the last record has
message.stop_reason: nullandmessage.stop_details: null. message.usage.output_tokensis only what had streamed so far, typically 2 to 16.input_tokensand the cache token counts are already final.- No later record carries that response's final usage (checked
assistant,user/tool_resultandattachmentrecords, and the.meta.jsonand.prefix.jsonside files). - It mostly affects responses whose last block is a
tool_use, including a subagent's final hand-back tool call. Responses ending in atextblock usually havestop_reason: "end_turn"and the fulloutput_tokens. - Example: a subagent's final hand-back call carried a report of about 4,000 characters, but its request's
output_tokensis 8 andstop_reasonis null.
Measured across local subagent transcripts:
| Version | Transcripts | Requests | Last record has a final stop_reason |
|---|---|---|---|
| 2.1.289 | 32 | 1,541 | 1,533 (99.5%) |
| 2.1.293 | 72 | 2,770 | 1,121 (40.5%) |
In the same 2.1.293 session, the main session transcript had a stop_reason on all 249 of its assistant records.
Impact
Any tool that reads subagent token usage from transcripts undercounts output tokens, and therefore cost. The parent session only receives a single totalTokens figure per subagent run in its task notification, so per-response output usage is not available anywhere else.