On agentic workloads with 1M+ input tokens per problem, this is the difference between roughly 0.50 per call.
The rule that matters
One-line enable (Anthropic)
The fastest path: flipprompt_caching=True on the validated D-arm preset. Internally TokenSavingMiddleware delegates wrap_model_call to LangChain’s AnthropicPromptCachingMiddleware, so you don’t add a second middleware to your list.
Validated headline
On paired SWE-bench Pro (n=50 ansible instances,claude-sonnet-4-6, no other middleware) — the same agent loop with and without the flag:
*Preliminary partial n=15/50. Full n=50 paired result lands on this page when both arms finish.
Every one of 15 paired instances saved cost (range −58.6% to −93.4%). The remaining 0.0% of input billed as fresh ≈ 683 tokens across all 15 runs — the cache effectively replaces input billing entirely after turn 1.
What RB does out of the box
ReasonBlocksMiddleware and TokenSavingMiddleware are cache-safe by design:
- The middleware never modifies the system prompt or tool definitions across turns — the stable prefix providers cache against.
ReasonBlocksMiddlewarewraps your base system prompt in acache_control: {"type": "ephemeral"}block automatically, and rides the variable[REASONBLOCKS]steering text in a separate uncached block so it can’t bust the prefix. - Tool-output compression replaces same-id
ToolMessageinstances (LangGraph’sadd_messagesreducer treats same-id messages as in-place replacements). Cache invalidation only affects the modified message onward; earlier turns still hit the cache. - Injection text (monitor firings, early-exit nudges) lands as a new
HumanMessageat the tail of the message list, not in the cached prefix.
enable_token_saving=True (the default), you’re already cache-safe. The remaining work is downstream: verify the provider sees a stable prefix on every turn.
Verify cache hits in production
Every Anthropic response includescache_read_input_tokens and cache_creation_input_tokens in usage. A healthy long-running agent writes the cache on turn 1, then reads it on every subsequent turn.
cache_read_input_tokens is zero on turn 2+, something upstream is mutating the prefix. Common culprits:
cache_controlmissing or mis-placed — must be on the system block (or last tool, or the message you want as the breakpoint). Anthropic supports up to 4 breakpoints.- System prompt being re-templated — even a timestamp injected into the system text breaks the cache.
- Tools list changing across calls — a downstream wrapper sorting or re-ordering tools.
- Prefix below the minimum — Anthropic’s cache requires ≥1024 tokens on Sonnet/Opus, ≥2048 on Haiku. Tiny prompts can’t be cached.
Anthropic native context editing (provider-side)
Recent Claude models ship a server-side context-editing feature (behind a beta header) that clears staletool_use rounds once the context grows past a threshold. It’s a provider feature you enable directly on the Anthropic client — ReasonBlocks does not wrap it. Configure it per the Anthropic context-editing docs; it stacks with RB because the token pools are disjoint (Anthropic evicts stale tool rounds server-side, RB head+tail-truncates the tool outputs you keep visible).
Stack the input-side levers
The full input-side token-reduction stack for a coding agent — one factory, one flag, and each layer targets a mostly disjoint token pool so the reductions compound:
Measure on your own workload — the combined cut depends on your token mix and how orthogonal these pools actually are for your agent.
See also
- Reduce token usage — tool-output compression and early-exit internals
- Chain-of-Draft — minimalist reasoning style (
CHAIN_OF_DRAFT)

