To prove what an AI agent did, you need evidence that survives distrust: a record of the agent's output that a third party can verify without trusting you, your logs, or your infrastructure. The standard technique is hashing — compute a SHA-256 fingerprint of what the agent produced, then have that fingerprint signed and timestamped by a party who has no stake in the outcome. This guide covers when you need this, the three levels of attestation strength, and working code to add receipts to any agent in one HTTP call.
Agents increasingly do things that other parties care about: merge code, file reports, execute purchases, publish packages, make decisions about people. When something is later disputed — did the agent really deliver that file? was the report altered after the fact? which version of the model output was shown to the customer? — the operator's own logs are the first thing the other side challenges. You wrote them; you can rewrite them. Traces and observability dashboards are built for debugging, not for evidence.
Attestation schemes differ in one dimension that matters: who holds the signing key.
| Level | Key holder | Proves | Fails when |
|---|---|---|---|
| 1. Self-attestation | The agent process itself | Useful for debugging, internal audit trails, correlating runs | Anyone questions the agent or its operator — the signer is the party being questioned |
| 2. Operator attestation | The runtime / platform running the agent | The platform observed this action (stronger than the agent's own claim) | The dispute involves the operator — they hold the key and the logs |
| 3. Independent witness | A third party outside the operator's deployment | This exact content existed at this time, attested by someone with nothing to gain | The witness itself is compromised (mitigate: HSM keys, immutable storage, offline verification) |
Most agent frameworks ship level 1 (an SDK signing its own receipts) or level 2 (platform traces). Both are the right tool for observability. Neither survives the question "why should I believe your logs?" — for that you need level 3: a witness that is structurally incapable of taking your side, with keys held in an HSM and records in storage nobody can rewrite.
The pattern is the same regardless of provider: hash the artifact, send only the hash (content never leaves your system), store the receipt ID with the work. With mpps.io — free, no API key — after an agent finishes a task:
> HASH=$(sha256sum final-report.md | awk '{print "sha256:" $1}') curl -X POST https://api.mpps.io/v1/receipts \ -H "Content-Type: application/json" \ -d "{ \"action\": \"agent.task.complete\", \"subject\": \"final-report.md\", \"artifact_hashes\": [{\"label\": \"final-report.md\", \"sha256\": \"$HASH\"}], \"context\": {\"runner\": \"claude-code\", \"repo\": \"acme/reports\", \"commit\": \"abc123\"} }"
Python, inside an agent or pipeline:
import hashlib, requests
artifact = open("final-report.md", "rb").read()
h = "sha256:" + hashlib.sha256(artifact).hexdigest()
receipt = requests.post("https://api.mpps.io/v1/receipts", json={
"action": "agent.task.complete",
"subject": "final-report.md",
"artifact_hashes": [{"label": "final-report.md", "sha256": h}],
"context": {"runner": "my-agent", "task_id": "T-4821"},
}, timeout=30).json()
print(receipt["uuid"], receipt["verify_url"])
The response contains the receipt UUID, an RSA-PSS signature produced inside an AWS KMS HSM, a timestamp, and a verify URL. The receipt is stored in S3 Object Lock (Compliance Mode, 10-year retention) — storage the operator cannot modify or delete early, by AWS's own enforcement.
Online: GET https://api.mpps.io/v1/verify/<uuid> returns the receipt with its signature. Offline: fetch the public key once from api.mpps.io/v1/public-key (also mirrored in the open-source repo) and verify the RSA-PSS SHA-256 signature with OpenSSL or any crypto library — no dependence on mpps.io being alive. Then recompute the artifact's hash and compare. Match = this exact content existed no later than the receipt's timestamp.
parent_uuid to link a receipt to the receipt of its inputs — a verifiable pipeline lineage.Software supply chains went through this exact transition: from "trust my build server" to signed provenance (SLSA), from "trust this image" to content credentials (C2PA). Agent work is next: the EU AI Act already requires tamper-evident event records for high-risk systems, and platforms and insurers are following. The cost of adding a receipt is one HTTP call at the end of a task; the cost of not having one is arguing about whose logs to believe.