Receipt
Interface: Receipt
Defined in: src/core/agent/receipt/receipt.ts:334
THE RECEIPT. One per composed request, committed at the call-llm stop.
Example
import { receiptAt } from 'agentfootprint';
// Epochs are the run's OWN iteration numbers and start at 1.
const receipt = receiptAt(agent.getSnapshot()!, 1);
receipt?.tools.withheld; // 'wrap-up' on the out-of-budget call
receipt?.messages.count; // how many turns went out
receipt?.params.temperature; // the dial this turn went out onProperties
basis
readonlybasis:object
Defined in: src/core/agent/receipt/receipt.ts:433
epoch
readonlyepoch:number
model
readonlymodel:string
provider
readonlyprovider:string
runId
readonlyrunId:string
cache
readonlycache:object
Defined in: src/core/agent/receipt/receipt.ts:366
markersApplied
readonlymarkersApplied: readonlyReceiptCacheMarker[]
The breakpoints the strategy actually applied, in the order it applied them — see ReceiptCacheMarker. Empty when it applied none.
strategy
readonlystrategy:string|null
WHICH strategy stood between assembly and the port, or null when none
did (9.93.0). The value is the strategy's name: for the built-ins,
the caching the provider declared ('breakpoints', 'automatic',
'none'); older receipts carry the old registry key ('anthropic',
'openai', '*').
null is a FACT, not an absence: LLMCall and the two message-API
charts hand the port the request assembly built, with nothing in
between, and say so here. transform alone could not — 'unchanged' is
the honest verdict both when a strategy returned what it was given and
when there was no strategy to return anything — which is why the served
view raised cache-transform on every view until this field existed.
Now it raises that gap only where a strategy could have rewritten the
request: where this is not null, or where no receipt can say.
A receipt minted before 9.93.0 has no key here; a reader treats that as
"cannot say", never as null — StoredReceipt is the shape that
says so, and the one every reader is handed.
transform
readonlytransform:"unchanged"|"rewritten"|"unknown"
What the comparison between the request handed TO the cache strategy and
the one it handed back could establish. BRANCH ON THIS, never on
transformHash === null:
'unchanged'— the two serialize identically.'rewritten'— they do not, andtransformHashfingerprints the result.'unknown'— one of them could not be serialized at all, so the receipt refuses to claim either.
It scopes to the CACHE STRATEGY and to nothing else — see RECEIPT_BOUNDARY.
transformHash
readonlytransformHash:string|null
Fingerprint of the request the cache strategy handed back, when it
differed from the one it was given; null otherwise. Recompute it with
transformHashOf. The value names its scheme: 'chain-v1:…'
(see TRANSFORM_HASH_PREFIX), or a bare 16-hex value on a receipt
minted before the prefix existed, which verifies as
receiptHash(runId, stableJson(request)).
messages
readonlymessages:object
Defined in: src/core/agent/receipt/receipt.ts:353
count
readonlycount:number
entries
readonlyentries: readonlyReceiptMessage[]
requestOnly
readonlyrequestOnly: readonlyReceiptRequestOnlyMessage[]
omittedForAttention?
readonlyoptionalomittedForAttention?:ReceiptAttentionOmission
Defined in: src/core/agent/receipt/receipt.ts:432
What left the window for budget at this iteration's head, before this
request was composed — one hash per evicted turn, each the turn's own
messages.entries[].hash as an earlier receipt served it.
Absent when nothing was dropped before this call. Since 9.93.0 that is a
claim and not a shrug: the agent chart's window stage is the one shipped
mechanism that drops for attention and it files every eviction here; the
built-in slots drop nothing; LLMCall and the message-API charts have no
window. It is named by the no-receipt-on-chart entry of time-travel/servedView.ts ·
SERVED_GAPS — the one gap that can lose it, by losing the receipt — and it sat in
UNGAPPED_FIELDS until this release, when its absence was universal and
meant only that nobody had recorded a drop.
params
readonlyparams:ReceiptParams
Defined in: src/core/agent/receipt/receipt.ts:417
The sampling knobs the call went out with — see ReceiptParams.
replayPreparations?
readonlyoptionalreplayPreparations?: readonlyobject[]
Defined in: src/core/agent/receipt/receipt.ts:340
Actual leaf-provider preparation omitted thinking after this port receipt was minted. Original hashes/measurement/cache verdict remain port-level; this is an explicit downstream gap, not proof of what a server accepted.
requestMeasurement?
readonlyoptionalrequestMeasurement?:RequestMeasurement
Defined in: src/core/agent/receipt/receipt.ts:347
Counts of the initial prepared canonical request, including full schemas. Older recordings have no measurement. No payload, tokens or retry totals.
system
readonlysystem:object
Defined in: src/core/agent/receipt/receipt.ts:348
chars
readonlychars:number
hash
readonlyhash:string
pieces
readonlypieces: readonlyReceiptPiece[]
tools
readonlytools:object
Defined in: src/core/agent/receipt/receipt.ts:358
forced
readonlyforced:string|null
The tool the model was forced to answer through, or null.
names
readonlynames: readonlystring[]
schemaHashes
readonlyschemaHashes:Readonly<Record<string,string>>
withheld
readonlywithheld:"wrap-up"|null
Why the tool list is empty when it would not otherwise be.
