Skip to content

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
  1. 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.
  2. 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.
  3. 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).