AI agents

When to Cache Agent Memory: Trade-offs and Strategies

Antonio Evans8 min read

A split diagram showing an agent's memory system with two layers: a cache (fast, small, volatile) and a persistent store (slow, large, durable).
Key points

Key points

  1. 1Cache agent memory when the cost of recomputation in tokens, latency and API calls outweighs the risk of a stale answer.
  2. 2Prompt caching reuses the model's internal state for an identical prefix, while response and semantic caching return stored text and skip inference entirely.
  3. 3Set short TTLs for volatile facts such as prices and stock levels, longer TTLs for stable reference knowledge, and invalidate on every write or version change.
  4. 4Measure hit rate and freshness together before you commit, because a high hit rate on the wrong data is worse than a cache miss.

The four caches inside an agent

An agent that looks like one system is really four caches stacked on top of each other, and each one fails in a different way. Getting the vocabulary straight is the first step, because teams routinely argue about "caching" while meaning completely different things.

Prompt caching stores the key-value tensors the model computes during prefill, the phase where it reads the input tokens. A later request with the same prefix skips that recomputation and starts reading at the bookmark, which cutting teams describe as cost savings of 50 to 90 percent and latency savings of up to 80 percent in this explainer. The model's outputs still change between calls; only the processing of the input is reused.

Response caching sits in front of the provider. An identical request body, model, key and streaming mode is hashed into a cache key, and a hit returns the stored response with zero tokens billed per these docs. This is exact match only: one character different and you have a new key.

Semantic caching embeds the query and returns a stored answer when cosine similarity clears a threshold, which catches paraphrases that exact-match caching misses as described here. It trades precision for hit rate, so a threshold set too low returns confident answers to the wrong question.

Tool and retrieval caches store the outputs of external calls: a vector search, a database read, an HTTP fetch. These are the cheapest wins in agent loops because they avoid network round trips as well as tokens.

LayerWhat is storedMatch ruleFreshness risk
Prompt cacheKV tensors for a prefixExact prefix, byte for byteLow on content, expires on its own
Response cacheFull response bodyExact request hashMedium, replay of old output
Semantic cacheQuery embedding plus answerSimilarity above thresholdHigh, wrong-question risk
Tool cacheReturn value of a callCache key you defineDepends on the data source

A useful rule: prompt caching is nearly free and almost never wrong, so turn it on first. Every other layer needs an explicit freshness argument.

How prefix caching actually decides a hit

The mechanics matter because they determine what you can safely put where. Serving engines hash the KV cache in blocks, and each block's hash includes the tokens of its parent block plus its own tokens, so a block is only reusable if every block before it matched exactly per the vLLM design notes. In practice that means one edited character near the top of the prompt invalidates everything after it.

This is why the author of a detailed write-up describes putting long user-specific data at the end of the system prompt as his mistake: the cache can start at position zero across all users of the same API key organization if the system prompt is genuinely shared, but a per-user blob near the front kills that shared prefix as he explains here. The fix is the same one that helps everywhere else: static content first, variable content last.

[ shared system prompt + tool definitions ]   <- cacheable across users
[ stable reference documents ]                <- cacheable per tenant
[ retrieved context for this task ]           <- cacheable per task
[ conversation history so far ]               <- grows, cacheable
[ the new user turn ]                         <- never cached

Two gotchas are worth designing around. First, dating information ("today is Tuesday...") near the top of a prompt guarantees a miss on every request that crosses midnight, or sooner. Second, prefix caching depends on the serving engine keeping the entry and routing the request to a worker that can see it, and the messages must serialize identically according to this handbook. A load balancer that scatters a conversation across pods throws the cache away without telling you.

If you call many different providers, the routing problem multiplies. Quanta Inference (https://quantaintelligence.ai/inference) puts text, image, video, audio and embedding models behind one OpenAI-compatible key, which reduces the number of routing layers you have to reason about.

Deciding what to cache: a break-even calculation

The decision rule is arithmetic, not instinct. Caching a value pays off when the expected savings from hits exceed the cost of storing it plus the expected cost of a stale answer. You can estimate the first part before you ship.

Take a support agent that retrieves the same 8,000-token product manual for every question in a session. Say the cacheable prefix is 10,000 tokens, you serve 20,000 requests a day, and 70 percent of them repeat a prefix you already wrote. With input priced at $3 per million tokens and cache reads at a tenth of that, uncached input alone costs 10,000 × 20,000 ÷ 1,000,000 × $3 = $600 a day. At a 70 percent hit rate the same traffic costs $180 for the misses plus about $42 for the hits, roughly $222 a day. The saving is about $378 a day, and it arrives without touching answer quality because prompt caching changes no output. The 10x gap between cached and uncached token prices is the number behind most of these calculations, as stated in this engineering write-up.

Now the freshness side. Suppose 2 percent of answers built on that manual would be wrong if the document is more than a day old, and a wrong answer costs you a $15 credit. You want the manual to be invalidated whenever a new revision is published, which is a write-triggered invalidation, not a TTL. The cache is still worth it, but the invalidation design is now load bearing.

A short checklist before you cache anything:

  • Can you express the invalidation trigger as a signal your system actually receives (a write event, a revision ID, a content hash)?
  • Is the cost of one stale answer lower than the savings from the hits it buys?
  • Does the cache key include every input that changes the output, including model choice and temperature?
  • Can you observe hit rate and staleness separately in production?

If any answer is no, cache a smaller thing. Storing a compiled retrieval result is safer than storing the final answer.

Freshness tiers and time to live

Treat memory as layers with different refresh rules rather than one cache with one timer.

Memory typeExampleSuggested TTLInvalidate on
Live operational dataOrder status, balance, inventorySeconds, or no cacheEvery write
User session contextRecent turns, chosen filtersMinutes to hoursNew turn, logout
Retrieved documentsPolicy pages, product docsHours to a dayDocument revision
Reference knowledgeStyle guides, schemasDays to weeksVersion bump
EmbeddingsVector of a document chunkLong, effectively immutableChunk text changes

The provider defaults set a floor on what is feasible. Anthropic's cache has a five-minute lifetime by default and refreshes at no cost each time the content is used, measured from the start of the request that wrote or read the entry per the Claude docs. That detail matters: a slow response eats into the window, so a four-minute stream leaves about a minute for the follow-up to reuse the same prefix. If your agent thinks for a long time between turns, an explicit longer-lived cache breakpoint is the right call.

Routing layers add their own clocks. A gateway may keep subsequent requests on the same provider to preserve cache locality, and sticky sessions can expire after a period of inactivity per these routing notes. When you debug an unexpected miss, check the routing layer before you doubt your prompt.

The mistake that bites teams is using one TTL for everything. A single hour on a mixed cache means volatile facts go stale and stable facts get evicted early. Split the store by tier and you can tune each one against its own risk.

Invalidation on writes and version changes

TTL is a fallback, not a strategy. Any memory derived from a record should carry a version stamp, and any write to that record should bump the stamp so dependent entries stop being served.

A pattern that holds up well:

def cache_key(kind, record_id, version, model, extra=""):
    return f"{kind}:{record_id}:v{version}:{model}:{hash(extra)}"

def get_plan(record, version, model, store):
    key = cache_key("plan", record.id, version, model)
    hit = store.get(key)
    if hit is not None:
        return hit
    plan = build_plan(record, model)
    store.set(key, plan, ttl=3600)
    return plan

Because the version is inside the key, a write does not need to hunt down and delete old entries: the new version simply produces different keys and the old ones age out. This is the same reasoning vLLM uses when it hashes a block together with its parent hash, so a changed prefix cannot collide with an old one per the vLLM docs.

Versioning also covers the parts of a prompt people forget. Change a tool definition, a JSON schema, or the system prompt, and every plan cached against the old one is suspect. Fold a hash of the whole static block into the key and those caches invalidate themselves the next time you deploy.

For user-facing answers, the cheap insurance is to cache the plan and not the final prose. A research paper on agentic plan caching reports reducing cost by 50.31 percent and latency by 27.28 percent on average by reusing structured plan templates across semantically similar tasks while re-deriving task-specific details per the paper. You keep most of the savings and re-read current data on every run.

Prompt caching and memory management are the same problem

Once you see prompt caching as a memory layout problem, the design choices stop being separate. Both ask the same question: which bytes are shared, which are unique, and where do they sit relative to a boundary?

Cache-aware memory management comes down to four habits.

Order by stability. Most stable content first, most volatile last. A memory record written into the middle of the system prompt costs you every downstream hit.

Never mutate a cached prefix. Append to history rather than editing it. If compaction has to rewrite older turns, do it rarely and accept the miss when you do.

Keep tenant boundaries explicit. Shared prefixes should contain nothing that belongs to one customer. Serving engines offer per-request salting to isolate caches in multitenant environments per the vLLM docs, and you should use it rather than trusting that two tenants happen to have identical text.

Measure what you think you measured. Hit rate alone is not enough. Track time to first token, billed input tokens, cache reads and, separately, how often a served value was older than its tolerance. The advice in the Claude docs on automatic versus explicit cache breakpoints is a good design prompt here: automatic caching tracks the end of a growing conversation, explicit breakpoints let you pin exactly what should be stable per the Claude docs.

The payoff shows up in latency numbers you can feel. A recorded example sending a roughly 10,000-token prompt to a 32B model a second time drops time to first token from 4.3 seconds to 0.6 seconds per this benchmark write-up. Streaming speed stays the same, because caching shortens the wait before output, not the output itself.

For teams running agents across several modalities and providers, the operational surface grows quickly, and managing cache behavior per vendor is easy to get wrong. That is where a single endpoint and a specialist who can sit with your team helps: Quanta (https://quantaintelligence.ai/) takes a described app or agent and builds it with you.

FAQ

FAQ

Should I cache the final answer or the intermediate steps?

Cache intermediate steps first. Plans, retrieval results and tool outputs can be re-derived cheaply and checked against current data, while a cached final answer is only as good as its timestamp. Teams that cache whole responses usually end up adding exact-match keys and short TTLs anyway, which is more work than caching the plan.

Does prompt caching change the quality of the model's answers?

No. It reuses the model's internal computation for the input tokens and still generates a fresh response, so output quality is unaffected per this explainer. What changes is cost and the time to first token. Response caching is the layer where a stored answer gets replayed, and that is where staleness becomes a quality question.

Why do I keep missing the prompt cache even though my prompt looks identical?

Three usual causes: a date or timestamp near the top of the prompt, whitespace or JSON serialization that differs between calls, and a load balancer routing the follow-up to a worker that never saw the prefix per this handbook. Log the exact serialized prompt for two consecutive calls and diff them. Most misses are visible in that diff.

How do I choose a TTL for data that changes unpredictably?

Pick the TTL from the acceptable staleness of the answer, not from how often the data changes. If a wrong price costs more than a thousand cache misses save, use seconds or invalidate on write. Then add a version stamp so a write event invalidates directly and the TTL only exists to clean up entries nothing depends on.

Is semantic caching safe for agents that take actions?

Use it for read-only answers with human-visible citations, not for actions. A similarity match can return a correct-looking answer to a question the user did not ask, and an agent acting on that answer has no chance to notice. If you do run it, set a high threshold and route low-confidence matches back to a full inference call.

Sources

Sources

  1. Prompt Caching Explained: What It Is, What It Isn't, and When to Use It
  2. Cache Identical API Responses - OpenRouter
  3. Prompt caching vs semantic caching: How to make AI ...
  4. Automatic Prefix Caching - vLLM Documentation
  5. How prompt caching works - Paged Attention and Automatic Prefix ...
  6. Prefix caching - LLM Inference Handbook - Modular
  7. KV-Cache Wins You Can See: From Prefix Caching in vLLM to ... - llm-d
  8. Prompt caching - Claude Platform Docs
  9. Prompt Caching - Optimize AI Model Costs with Smart Caching
  10. Test-Time Memory for Fast and Cost-Efficient LLM Agents
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles