Subagent dispatch: final cache breakpoint sits ~5.3k tokens upstream of the user message, so a 33-token prompt diff rewrites ~5,308 cached tokens
Summary
When several subagents are dispatched with near-identical prompts, a 33-token difference between their user messages invalidates ~5,308 tokens of byte-identical cached content. It looks like the final prompt-cache breakpoint sits ~5.3k tokens upstream of the subagent user message rather than immediately before it, so the user message shares a cache block with a large, unchanging segment.
Measurement
Two arms, four dispatches each, one variable: the text of the user prompt. Same agent definition, same declared tools, same session, same model. Numbers read from cache_creation_input_tokens / cache_read_input_tokens on each subagent's first assistant turn.
| arm | prompts | fresh cache_creation per agent | cache_read per agent |
|---|---|---|---|
| A | byte-identical | #1: 11,374 · #2-#4: 0 | #2-#4: 11,374 (100% hit) |
| B | differ by one word | 5,303 each | 6,076 each |
Arm A is the control that makes this legible: with byte-identical prompts the siblings hit the cache completely. So the ~5.3k that Arm B re-writes is not per-agent content — it is identical across the siblings and gets invalidated only because the user message sharing its block changed.
The user message is 33 tokens. So roughly 5,270 tokens — 99.4% of what is rewritten — did not change.
It is not the agent definition, and not the tool schemas
Repeating on a second agent type:
| agent | declared tools | shared (cached) prefix | per-agent block |
|---|---|---|---|
| A — read-only scout | 4 | 6,076 | 5,303 |
| B — acting worker | 7 | 7,959 | 5,313 |
The shared prefix grows with the agent definition (+1,883). The block does not move (+10, noise). Whatever occupies that trailing segment is constant across agent types — which rules out the two explanations we started with (per-agent preamble drift, per-agent tool schemas).
We cannot determine from outside what that ~5.3k actually contains. We can only observe that it is byte-identical across siblings and shares a cache block with the user message. That part is visible to you and not to us, and we would rather say so than guess.
The ask
Place the final cache breakpoint immediately before the subagent user message.
Cost: one breakpoint slot. Benefit: the ~5.3k stops being rewritten on every dispatch whose prompt differs at all — which is every parallel fan-out, since the point of fanning out is to give each child a different task.
What it costs today
~5,308 tokens x cache-write rate is about $0.033 per non-first agent. Across the 1,744 subagent runs behind our own startup-tax measurement, roughly $58 — modest in absolute terms, and mechanical: paid per dispatch regardless of how little work the child does. It scales with fan-out width.
Limitations
- Two agent types. The constancy claim rests on the 4-tool and 7-tool cases above. We have not tested a large-prefix (~117k) agent, and a null at ~11k does not by itself bound behaviour at 117k. Read it as "constant across the two measured", not "constant".
- One anomalous dispatch in eleven. In the second arm, one sibling read 0 and cold-wrote its full prefix while its two simultaneous siblings both hit. Sibling cache hits are usually available in parallel fan-out but are not guaranteed. We could not reproduce the miss deliberately, and report it rather than drop it because it is the one observation that resists the tidy story.
- Black-box method. We infer breakpoint placement from cache behaviour; the inference is only as good as that correspondence.
What we tried first
- Staggering sibling dispatch 8-28s apart (hypothesis: parallel siblings race the cache write): -0.1%. Noise. Parallel siblings hit as well as staggered ones.
- Pinning the agent preamble so it cannot drift between instances: premise is false. Arm A proves the preamble is already stable and already fully cached. Nothing to pin.
Both were pre-registered as hypotheses and both were falsified by their own measurement. We found no remaining lever on our side of the boundary, which is why this is a report rather than a patch.
Possibly same family as #71983 (different mechanism — that one is main-thread history re-read, this one is subagent boot), in that both are context/cache economics not reachable from outside the harness.