Search

↑↓ to move↵ to openesc to closetop 6 documentation results

Book a demoTry TokenTriage

In development · Explore the product preview. Join the launch list or book a walkthrough.

Browse docs

Cache disclosure surfaces

Every response header a hit sets, every client control a caller can send, and every field the decision ledger records about the cache.

ReferenceLast updated

On this page

Three surfaces carry what the cache did: the response headers a client sees, the control headers a client may send, and the decision.response_cache block on the ledger row. This page is the full list of each.

Headers are covered generally in response headers and ledger fields in decision ledger fields; this page is the cache-specific detail.

Response headers

x-tt-cache is set on every cache-eligible request. The rest appear on a served hit.

Header On Values
x-tt-cache every eligible request hit · miss · bypass · error
x-tt-cache-kind hit exact · normalized · semantic
x-tt-cache-age hit age of the stored entry, in seconds
x-tt-cache-source hit the request id whose response this is
x-tt-cache-entry hit the entry id, and the handle a per-entry purge takes
x-tt-cache-similarity semantic hit the match score
x-tt-cache-threshold semantic hit the bar that score cleared
x-tt-cache-verified semantic hit true · false · none when no verifier ran

There is no setting that suppresses them. They are written from the same value the ledger block is written from, before any response byte goes out.

HTTP/1.1 200 OK
Content-Type: application/json
X-Tt-Cache: hit
X-Tt-Cache-Age: 102
X-Tt-Cache-Entry: 3a2e3889d0a87a520dce119a216f57b64631b2514a094c71d65f078a67452f23
X-Tt-Cache-Kind: exact
X-Tt-Cache-Source: tt_3fg5aqubovpekklypzj5fxq3de
X-Tt-Mode: route
X-Tt-Request-Id: tt_n67vihukwdsdhxma57ugkvzm74

x-tt-decision is absent on a hit: no upstream was contacted for that response.

What is replayed alongside them

The stored entry carries the response headers the client saw, minus the ones that must be recomputed or must not be reused: framing and length, content encoding, the authentication headers, and the whole x-tt-* namespace. Those are stamped fresh at replay, so a replayed response carries its own request id rather than the original’s.

Client control headers

A caller sends x-tt-cache on the request to change what the cache does for it. Each control’s true effect is recorded on the row.

Sent Effect Row records
off no read, no write outcome: bypass, bypass_reason: client_off
refresh no read, write allowed outcome: miss, stored: true
no-store read allowed, no write a normal hit or miss, stored: false
anything else treated as no control as though the header were absent

These are TokenTriage control headers and are stripped before the request is forwarded; the provider never sees them.

Two behaviours are worth knowing:

refresh replaces the entry in place. The entry id is derived from the scope and fingerprint, so it does not change. What changes is the stored payload and its provenance — after a refresh, x-tt-cache-source on later hits names the refreshing request.

A no-store hit is still a hit. The control skips the write, not the disclosure. The response carries the full hit header set.

An unrecognised value fails open to no control, so a client typo cannot silently disable caching for a caller.

The ledger block

decision.response_cache is present on every row where the cache engaged: a lookup ran, a store happened, or a bypass was decided. Its absence means the cache did not touch the request.

"response_cache": {
  "outcome": "hit",
  "kind": "exact",
  "rule": "chat-cache",
  "strategy": "exact",
  "entry_sha7": "3a2e388",
  "source_req_id": "tt_3fg5aqubovpekklypzj5fxq3de",
  "age_ms": 102885,
  "scope_sha7": "799cda7",
  "stored_provider": "openai",
  "stored_model": "gpt-4o-mini",
  "source_usage": { "input_tokens": 1200, "output_tokens": 350, "total_tokens": 1550 },
  "saved": { "usd": 0.00039, "estimated": true, "unpriced": false },
  "saved_basis": "source_usage repriced @ litellm@2026-07-14#179affb, fixed usage",
  "stored": false,
  "lookup_us": 518,
  "serving_tier": "l2"
}
Field On Meaning
outcome always hit · would_hit · miss · bypass · error
rule when a rule was selected the rule id that governed
strategy hit, would_hit the matcher that matched
kind hit, would_hit the disclosure kind of the match
entry_sha7 hit, would_hit first seven characters of the entry id
scope_sha7 hit, would_hit first seven characters of the scope key
source_req_id hit, would_hit the request whose response is stored
age_ms hit, would_hit age of the entry at match time
stored_provider, stored_model hit, would_hit the identity that generated the payload
source_usage hit, would_hit the source row’s usage, the savings input
saved, saved_basis hit, would_hit the repriced counterfactual and how it was computed
serving_tier hit, would_hit l1 · l2 · l3
similarity, threshold semantic the score and the effective bar
verified semantic, when a verifier ran the gray-band verdict
recall_exact, recall_config semantic false plus a config string when an approximate index recalled
verified_active, verified_calibrated, verified_samples, verified_bound semantic under a calibration policy the calibration state behind the effective threshold
embed_cost metered embedder the cache’s own priced spend for this lookup
stored always whether this row’s response was written to the store
bypass_reason bypass, and an over-budget miss the closed reason vocabulary
lookup_us, embed_us when measured lookup and embedding time
Fields whose absence is meaningful

verified is absent when no verifier ran, which is the normal case for a confident-zone semantic hit and for every exact or normalized hit. It is not the same as verified: false, which means a verifier ran and did not pass.

embed_cost is absent for any lookup that did not embed and for any in-process embedder, which records no spend rather than a zero.

source_usage is absent when the stored entry carried no usage.

recall_exact is present only when a similarity decision was made.

The top-level fields a hit row changes

Two, and both matter for anything that aggregates rows.

"usage": { "input_tokens": 0, "output_tokens": 0, "total_tokens": 0, "source": "replay" },
"cost":  { "usd": 0, "pricing_snapshot": "litellm@2026-07-14#179affb", "estimated": false }

usage.source: "replay" with zero buckets is what keeps replayed tokens from being counted as fresh spend. The source row’s tokens are disclosed inside the cache block instead, where a token aggregation will not pick them up.

cost.usd: 0 on a hit row is a confident zero, which is correct here: no upstream call was made, so no money was spent. It is not the UNPRICED case, where a price could not be resolved.

The row still carries the routing decision (decision.tier, decision.upstream) because routing ran before the cache lookup. On a hit those name the route the request would have taken.