Mindket

Claude prompt caching: add cache_control and read the usage fields

A black banner titled "Claude API" over the line "Calls, tools, caching and an agent loop".

Prompt caching lets Claude reuse a prompt prefix instead of processing it again. You add a cache_control marker to the last block that stays the same, and later requests that begin with an identical prefix read it from the cache. The first call writes the entry, and the usage fields show whether a later call read it.

In this lesson

  • Put stable content first and mark the last block that never changes.
  • Check the minimum length for your model, because a short prefix is skipped silently.
  • Read cache_creation_input_tokens and cache_read_input_tokens on every response.
  • Use cache diagnostics to name the change that caused a miss.
All courses
On this page
  1. Before you start
  2. Add a cache breakpoint and prove it worked
  3. What a breakpoint covers
  4. Minimum lengths by model
  5. Lifetime and cost
  6. What resets the cache
  7. Find out why a request missed
  8. Warm the cache before traffic arrives
  9. Thariq Shihipar and ClaudeDevs on building around the cache
  10. Common mistakes
  11. Try it yourself
  12. Next
  13. Check yourself
  14. Frequently asked questions
  15. Sources

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,
    )
  1. Put the stable content first. The cache prefix is built in the order tools, system, then messages.
  2. Add "cache_control": {"type": "ephemeral"} to the last block that is identical in every request.
  3. Run the script. The second request starts within five minutes of the first.
  4. Read the printed numbers. The first request reports tokens written to the cache, and the second reports the same count as tokens read.
  5. 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.

Both modes share the same minimums, ordering and 20-block lookback. From the prompt caching page, read on 5 November 2026.
AspectAutomatic cachingExplicit breakpoints
Where it goesOne cache_control at the top level of the requestcache_control on a tool, system or message block
As the chat growsMoves to the last cacheable block on each requestStays where you put it
Good forMulti-turn conversations and agent loopsSections that change at different rates, such as tools, system and documents
SlotsUses one of the fourUp to four
Fails whenThe last block has an explicit marker with a different TTL, or all four slots are takenThe 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.

For the Claude API, Claude Platform on AWS, Google Cloud and Microsoft Foundry. Bedrock lists its own. Models are named on the models overview. Read on 5 November 2026.
Minimum cacheable promptModels
512 tokensFable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5, Opus 5, Fable 5
1,024 tokensOpus 4.8, Sonnet 5, Sonnet 4.6, Sonnet 4.5
2,048 tokensOpus 4.7
4,096 tokensOpus 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.

Multipliers on the base input price

1.25x

for a 5-minute cache write

Source: Anthropic Docs: Prompt caching (read November 5, 2026)

2x

for a 1-hour cache write

Source: Anthropic Docs: Prompt caching (read November 5, 2026)

0.1x

for a cache read on most models

Source: Anthropic Docs: Prompt caching (read November 5, 2026)

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.

From the invalidation table on the prompt caching page, read on 5 November 2026.
What changesToolsSystemMessages
Tool definitionsResetResetReset
Web search or citations toggleKeptResetReset
Speed setting, fast or standardKeptResetReset
tool_choiceKeptKeptReset
Images added or removedKeptKeptReset
Thinking parameters, output_config.effortModel-specificModel-specificReset

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

Thariq Shihipar, Formerly on Claude Code at Anthropic · X (read November 5, 2026)
Thariq Shihipar (@trq212) on X, 20 February 2026. One of the biggest realizations I have had working on Claude Code is that you fundamentally have to design agents for prompt caching first, almost every feature touches on it somehow. I wrote this in a day but it is the culmination of months of learnings, hope you enjoy it.
Thariq Shihipar on X, 20 February 2026
ClaudeDevs (@ClaudeDevs) on X, 14 May 2026: Useful tip to cut time-to-first-token on longer prompts in the API: pre-warm the prompt cache. Send your system prompt before the user prompt. Claude writes it to the cache, but skips generating any output. When the real user request lands, it will hit a warm cache.
ClaudeDevs on X, 14 May 2026

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_tokens as 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 print usage.cache_creation to 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

  1. 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.

  2. 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.

  3. 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.

  4. 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

  1. Anthropic Docs: Prompt caching (read November 5, 2026)https://platform.claude.com/docs/en/build-with-claude/prompt-caching
  2. Anthropic Docs: Cache diagnostics (read November 5, 2026)https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics
  3. Anthropic Docs: Models overview (read November 5, 2026)https://platform.claude.com/docs/en/models/overview
  4. X: Thariq Shihipar on designing agents for prompt caching first (read November 5, 2026)https://x.com/trq212/status/2024638793719177291
  5. X: ClaudeDevs on pre-warming the prompt cache (read November 5, 2026)https://x.com/ClaudeDevs/status/2055069548672631218

Share this lesson

Browse AI agents built on long prompts

Agents that carry a big system prompt or tool list gain the most from caching. See how finished ones are listed on Mindket.

Browse AI agents

This lesson as Markdown · Claude API course: build an AI agent from scratch · All courses