Verify a receipt#
Every agent run leaves a signed receipt when it ends (see Receipts). This page shows how to read it, and how to check it offline — its signatures, its place in the agent's chain and the steps it covers — with nothing but files.
Before you begin#
- Any role in the workspace reads receipts.
astraon the computer that checks (Install the CLI).astra anemoi receipts verifyneeds no sign-in and no network.- For the downloads:
ASTRA_TOKENandWSas in the REST API page.
1. Read it#
Open the run and its Receipt tab: the run's version, policies' and input's and output's digests, Steps (Merkle root), Tokens · cost, the approvals it used, and the checks your browser made (machine signature, countersignature, chain). No receipt yet until the run ends; its machine sends it within seconds.
$ curl -sS "$WS/agents/researcher/runs/researcher-d2b797/receipt" -H "Authorization: Bearer $ASTRA_TOKEN" \
| jq '{receipt: .receipt | {run, agent, agent_version, exit, totals, calls}, seq: .countersignature.claims.seq}'
$ curl -sS "$WS/agents/researcher/receipts?limit=10" -H "Authorization: Bearer $ASTRA_TOKEN" \
| jq -r '.items[] | [.countersignature.claims.seq, .receipt.run] | @tsv'
receipts is the agent's chain, newest first (50 by default, at most
1 000).
2. Save the files#
| File | From | Needed for |
|---|---|---|
| The receipt | Download receipt, or GET $WS/agents/{agent}/runs/{run}/receipt |
Everything. Save it as served, byte for byte. |
| The cluster's keys | GET $WS/identity/jwks (public) |
The countersignature. Save it once, when you trust the cluster, and reuse it. |
| The previous receipt | Download the previous one, or the chain listing | The chain link. |
| The exported steps | Download the steps it covers, or GET $WS/tasks/{run}-0/trace?canonical=1&format=jsonl |
The Merkle root. While the machine still keeps them (7 days after the run is gone from it by default). |
| The node CA (PEM) | optional | Who issued the machine's certificate. |
$ R=researcher-d2b797
$ curl -sS "$WS/agents/researcher/runs/$R/receipt" -H "Authorization: Bearer $ASTRA_TOKEN" -o $R.receipt.json
$ curl -sS "$WS/identity/jwks" -H "Authorization: Bearer $ASTRA_TOKEN" -o jwks.json
$ curl -sS "$WS/tasks/$R-0/trace?canonical=1&format=jsonl" -H "Authorization: Bearer $ASTRA_TOKEN" -o $R.trace.jsonl
3. Verify#
$ astra anemoi receipts verify researcher-d2b797.receipt.json --jwks jwks.json \
--prev researcher-9c01aa.receipt.json --trace researcher-d2b797.trace.jsonl
It prints the receipt's run, agent and digest, then one line per check —
ok, failed or skipped, with what it found — and verified or NOT
verified. The exit status is 1 when a check failed.
| Check | Fails when |
|---|---|
format |
It is not a version 1 receipt. |
machine signature |
The receipt was changed after the machine signed it. |
machine certificate |
The certificate does not name the machine, or (with --node-ca) was not issued by that CA. Skipped on a machine without a certificate. |
countersignature |
It is not signed by a key of the JWKS, or it countersigns another receipt, machine key, run or machine. Without one: the cluster did not countersign it. |
chain |
The receipt does not follow the one given (--prev) directly. |
trace |
The lines are not the receipt's: their count or Merkle root differ. |
What is not given is skipped, and said.
| Flag | Description |
|---|---|
<receipt> |
The receipt (JSON, as served). |
--jwks <file> |
The cluster's JWKS, saved. |
--cluster <url> |
Fetch the JWKS from <url>/v1/identity/jwks now instead — the one step that is not offline. Not with --jwks. |
--prev <file> |
The agent's previous receipt. |
--node-ca <file> |
The node CA (PEM). |
--trace <file> |
The exported steps: JSON lines, or the format=json export ({"lines": [...]}). |
--json |
Print {ok, receipt_digest, checks: [{name, result, detail}]}. |
astra anemoi receipt verify is the same command.