Before you start
Caching pays off when many requests begin with the same large block: a system prompt, tool definitions, a reference document or a long history. The first request writes that prefix to the cache once its response starts. A later request with an identical prefix reads it back. The docs state that caching has no effect on the output you receive.
You need the setup from lesson 1, and the tool list from lesson 2 is a typical thing to cache. Caching needs no beta header any more. The prompt caching page covers the one trap: an old tutorial that calls client.beta.prompt_caching fails in current SDKs with an AttributeError. Call client.messages.create instead.
Add a cache breakpoint and prove it worked
The sample reviews text against a style guide kept in a file. The guide is the same on every request, so it carries the breakpoint, and the question that follows it changes. Use a real guide of at least 512 tokens, or the cache is skipped.
import anthropic
client = anthropic.Anthropic()
# Your stable text. It must reach the model's minimum, 512 tokens on Opus 5.5.
STYLE_GUIDE = open("style_guide.md", encoding="utf-8").read()
def ask(question: str):
return client.messages.create(
model="claude-opus-5-5",
max_tokens=500,
system=[
{"type": "text", "text": "You review text against the style guide below."},
{
"type": "text",
"text": STYLE_GUIDE,
"cache_control": {"type": "ephemeral"},
},
],
messages=[{"role": "user", "content": question}],
)
for question in ["Is the word 'utilize' allowed?", "How should I write a date?"]:
usage = ask(question).usage
print(
"written:", usage.cache_creation_input_tokens,
"read:", usage.cache_read_input_tokens,
"uncached:", usage.input_tokens,
)- Put the stable content first. The cache prefix is built in the order
tools,system, thenmessages. - Add
"cache_control": {"type": "ephemeral"}to the last block that is identical in every request. - Run the script. The second request starts within five minutes of the first.
- Read the printed numbers. The first request reports tokens written to the cache, and the second reports the same count as tokens read.
- If written and read both stay at 0, the prefix is under the model minimum or the marked block changes between calls.
What a breakpoint covers
A breakpoint caches everything before it, from the first tool down to the marked block. Writes happen only at breakpoints. A read goes the other way: the API looks for an entry at your breakpoint, then walks back through earlier blocks, up to 20 positions, for one that an earlier request wrote. It never finds stable text that was not a breakpoint when it was written.
That rule explains the classic failure. Put a timestamp or the user message inside the marked block and every request writes a new entry and none reads one. Mark the end of the static prefix and let the changing part follow it.
You can place up to four breakpoints, and they cost nothing by themselves. Billing covers only writes, reads and uncached input. A second breakpoint matters in a long conversation: when a turn adds 20 or more blocks past the last write, the walk misses the old entry unless a nearer breakpoint has been writing.
| Aspect | Automatic caching | Explicit breakpoints |
|---|---|---|
| Where it goes | One cache_control at the top level of the request | cache_control on a tool, system or message block |
| As the chat grows | Moves to the last cacheable block on each request | Stays where you put it |
| Good for | Multi-turn conversations and agent loops | Sections that change at different rates, such as tools, system and documents |
| Slots | Uses one of the four | Up to four |
| Fails when | The last block has an explicit marker with a different TTL, or all four slots are taken | The marked block changes from request to request |
Minimum lengths by model
A prompt shorter than the minimum is processed without caching, and the API returns no error. You find out only from the usage fields: if both cache counts are 0, the prefix was too short or did not match.
If your prompt falls just under the line, the docs say padding the cached content to the threshold is often worthwhile, because a read costs less than uncached input.
| Minimum cacheable prompt | Models |
|---|---|
| 512 tokens | Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5, Opus 5, Fable 5 |
| 1,024 tokens | Opus 4.8, Sonnet 5, Sonnet 4.6, Sonnet 4.5 |
| 2,048 tokens | Opus 4.7 |
| 4,096 tokens | Opus 4.6, Opus 4.5, Haiku 4.5 |
Lifetime and cost
The default lifetime is five minutes, counted from the start of the request that wrote or read the entry. Every read refreshes it at no extra charge, so a busy agent keeps its own cache alive. A response that streams for four minutes leaves its follow-up about one minute to start.
For longer gaps, set "ttl": "1h" inside cache_control. A 1-hour write costs more, and the docs suggest it for side agents that run past five minutes or for chats where the user may not reply soon. When one request mixes both lifetimes, the 1-hour entries must come first. The usage object then splits writes into ephemeral_5m_input_tokens and ephemeral_1h_input_tokens.
The usage fields add up: total input is cache_read_input_tokens plus cache_creation_input_tokens plus input_tokens. The last one counts only what comes after your final breakpoint, which is why it shrinks once caching works.
0.05x
for a cache read on Opus 5.5 and Sonnet 5.5
Source: Anthropic Docs: Prompt caching (read November 5, 2026)
What resets the cache
A change at one level of the tools, system, messages order resets that level and every level after it. Tool definitions come first, so touching a name, a description or a parameter throws everything away.
The cache diagnostics page names a cause that surprises people: the cache is per model, so a router or fallback that picks another model starts from nothing. Another comes from JSON writers. Swift and Go, among others, randomize key order, so the keys inside a tool_use block must come out in the same order every time.
| What changes | Tools | System | Messages |
|---|---|---|---|
| Tool definitions | Reset | Reset | Reset |
| Web search or citations toggle | Kept | Reset | Reset |
| Speed setting, fast or standard | Kept | Reset | Reset |
tool_choice | Kept | Kept | Reset |
| Images added or removed | Kept | Kept | Reset |
Thinking parameters, output_config.effort | Model-specific | Model-specific | Reset |
Find out why a request missed
Reading usage tells you that the cache missed, not why. Cache diagnostics compares two requests and names the first place they diverged. Pass a diagnostics object with previous_message_id set to null on the first turn, then pass the previous response id on the next one. It works on the Claude API only. The beta header it once needed is no longer required, though the docs' Python example still goes through client.beta.messages.
A reply with cache_miss_reason of model_changed, system_changed, tools_changed or messages_changed points at the culprit, with cache_missed_input_tokens as a rough size of the lost prefix. A messages_changed result usually means the history was truncated, edited or re-serialized instead of appended to (cache diagnostics page).
r1 = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[{"role": "user", "content": "Summarize section 1."}],
diagnostics={"previous_message_id": None}, # opt in on the first turn
)
r2 = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[
{"role": "user", "content": "Summarize section 1."},
{"role": "assistant", "content": r1.content},
{"role": "user", "content": "Now summarize section 2."},
],
diagnostics={"previous_message_id": r1.id},
)
if r2.diagnostics and r2.diagnostics.cache_miss_reason:
print(r2.diagnostics.cache_miss_reason.type)- A null result with high cache reads means the prefix held and the cache hit.
- A null result with zero reads means the requests matched but the entry had expired, so shorten the gap or use the 1-hour lifetime.
- A changed type with zero reads means the request changed. Fix what the type names, starting with the first one reported.
Warm the cache before traffic arrives
An entry exists only after the first response starts. Requests fired at the same moment cannot read it, so send one, wait for its response to begin, then send the rest in parallel.
To fill the cache before a user asks anything, send a pre-warm request. Set max_tokens to 0 and put an explicit breakpoint on the last block the real requests share, usually the system prompt or the tool list. It returns an empty content array, a stop_reason of max_tokens and a full usage block. No output tokens are billed, but a cache write still is.
The API rejects a zero-token request that sets stream, extended thinking, structured outputs or a forced tool_choice, and it rejects one inside a batch. Match the real requests' thinking and effort settings, because the cache keys on them.
Thariq Shihipar and ClaudeDevs on building around the cache
Thariq Shihipar, who worked on Claude Code at Anthropic when he posted it, wrote on X on 20 February 2026 that agents have to be designed for prompt caching first. Almost every feature touches the cache somehow, in his words. For your own agent, decide where the breakpoints go before you add features that rewrite the system prompt or swap tools mid-session.
ClaudeDevs, Anthropic's account for developers, shared a tip on 14 May 2026: send the system prompt before the user's request. Claude writes it to the cache without generating output, so the real request lands on a warm cache. That is the zero-token pre-warm request in this lesson. The docs add a rule the post leaves out: on the default lifetime, re-warm at least every five minutes.
you fundamentally have to design agents for prompt caching first, almost every feature touches on it somehow
Screenshots of X's own embeds of the posts, taken on 5 November 2026, with the time in UTC. Select one to open the post on X.
Common mistakes
- Marking a block that holds a timestamp, a request id or the user's message.
- Expecting a hit under the model minimum and getting neither a hit nor an error.
- Reading
input_tokensas the whole input once caching is on. - Editing, reordering or re-serializing the tool list between requests.
- Switching
tool_choice, effort or images mid-conversation and wondering why the messages stopped hitting. - Counting on the cache after a pause longer than its lifetime.
- Expecting a second workspace to share the cache.
Try it yourself
- Run the sample twice and print the three usage numbers. Then change one character in the style guide and run again. Which number moves?
- Add a timestamp to the first system block, above the breakpoint. Run twice and watch the read count stay at 0.
- Set
"ttl": "1h"and printusage.cache_creationto see the two lifetimes counted apart. - Wait six minutes between two calls and see what the usage fields say.
Next
Lesson 4 writes the agent loop with a top-level cache_control on every call, so the history before each new turn is read from the cache. The cache only saves work on input, and the context window lesson explains what still has to fit.
Check yourself
Where should the cache_control breakpoint go?
Show answer
D. On the last block that stays identical across requests Writes happen only at breakpoints, so a breakpoint on a changing block never produces a read.
Both cache usage fields are 0 on a call that carries cache_control. What is the likely cause?
Show answer
A. The prefix was shorter than the model minimum A prefix below the minimum is processed without caching and no error is returned.
With caching on, what does input_tokens in usage count?
Show answer
B. Only the tokens after the last breakpoint Total input is cache reads plus cache writes plus input_tokens, and the last one covers only what follows the final breakpoint.
Which change resets the tools, system and messages caches together?
Show answer
C. Editing a tool definition Tools come first in the cache order, so a changed tool definition resets every level after it.
Frequently asked questions
Does caching change what Claude answers?
No. The docs say prompt caching has no effect on output token generation, so you get the same response you would get without it.
Can I use caching with the Batch API?
Yes, but hits are best effort, because batch requests can run concurrently and in any order. The docs suggest sending one request with the shared prefix and a 1-hour cache block first, then the rest of the batch.
Can I clear the cache by hand?
No. There is no way to clear it. An entry expires after a minimum of five minutes without use, or after its 1-hour lifetime.
Are thinking blocks cached?
They cannot carry cache_control themselves. When they sit in earlier assistant turns they are cached along with the other content, and they count as input tokens when read from the cache.
What does a cache read cost compared with normal input?
On 5 November 2026 the docs list 0.1 times the base input price for most models, 0.05 times for Opus and Sonnet 5.5, and 0.025 times for Fable 5.1. Writes cost more than normal input, so a prefix used only once never pays back.
Sources
- Anthropic Docs: Prompt caching https://platform.claude.com/docs/en/build-with-claude/prompt-caching
- Anthropic Docs: Cache diagnostics https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics
- Anthropic Docs: Models overview https://platform.claude.com/docs/en/models/overview
- X: Thariq Shihipar on designing agents for prompt caching first https://x.com/trq212/status/2024638793719177291
- X: ClaudeDevs on pre-warming the prompt cache https://x.com/ClaudeDevs/status/2055069548672631218


