Subagent transcripts record usage before responses finish (output_tokens too low, stop_reason null) in 2.1.293

Status Open
Reported on v2.1.293
Maintainer reply None cached
Activity 0 comments · opened Oct 8, 2026

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

  1. 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).
  2. When it finishes, open ~/.claude/projects/<project>/<session>/subagents/agent-<id>.jsonl.
  3. Group type: "assistant" records by requestId and look at the last record of each request.
  4. 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 assistant record. All records of one response share requestId, message.id and the same message.usage.
  • For most requests, the last record has message.stop_reason: null and message.stop_details: null.
  • message.usage.output_tokens is only what had streamed so far, typically 2 to 16. input_tokens and the cache token counts are already final.
  • No later record carries that response's final usage (checked assistant, user/tool_result and attachment records, and the .meta.json and .prefix.json side files).
  • It mostly affects responses whose last block is a tool_use, including a subagent's final hand-back tool call. Responses ending in a text block usually have stop_reason: "end_turn" and the full output_tokens.
  • Example: a subagent's final hand-back call carried a report of about 4,000 characters, but its request's output_tokens is 8 and stop_reason is 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.

View original on GitHub ↗