Claude Prompt Caching: Why Agent Loops Miss the 20-Block Lookback
Your agent starts a run with cache_read_input_tokens at 40K and climbing. Twelve tool calls later, reads drop to zero and cache_creation_input_tokens jumps to the full conversation length — on every single turn. Nothing in your prompt changed. No timestamp, no reordered tool, no model switch. The prefix is byte-identical. You just hit the 20-block lookback window, and it is the single most expensive thing about Claude prompt caching that nobody puts in their retro. TL;DR A cache_control breakpoint searches backward through at most 20 content blocks to find an existing cache entry. One agentic turn with 11 parallel tool calls emits 22+ blocks and blows past that — the next request finds nothing and rewrites the whole prefix at 1.25x. Fix it by placing rolling breakpoints every ~15 blocks , not one marker on the last block. You get 4 breakpoints per request total; spend 1 on tools+system and rotate the other 3 through the message list. Invalidation is tiered , not all-or-nothing: tool_choice , images, and toggling thinking preserve the tools+system cache. Only tool-definition changes and model switches force a full rebuild. Changing the system prompt mid-run nukes everything downstream — unless you append a {"role": "system", ...} message to messages[] instead (Claude Opus 5, Opus 4.8, Fable 5; not Sonnet 5). input_tokens in the usage block is the uncached remainder only . Total prompt size is input_tokens + cache_creation + cache_read . Dashboards that graph input_tokens alone will show you a flat line while you burn cache writes. Why does Claude prompt caching miss in the middle of an agent loop? Because cache lookup is bounded. Prompt caching is a prefix match on exact bytes, but a breakpoint doesn't scan the entire history for a matching entry — it walks backward a limited number of content blocks. That limit is 20. If the previous request's cached block is more than 20 blocks behind your new breakpoint, the lookup fails, and the API treats your request as cold ev