m@berryhill: ~/berryhill.dev/posts/an-agent-cache-miss-can-start-in-the-tool-list.md
m@berryhill in ~/posts$ cat an-agent-cache-miss-can-start-in-the-tool-list.md
---
title:  An Agent Cache Miss Can Start in the Tool List
date:   2026-10-26
topic:  ai-agents
read:   9 min
words:  1,973
slug:   an-agent-cache-miss-can-start-in-the-tool-list
views:  live post
tags:   [ai-agents, prompt-caching, tool-calling, agent-operations]
---
essay · long read

An Agent Cache Miss Can Start in the Tool List

Before upgrading models or extending cache lifetimes, test whether tool definitions and changing prompt prefixes are defeating reuse.

table of contents
  1. The tool list comes before the instructions
  2. A breakpoint after a timestamp can cache the wrong boundary
  3. Establish a control before changing the registry
  4. Choose the repair that matches the evidence
  5. Don't preserve the wrong tools to protect a cache hit

An agent can send the same instructions on every request and still miss its prompt cache. The instructions may be stable while the tool definitions ahead of them keep changing.

Before paying for longer retention or blaming the model, compare the requests your application actually builds. With Claude's prefix cache, an edited tool description can matter more than a paragraph of unchanged system instructions.

My recommendation is to treat the reusable prefix as a versioned interface: make accidental changes visible, put the cache boundary before volatile request data, and check the usage fields before choosing a repair.

This is a debugging procedure based on Anthropic's prompt-caching documentation, not a benchmark. I haven't measured a savings figure for it. The ordering and field names below are specific to Claude; another provider needs its own checks.

The tool list comes before the instructions

Anthropic documents the cache hierarchy as tools, then system, then messages. A change at one level invalidates that level and the levels after it. Editing a tool's name, description, or parameters in the original tools array can therefore invalidate reuse of the following system and message content.

Consider a hypothetical agent that rebuilds its registry for each request. The system instructions stay untouched, but a tool description includes a fresh timestamp or a changing list of available resources. Comparing only the system prompt would miss the difference that matters.

The same problem can arise without a deliberate content edit. Anthropic's troubleshooting guidance warns that unstable key ordering in tool_use content blocks can break cache matching. The serialized request deserves attention, not just the source template that produced it.

One edit, downstream scopeClaude constructs cache prefixes in tools, system, messages order. Editing the original tools array invalidates its prefix and following system and message cache levels. Supported inline tool additions are a distinct model-specific path, not edits to the original tools array. Provider-documented mechanism, not measured results.One edit, wider scopeClaude prefix orderTools: original arrayEdit a descriptionSystemPrefix invalidatedMessagesPrefix invalidatedSeparate supported pathInline tool additions:keep original tools intact.Check model support first.
Editing the original prefix and appending a supported tool addition are different operations.

There is an important exception to the tool-change rule. On supported models, Anthropic documents a beta path for adding or changing tools through a tool_addition block in a mid-conversation system message while leaving the original tools array unchanged. That preserves the cached prefix. The documentation also notes a first-tool cache-miss exception when the original array has no non-deferred tool.

That is a separate implementation choice, not evidence that rewriting the original tool list is harmless. Check the supported-model tool-change mechanism before designing around it. An ordinary registry rebuild and an appended tool addition should not share the same label in your logs.

A breakpoint after a timestamp can cache the wrong boundary

Suppose independent requests contain stable instructions, then a current timestamp, then the question. If the only explicit cache breakpoint sits after the changing timestamp, each request writes a different prefix.

A longer lifetime keeps those entries around longer. It does not make their prefixes identical.

The fix for that request shape is to put an explicit breakpoint at the end of the stable prefix and keep the timestamp and incoming question after it. Anthropic explains that automatic prefix checking looks for entries written at previous breakpoints; it does not discover arbitrary stable content that was never written at a reusable boundary.

Put the boundary before changeAlternative A places stable context then a changing timestamp before the only breakpoint, so its written prefix varies. Alternative B places the breakpoint at the end of stable context, with the timestamp afterward. These are independent-request alternatives, not sequential steps or a rule for append-only chats. Reuse still requires a matching prior write and applicable cache conditions.Boundary before changeIndependent requestsTwo alternatives, not stepsA · Changing prefixStable contextChanging timestampOnly breakpointWritten prefix varies.B · Stable boundaryStable contextExplicit breakpointChanging timestampStable prefix can matcha prior cache write.Not an append-only chat rule.Cache conditions still apply.
Write a reusable boundary before the changing suffix.

This example is about separate requests with a varying suffix. An append-only conversation preserves earlier blocks and can reuse earlier writes as it grows. Anthropic recommends automatic caching for many multi-turn conversations. Don't apply the timestamp diagnosis to a growing conversation without inspecting its actual block history and caching mode.

Establish a control before changing the registry

Use non-sensitive representative context. First confirm that the intended prefix meets the minimum cacheable length for the exact model and platform, and that the follow-up starts within the applicable cache lifetime. Keep the model, route, workspace, caching settings, and other request options constant.

Then run a few comparisons, changing one thing at a time:

  1. Write the static prefix, then send a matching follow-up with only the question changed after an explicit stable breakpoint. Check whether the response reports cache reads.
  2. Return to that control and change only one description in the original tool list. Compare the usage fields with the stable case.
  3. Test the independent-request timestamp placement: first before the only breakpoint, then after a breakpoint at the end of static context. Avoid changing the registry during this comparison.

These are proposed tests, not reported results. A missing cache read in the control is a reason to investigate the setup before attributing anything to the changed description.

Inspect before choosing a repairThree unmeasured experiment cards. Stable control: write a stable prefix and then send a matching request, inspecting cache creation and cache reads. Tool experiment: change only one description in the original tools array and compare usage against control. Timestamp experiment: for independent requests, move only the timestamp across a fixed stable breakpoint and compare usage. Inspect cache_creation_input_tokens and cache_read_input_tokens in the response. Hold model, route, cache settings, prefix length, and timing conditions constant. No token counts or success outcomes are asserted.Inspect, then decideProposed tests · unmeasuredStable controlWrite, then match prefix.Inspect creation + reads.If no reuse: check length,lifetime, route, boundary.One tool editChange one descriptionin the original tools.Inspect creation + readsagainst the control.One boundary changeIndependent requests:move timestamp acrossthe fixed breakpoint.Inspect creation + readsfor both placements.Keep conditions fixedModel, route, cache settings;eligible length, within lifetime.No results claimed here.
Change one input at a time; inspect usage before choosing the repair.

The response's usage object provides the useful separation:

Field What Anthropic says it counts
cache_creation_input_tokens Tokens written to a new cache entry
cache_read_input_tokens Tokens retrieved from cache for this request
input_tokens Input tokens neither read from nor used to create a cache entry

A cache write proves that an entry was created. It doesn't prove that a later request reused it. Keep creation and read counts separate when comparing cases.

For the experiment record, retain the request-builder and tool-set version labels, model and route, prefix token length, elapsed interval, and these usage counters. You don't need a new store full of raw prompts, sensitive tool descriptions, or tool arguments to diagnose the boundary. Use deliberately non-sensitive fixtures and opaque version labels for the comparison.

Choose the repair that matches the evidence

If the stable control reads cache and the edited original tool list does not, investigate accidental registry churn. Give that workload a deliberate, reproducible tool set instead of generating a slightly different one on every call.

If moving the timestamp after a stable breakpoint restores reuse, fix the request builder's boundary. Buying longer retention would address a different problem.

If an unchanged request shape stops reusing the cache only after its lifetime elapses, retention becomes a reasonable candidate. Keep response duration in the timing record: Anthropic measures the lifetime from the start of the request that writes or reads the entry, not the end of its response.

If the control never reads cache, check the documented minimum length, matching content, isolation scope, request settings, and breakpoint lookback rules. The current documentation also links a cache-diagnostics feature that can compare consecutive requests. Follow the provider's troubleshooting guidance rather than assuming every miss has the same cause.

There may be little to optimize. If the workload has barely enough reusable context, or almost every request legitimately changes it, elaborate cache engineering may cost more than it saves. Measure repeated work in your own workload before committing to the maintenance.

Don't preserve the wrong tools to protect a cache hit

A stable prefix is useful only while its contents remain correct and authorized. Remove revoked tools. Refresh stale policy and source material. Accept the miss when the task requires a different tool set, or evaluate a supported tool-addition mechanism when that is appropriate.

The broader context-policy problem still governs what belongs in the request. Cache reuse is one resource decision inside that policy, alongside constraints such as the budget for parallel tool calls.

Before changing model tiers or extending retention, capture a stable control and one changed request. If the reusable prefix differs, repair accidental differences first. If it doesn't, let the usage fields point you toward the next check.

m@berryhill in ~/posts$

Getting started: research, subscribe, or get in touch

$ cd ../ · back to posts/