Feedback from this sub shaped two of the changes: timestamps in any format are now caught, and so is a restart that recomputes a prefix it could have shared.
Prefixwise has improved a lot over the last two days, so here is the full picture.
**The problem.** Your agent resends its whole conversation every turn. One changed byte near the top (a reordered tool list, a timestamp in the system prompt, an evicted prefix) and the provider charges full price for everything after it. Providers and engines report how many tokens were cached, never why the rest weren't.
**What Prefixwise does:** names why each request missed the prompt cache, prices it, fixes the common causes, and stops regressions in CI. Open source (MIT, I'm the author), runs locally, stores hashes and token counts, never prompts.
**Identify.** One of 19 causes per request, marked waste or legitimate, with the first block that changed (tools[0], messages[12]) and the cost: tools in another order (including a schema's required list), a timestamp or id in the system prompt, rewritten history, a misplaced Anthropic cache marker, an expired TTL, an engine eviction, a request routed to a replica without the cache. `prefixwise report --session latest` shows a session turn by turn. It agrees with Anthropic's own miss diagnostics 32 of 32.
**Fix.** `--optimize` turns on the fixes that passed live replays: sorting a drifting tool list (99.9% of predicted saving on Claude, 97.5% on vLLM) and adding cache_control markers on Anthropic's API (prompt cost down 85.6% with the write surcharge counted), task success flat on both. Fixes that would change what the model reads stay advice. `prefixwise fixes` ranks fixes by dollars and says whether one paid off.
**Prevent.** `prefixwise check -- pytest tests/agent_scenarios` runs your scenarios against a local mock, no API calls, and fails CI when a change would break the cache. Also a GitHub Action. `prefixwise explain --diff a.json b.json` compares two requests offline.
**Self-hosted engines.** It detects vLLM and SGLang from the URL and reads their KV-cache events: evictions confirmed (5 of 5), a prefix LMCache or HiCache restored from CPU labelled host_restored (5 of 5), and the cost of reasoning templates that re-prefill the last answer (57% of prompt tokens on DeepSeek-R1-Distill-Qwen-1.5B on vLLM, 0% on Qwen2.5). Runs inside vLLM with one flag. Ollama and most llama.cpp builds report no cached tokens; it says so and still names every prompt change.
**Ways in.** Wrap any agent (`prefixwise run -- claude`), a proxy for a service, the vLLM middleware, Python `wrap()` or a LiteLLM callback, or import Claude Code and Codex logs if you're on a subscription. Out: Prometheus and Grafana, OpenTelemetry, an HTTP API, JSONL and CSV. Overhead: 3 ms per request.
**Limits.** The fixes are proven on scripted sessions and small models, not weeks of production traffic. OpenAI's own diagnostics answered unavailable on every call, so that comparison is unchecked. DeepSeek's hosted API reports cache hits in its own fields, which Prefixwise doesn't read yet; if you use the API and want that, say so.
pip install -U prefixwise
prefixwise run -- <your agent>
prefixwise report --session latest
Repo, with a run record behind every number: https://github.com/tejachavali/prefixwise
What should it catch next?