Most agent security tools tell you what the agent did from inside the agent. An action receipt tells you what the agent did from outside, signs the record with a key the agent cannot reach, and lets any third party verify the record without trusting the vendor that produced it.
That is the difference between a log and evidence.
What a receipt is
A receipt is a JSON record with three parts:
- An action_record describing what happened: action type, target, principal, delegation chain, policy hash, verdict, transport, method, and a chain pointer to the prior receipt.
- An Ed25519 signature over
SHA-256(canonical-JSON(action_record)). - The signer_key as a 32-byte hex string.
The exact bytes are documented in the action receipt spec. Two important properties of the format:
- Signed from outside the agent. Pipelock signs receipts from the mediator process. The agent has no access to the signing key. A compromised agent cannot forge a receipt because the verifier checks the signature against the pinned mediator public key.
- Chained by hash. Each receipt’s
chain_prev_hashis the SHA-256 of the previous receipt’s bytes. Removing or reordering any receipt in the chain breaks the linkage and the verifier rejects.
The chain compounds into an evidence.jsonl flight recorder file with
one receipt per line. The Audit Packet v0 bundle wraps that file with
policy metadata, totals, and a verifier output for delivery to an
auditor or procurement team.
Receipts or it didn’t happen
If a relying party cannot independently verify that an agent action happened, was inspected, and was adjudicated, then telling them the action happened is a statement of trust, not evidence. The whole point of the receipt is to remove that trust requirement.
Three independently relevant facts a passing verification proves:
| Property | What the verifier checks |
|---|---|
| Authenticity | The signature is a valid Ed25519 signature over the canonical hash of the action_record, produced by the holder of the pinned mediator private key. A foreign key fails this check. |
| Integrity | The verifier recomputes the canonical-JSON hash from the current bytes of action_record. If any byte changed after signing, the recomputed hash disagrees with the one the signature was produced over. A post-sign edit fails this check. |
| Linkage | When verifying a chain, each receipt’s chain_prev_hash is checked against the SHA-256 of the previous receipt’s bytes. Cutting a receipt out or splicing in a foreign one breaks the chain. |
Add the relying-party policy on top: pinned signer key, max receipt age, replay window, schema version, strict JSON parsing. The conformance corpus README documents the exact policy assumptions the public verifiers use.
How receipts get produced
The Pipelock proxy emits a receipt for every mediated action. Sources:
- Every HTTP request the agent issues through the forward proxy or CONNECT tunnel.
- Every MCP tool call routed through the MCP proxy, whether stdio or streamable HTTP.
- Every WebSocket frame in both directions on the WebSocket proxy.
- Tool list responses scanned for poisoning, with the tool baseline pinned per session for rug-pull detection.
Receipts append to the hash-chained flight recorder. The pipelock-agent-egress-action GitHub Action bundles the chain with policy metadata into a complete Audit Packet on every CI run.
How a third party verifies
Four shipped verifiers expose the same receipt and chain verification surface across Go, TypeScript, Rust, and Python:
# Single receipt with the main Pipelock binary
pipelock verify-receipt receipt.json
# Single receipt with the standalone verifier
pipelock-verifier receipt receipt.json
# A full chain
pipelock-verifier chain evidence.jsonl
# A complete Audit Packet bundle
pipelock-verifier audit-packet ./audit-packet/
The common exit-code contract is 0 valid, 1 invalid, 2 runtime
error, 64 usage error. The
verify-a-receipt walkthrough runs each
command against the public conformance corpus with copy-paste-ready
input and expected output.
What receipts replace
| Without receipts | With receipts |
|---|---|
| “The agent’s logs say the request was blocked.” | “The mediator signed evidence that the request was blocked, and the auditor verified the signature offline.” |
| “Trust our dashboard.” | “Verify the bundle locally with a binary you build from source.” |
| “We retain audit logs for six months.” | “We retain signed evidence for as long as the relying party’s policy requires, and the relying party can re-verify any time.” |
| “The vendor was hacked, we lost the logs.” | “The signing key was rotated; pre-rotation receipts remain verifiable against the prior public key; the chain self-documents the rotation point.” |
Where receipts go next
The current shipped target is procurement evidence: receipts as the artifact auditors, customers, and internal counsel can rely on without trusting the vendor that produced them. The longer arc is portable runtime proof for delegated software actions in general, which is why the format is published as a JSON Schema and the verifier is open source.
Where to go next
- Verify a Pipelock receipt: the copy-paste walkthrough that proves the verifier on the public corpus.
- Action receipt format spec: exact bytes on the wire, canonical JSON rules, signature math.
- AARP v0.1 spec: the assurance profile that appraises a signed receipt and separates verified claims from producer claims.
- Verifiable egress control: how receipts fit the broader category of binary-enforced egress with evidence.
- Compliance evidence substrate: what receipts buy you in a SOC 2, HIPAA, or PCI engagement.
- Audit Packet v0 schema: the bundle format wrapping the receipt chain.
Receipts or it didn’t happen.