[BUG] Waking a parked subagent re-caches its entire context: only the system prefix is served from cache, even minutes later within TTL
Summary
When a stopped/parked subagent is woken (by SendMessage from its parent, or by a background-task completion notification), the next API request serves only the ~6K-token system prefix from cache and re-writes the entire remaining conversation at cache-write rates. This happens even when the wake arrives minutes after the subagent's last turn, well inside the cache TTL, so it is not cache expiry: the conversation-level cache breakpoints appear to be discarded when the subagent's request is reassembled on wake.
Environment
- Claude Code 2.1.233, macOS (darwin 24.6.0)
- Session with 1-hour prompt-cache TTL
- Multi-agent orchestration: a parent session spawning
claude-type background subagents that park between turns (waiting on child agents / background test runs) and are woken by SendMessage or task notifications
Evidence (from session transcripts, usage deduped by message id)
One subagent's wake sequence, all within a single 1h-TTL session. Every wake shows cache_read_input_tokens pinned at exactly the system-prefix size while the whole conversation is re-written:
| wake (UTC) | gap since last turn | cache_read | cache_creation |
|---|---|---|---|
| 20:35:37 | 11m | 6,007 | 82,903 |
| 20:39:10 | 2m | 6,007 | 97,752 |
| 20:43:06 | <1m | 6,007 | 128,121 |
| 20:51:54 | 5m | 6,007 | 150,735 |
| 21:03:19 | 11m | 6,007 | 152,653 |
| 21:21:26 | 18m | 6,007 | 153,767 |
The same signature appears in every parked subagent of the session: 12 subagents, 54 full-context rewrites, 5.2M tokens re-cached at write rates in a 2-hour run. During a subagent's normal working turns, incremental caching behaves correctly (large cache reads, small writes); the full rewrite happens only on the first request after a wake.
Note the 2-minute and sub-minute gaps: no TTL explains those. The cache_read value being exactly the system-prefix size every time suggests the wake path rebuilds the request with a cache breakpoint after the system prompt but without the breakpoints that covered the accumulated conversation.
Repro outline
- Spawn a background subagent (
claudetype) that does some work (grow its context to ~100K), then stops its turn to wait (e.g. on a background task). - A few minutes later,
SendMessageit from the parent. - Compare the woken request's usage against the subagent's prior turns: prior turns show
cache_read≈ full context; the wake showscache_read≈ system prefix only andcache_creation≈ full context.
Expected
A wake within the TTL should be an append: cache_read ≈ the full prior context, cache_creation ≈ the injected message plus normal growth.
Impact
In orchestration patterns where subagents park between phases (parent pings, task-completion wakes), this multiplies input spend: in the measured session the rewrites alone were roughly a quarter of total weighted token cost. It also penalizes exactly the workflows the docs encourage (backgrounded long runs, parent/child messaging).
Related, but distinct
- #74318 measures subagent cache-TTL strategy (5m vs 1h trade-offs). This report is orthogonal: within any TTL, the wake path discards conversation breakpoints entirely.
- #81389 asks for parent-cache inheritance at spawn. This is about a single subagent's own cache across its own turns.
3 Comments
Subagent-wake re-caching is #83913 (hook context dropped on the rebuild that the wake triggers); teammate-opened turns missed at 10× the typed-turn rate on 2.1.252 and were all hits on 2.1.259 in my capture. Suggest closing as fixed in 2.1.259. Details: https://github.com/anthropics/claude-code/issues/91707.
Same signature on Claude Code 2.1.258 with
claude-fable-5-1subagents, but without a park/wake: plain background subagents (Agent tool,run_in_background: true, 8 in parallel doing WebSearch/WebFetch/Write) re-cache the whole conversation on ordinary working turns.cache_read_input_tokenspinned at the 33,578-token system prefix,cache_creation= the rest of the context, always in theephemeral_5mbucket:| time (UTC) | agent | call # | cache_creation | cache_read | gap since previous response |
|---|---|---|---|---|---|
| 15:41:02 | a3ab40ae | 8 | 213,484 | 0 | 3.5 min |
| 15:57:58 | a9cd220c | 9 | 212,879 | 33,578 | 1.5 min |
| 16:03:25 | a629058a | 14 | 431,885 | 33,578 | 5.7 min |
| 16:09:27 | ad6e8ac3 | 10 | 263,804 | 33,578 | 5.2 min |
| 16:15:45 | ad6e8ac3 | 11 | 300,061 | 33,578 | 6.3 min |
10 rewrites, 2.88M cache-write tokens, in under 40 minutes on 2026-09-03; several agents did it on two consecutive turns. The request right after each rewrite reads the full context again (e.g. 304,655 read / 1,595 written), so the breakpoints come back; they just do not survive a Fable 5.1 turn. Two of the gaps above (1.5 and 3.5 min) are inside the 5m TTL, which looks like the loss you describe here rather than expiry; the rest line up with Fable 5.1 turns simply outrunning the 5m bucket. Zero such rewrites on
claude-opus-5(1,720 subagent calls) andclaude-fable-5(179) subagents in the same week.Filed the Fable 5.1 angle with request IDs and the cross-model table as #92090; linking here since it is likely the same underlying cache handling for subagents.
Another data point, same signature, on 2.1.276 / Linux (NixOS) /
claude-fable-5-1, and with a clean negative control.Setup: one interactive session spawned 14 background
Agentsub-agents over a morning (a security-sweep orchestrator with 11 research arms, plus two build/review agents). Only two of the 14 ever received a background-task completion notification (they had spawned children of their own). Usage from the sub-agent transcripts, assistant records deduplicated by message id:| sub-agent | calls | received task-notification wakes | full-context re-writes mid-run | tokens re-written |
|---|---|---|---|---|
| build agent (Fable 5.1) | 209 | 5 | 2 — both on the first request after a wake | 237,127 + 279,607 |
| research arm with children (Opus 5) | 39 | 1 | 5 (1 after a wake, 4 after its own child spawns) | 600,324 |
| the other 12 (no wakes) | ~1,000 total | 0 | 0 | 0 |
The build agent's two re-writes:
cache_read5,515 and 0,cache_creation237k and 279k, immediately after a[SYSTEM NOTIFICATION] task-notificationuser record (isMeta: true). The preceding request in each case was a normal incremental turn (cache_read~238k / ~279k,cache_creation3k / 0.7k). Gaps were 9 s and 7 min, both well inside the 1h TTL. Every other request in that agent cached incrementally.Cost that morning: ~1.1M cache-write tokens attributable to the wake path, ~7% of the day's weighted spend. Cross-ref #94728, which captures the
messages_changeddiagnostic for the same resume path.