Receipts#
When an agent run ends, its machine writes a receipt: a small record of what ran, under which rules, with what, and what came of it. It holds digests and counts only — no prompt, answer, argument or URL — so it can be handed to anyone. It is signed twice and chained, so it cannot be altered or dropped unnoticed, and it can be checked offline with files.
What a receipt says#
| Field | What |
|---|---|
run, task, namespace, machine |
The run, its worker, the workspace's namespace on the cluster, the machine it ran on. |
agent, agent_version, spec_digest |
The agent, the version, and the SHA-256 of that version's specification. |
policy_digests |
SHA-256 of the tool policy as applied (the version's with the guardrails appended), of the sandbox policy, and the guardrails' names. |
input_digest, output_digest |
SHA-256 of the input, and of the output (the worker's log when it ended). |
started_at, finished_at, exit |
When, and how it ended: Completed, Failed or Cancelled, the exit code, why. |
calls |
The steps as a Merkle tree: how many trace and activity entries, their root (RFC 6962), and whether older entries had been rotated away. |
approvals |
Each approval the run used: name, decision, who, when. |
totals |
Model calls, input and output tokens, cache tokens, provider-tool calls, cost, tool calls, steps refused. |
The full format and how each digest is computed are in Receipt format.
Signed twice, chained#
flowchart LR
M[Machine<br/>signs the receipt] --> C[Cluster<br/>checks it against the run<br/>countersigns it]
C --> N[Receipt n of the agent]
P[Receipt n−1] -->|its digest| C
- The machine signs it with its own key — its node identity key (ECDSA P-256, with its certificate) or, on a machine without one, a key of its own (Ed25519). This says: this is what ran here.
- The cluster checks it against the run as it knows it — the agent, version, specification and policy digests, input, machine — and refuses one that does not match.
- The cluster countersigns it with its public key set (the one
published as its JWKS) over the receipt's digest, the machine's key, the
receipt's place in the agent's chain (
seq) and the digest of the agent's previous receipt (prev). This says: the cluster received it from that machine, after that one.
Receipts are kept apart from the agent, immutable: deleting an agent leaves its runs' receipts on the record. They are kept as long as the workspace's retention says (forever by default, never less than 30 days, and at least as long as evidence packs).
What verifying proves#
| Check | Needs | Proves |
|---|---|---|
format |
the receipt | It is a version 1 receipt. |
machine signature |
the receipt | The machine's key signed exactly this receipt. |
machine certificate |
the receipt, optionally the node CA | The key belongs to the machine named (when the machine has a certificate). |
countersignature |
the cluster's JWKS | The cluster countersigned this receipt, from this machine's key, for this run. |
chain |
the previous receipt | It follows that receipt directly: none was removed between them. |
trace |
the exported steps | These steps are exactly the ones the receipt covers (count and Merkle root). |
The console checks what a browser can on the run's Receipt tab;
astra anemoi receipts verify checks everything offline. See
Verify a receipt.
A receipt is not anchored outside the cluster (no transparency log).