Agent Action Receipts: Signed Evidence for What an AI Agent Did

Receipts or it didn't happen. A signed, hash-chained record of every adjudicated agent action that any third party can verify offline.

Ready to protect your own setup?

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:

  1. 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.
  2. Chained by hash. Each receipt’s chain_prev_hash is 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:

PropertyWhat the verifier checks
AuthenticityThe 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.
IntegrityThe 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.
LinkageWhen 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 receiptsWith 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

Receipts or it didn’t happen.

Frequently asked questions

What is an agent action receipt?
An agent action receipt is a self-contained, Ed25519-signed proof that an AI agent attempted an action, that a mediator inspected the action, and that the mediator returned a specific verdict. The receipt includes the action type, target, principal, delegation chain, policy hash, verdict, transport, and method. It is signed from outside the agent trust boundary so verification does not depend on the agent’s own logs. Receipts chain by hash so tampering with any one of them breaks every receipt that follows.
Why receipts instead of logs?
Logs are produced inside the trust boundary. A compromised agent can rewrite its own logs. A receipt is signed by a mediator outside the agent process and is verified against a pinned public key by a separate verifier binary. The verification step does not need to trust the agent, the logs, or the vendor dashboard. The verifier reads bytes, recomputes a hash, runs Ed25519, and emits accept or reject. That is the evidence property that logs do not have.
Who needs an agent action receipt?
Auditors performing a SOC 2, HIPAA, or PCI engagement that includes AI agent operations. Procurement teams writing AI-vendor questionnaires. CISOs answering ‘show me what the agent did.’ Customers asking their vendor to prove agent actions stayed inside policy. Insurance underwriters pricing AI-agent operational risk. Internal counsel building defensible records for delegated machine action.
How is this different from agent-audit tools like agent-audit-trail-mcp or AgentAudit?
Other agent-audit tools record what the agent did from inside the agent runtime. They serve well as developer tooling. Receipts come from outside the agent runtime, are signed by an independent mediator, and verify offline against a pinned public key. The distinction is independent attestation versus self-attestation. Both have value; only the independent-attestation form produces evidence a third party can rely on without trusting the agent.
Is the format proprietary to Pipelock?
The Pipelock implementation is the current reference, but the format is published as a JSON Schema at pipelab.org/schemas/audit-packet-v0.schema.json, the conformance corpus is public at agent-egress-bench/receipts/v0/conformance/, and verifier implementations exist in Go, TypeScript, Rust, and Python. Receipts are open evidence, not vendor-locked logs. The longer arc is to lift the primitive into existing standards bodies (CoSAI, IETF, OASIS) rather than to keep it as a Pipelock-controlled format.
What does a relying party do with the receipt?
Three steps. First, fetch the receipt and the producer’s public key out-of-band. Second, run the verifier of your choice (pipelock verify-receipt, pipelock-verifier receipt, pipelock-verifier-ts receipt, pipelock-verifier-rs receipt, or pipelock-verify) with the key pinned. Third, read the exit code: 0 accept, 1 reject, 2 verifier error, 64 usage error. A relying party with the corpus README in hand can run the verifier on golden, malicious, and edge fixtures to confirm the verifier itself behaves correctly before trusting it on real receipts.

Ready to protect your own setup?