AXR/Agent eXecution Receipts/Open source · MIT

Make the agent show its receipts.

AXR is an open-source accountability layer for AI agents and automated workflows: cryptographically signed, tamper-evident execution receipts that turn "trust me" into "verify me". It is live in production today, anchored hourly, and verifiable by anyone holding the public key.

Protocol contract 1.5.3 (frozen 1.x)Live profile 0.2.1 core · hourly anchoringDependencies Zero
9
Maturity layers, one repo — core to the witness lifecycle + SDK
42
Test suites green, incl. JS↔Python cross-impl parity (core + governance)
15 / 15
Tamper mutations rejected by the verifier
2
Independent verifiers (Node + pure-Python) agree byte-for-byte
15
Security findings caught by multi-agent review before release
0
Runtime dependencies — standard crypto only

Logs can be edited. That used to be fine.

AI agents now take consequential actions: they call tools, change records, move money, send messages on someone's behalf. The audit trail for all of that is usually a log file owned by whoever ran the agent — mutable, deletable, and unverifiable by anyone outside the operator's own infrastructure.

After the fact, there is no reliable way to answer the questions that matter: which agent did this, what did it receive as input, what did it decide and on what basis, was the record altered afterwards, and why was a customer told "no"?

Regulators have noticed. The EU AI Act makes automatic event logging a design requirement for high-risk AI systems (Article 12), obliges deployers to retain those logs (Article 26), and its high-risk obligations apply from 2 August 2026. In the US, NIST's Center for AI Standards and Innovation launched the AI Agent Standards Initiative in February 2026, with agent security and identity as core pillars.

A log you can rewrite is a story. A receipt you can verify is a record.

One receipt per consequential action.

For each action that matters, AXR emits a receipt: the action taken, hashes of its inputs and outputs, a timestamp, the identity of the agent, and an Ed25519 signature over the canonicalised record. It proves one thing precisely — that a given workflow, on a given input, made a given decision, and that the record has not changed since.

That buys two distinct things. Tamper-evidence is the cryptographic floor: the signature proves the record has not changed. Behavioral legibility is what earns its keep day to day — the receipt makes the workflow's actual behaviour readable enough that an internal contradiction surfaces even when nothing was tampered with and every signature is valid.

It is deliberately not a workflow builder, an agent framework, or an observability platform. It is the thin accountability layer that sits underneath those tools. Two receipt types carry the load: a step receipt records a single decision-relevant node, and a workflow receipt ties one run's steps into a signed, chained record. Steps chain within a run; runs chain across an agent's history — so deleting any receipt breaks the chain, and altering any receipt breaks the signature.

Illustrative step receipt — the shape of one signed action

{
  "axr_version": "0.2.1",
  "agent_id":    "axr:agent:eco-clean:v5.1",
  "step": { "name": "Create Booking", "kind": "side_effecting" },
  "io": {
    "input_hash":  "sha256:9f2c…b41a",
    "output_hash": "sha256:1d7e…0c88",
    "decision":    "BOOKING_CONFIRMED"
  },
  "logic_version": "5.1",
  "logic_hash":    "sha256:a3b9…77e2",
  "previous_receipt_hash": "sha256:5c10…d9f3",
  "timestamp":  "2026-06-13T09:14:22Z",
  "signature":  "ed25519:K8f…/Qb2Aw=="
}
Signature valid Change one byte of any field and the signature no longer verifies. That is the whole principle — and it is enough.

Built for the people who have to answer for it.

AXR earns its keep wherever an automated decision can be questioned later and someone has to stand behind the answer.

Teams running AI agents

You ship agents that take real actions

They book, price, message, move money or change records on someone’s behalf. Today the only account of what happened is a log file you own and could edit.

What you get: A signed receipt per consequential action — proof, not an editable story.

Compliance & GRC

You answer for the EU AI Act

Article 12 makes automatic event logging a design requirement for high-risk systems; Article 26 puts retention on deployers, applying from 2 August 2026.

What you get: Records designed to map onto those duties, with an auditor-ready report.

Auditors & investigators

You need to verify, not to trust

After the fact you have to establish which agent did what, on which input, and whether the record was altered — without taking the operator’s word for it.

What you get: Offline verification from nothing but a public key. No operator access needed.

Platform & infra builders

You want an accountability primitive

AXR is not an agent framework or an observability platform. It is the thin, boring layer those tools can sit on — standard crypto, zero dependencies, MIT.

What you get: A frozen wire format and two independent verifiers to build against.

Privacy officers

You owe the right to erasure

GDPR Article 17 erasure appears to fight an append-only log: how do you delete personal data from a record whose whole point is that it cannot change?

What you get: Field-level salted Merkle commitments — erase the cleartext, signatures still hold.

Security operations

You watch for tampering

An independent monitor turns latent protection into active detection: equivocation, truncation, history rewrites and unauthorized key swaps.

What you get: OCSF-shaped Detection Findings and webhook delivery into your SIEM.

Mark the steps. Sign the record. Anchor it where you can't rewrite it.

The receipt generator is a single Code node placed at the end of a workflow, before the response. It reads the outputs of the decision-relevant nodes and produces all receipts in one pass. Anchoring and monitoring run outside the workflow, so the live hot path gains no latency and no new dependency.

  1. Mark the decision nodes. Each decision-relevant node attaches the exact input it consumed, so the receipt hashes what the step actually saw — not a uniform proxy.
  2. Generate & sign. One pass emits the step and workflow receipts, each signed with Ed25519 over a canonical (RFC 8785) serialisation. Generation is fail-open: a missing key degrades to a loud error, it never breaks the business process it attests.
  3. Append to an immutable log. Receipts are written one per line to an append-only JSON Lines file that survives restarts.
  4. Anchor independently. A sidecar batches receipt hashes into an RFC 6962 Merkle tree and commits Signed Tree Heads to an external, append-only backend (OpenTimestamps/Bitcoin, Rekor, RFC 3161). This introduces a party the operator does not control — the honest analogy is Certificate Transparency, not self-signed HTTPS.
  5. Verify, by anyone. A standalone, zero-dependency script verifies a whole chain offline. Exit code 0 means valid, 1 means a problem was found.
  6. Monitor, over time. An independent monitor keeps its own journal of the tree heads it has witnessed and raises an alarm when a new view contradicts the old one — catching equivocation, truncation, history rewrites and unauthorized key swaps.

Verify a log yourself — the whole command:

# offline, zero dependencies, exit 0 = valid
node axr-verify.js receipts.jsonl public-key.pem sth.jsonl anchors.jsonl

# the same log, checked by a fully independent Python implementation
python3 axr_verify.py receipts.jsonl public-key.pem sth.jsonl anchors.jsonl

No terminal? Drop a log into the in-browser verifier — it runs the same signature, Merkle-root and witness checks locally, with nothing uploaded.

Boring primitives, on purpose.

Assurance work should be auditable by people who did not write it. So AXR uses only standard, well-understood building blocks — and states its goals plainly:

Signed
Ed25519 over a canonical serialisation of the receipt. Re-signing a tampered record requires the private key; without it, edits are visible.
Self-contained
A receipt verifies offline with nothing but the public key. No access to the operator's infrastructure, no trust in their database.
Tamper-evident
Any change to a receipt breaks its signature; deleting one breaks the chain. Anchoring then makes silent rewriting detectable, not just evident.
Boring on purpose
SHA-256, Ed25519, canonical JSON, RFC 6962 Merkle trees. No novel cryptography, and zero runtime dependencies.

One repository, layered by how far each part has earned trust.

AXR ships as a single repo spanning several maturity levels. The point of this table is honesty: read a feature's level before you depend on it. The 0.2 wire format is frozen — older logs verify byte-for-byte under the current verifier, and all later work is additive.

Layer Version Maturity
Core — signing, chaining, per-step input hashing, canonical JSON, cross-impl parity
Production-tested, frozen wire format; hardened n8n node.
0.2.1 Stable
Anchoring — Merkle batching, Signed Tree Heads, monitor, external timestamping
Hourly anchoring cron live in production; separate STH key.
0.3 Deployed
Redactable receipts, side-effect attestation, trust root, key-role separation
Tested; frozen in the 1.0 contract.
0.4 Stable
Key succession — root-anchored rotation, distinguishable from compromise
Cross-impl parity + adversarial review; not yet exercised by the pilot.
0.5 Stable
SIEM export — OCSF Detection Finding mapping + generic webhook
OCSF-shaped output; best-effort delivery by design.
0.6 Stable
Root-lifecycle hardening — quorum (M-of-N) root, rotation, revocation, ceremony CLI
Cross-impl parity; quorum policy is part of the threat model.
0.6 Stable
Control log — anchored governance distribution + partial disclosure
Closes the out-of-band withholding gap; 1.5 adds off-wire inclusion proof for a single record (prove one, reveal none of the rest).
0.7 – 1.5 Stable
Witness lifecycle — cosigning, emergency revocation, temporary auto-expiring suspension
Preventive equivocation defence; the full slow-revoke → revoke → suspend lifecycle, cross-impl.
0.8 – 1.4 Stable
Library SDK — require('axr'): a frozen public API surface + programmatic verify()
Surface pinned by a test; axr.verify() runs the canonical verifier, so it can never diverge.
1.2 – 1.3 Stable

An honest receipt makes silent failures loud.

AXR runs in production on a live booking workflow for ECO Clean HU — six of the workflow's twenty nodes are receipt-bearing, and the log — now past 227 signed receipts — has been anchored hourly into one Merkle tree since June 2026. Standing up that accountability layer did something its operator did not expect: it surfaced four real bugs that pre-dated AXR, and two defects in AXR's own tooling.

None of these involved tampering or an invalid signature. They are behavioral legibility, not tamper-evidence: the receipt made the run readable enough that a contradiction between intended and executed branch surfaced on its own. Bug B was exactly that — a rejection that still fired the success branch, caught the moment the receipt's outcome was read.

Pilot — Bug B

Every run was firing all three response branches at once: a ZONE_INCOMPATIBLE rejection still sent a success email. The receipt’s final_status made the contradiction immediate. Fixed with a Switch routing on the receipt outcome.

Pilot — Bug C

Rejections returned "unknown_error" with the customer’s own message echoed back — the real reason was lost. The receipt recorded the correct status on every run, contradicting what customers received.

Pilot — Bug D

A recheck conflict produced an HTTP 200 with an empty body, while the receipt was a complete, signed 5-step SLOT_TAKEN chain. The gap between a correct receipt and an empty response is exactly what AXR is built to surface.

Pilot — Bug E

After a bugfix bumped the logic to v5.1, every receipt kept attesting v5.0 — valid signatures over a false claim about which code decided. Now code-hash fingerprints replace hand-written labels, and CI fails on drift. Version labels are testimony; code hashes are evidence.

In AXR itself

A sandbox dry-run of the anchoring rollout caught two of AXR's own defects before they touched the live log: cross-version anchoring would have invalidated every legacy signature, and the Python verifier silently ignored the separate-key flag. Both fixed before the first production anchor was cut. A dry-run that breaks in a sandbox is a feature.

The "tamper-evident" claim, tested like an attacker would.

A claim of integrity is worth only as much as the attempts to break it. AXR proves its central claim systematically rather than rhetorically:

15 / 15 rejected
A single valid, anchored, generative receipt log is subjected to 15 distinct mutations — body tampering, step deletion, signature swaps, dropped tree heads, tampered inclusion proofs, wrong-key re-signing, and more. The verifier rejects all fifteen; the untouched control passes.
Two implementations
Credibility, the way Certificate Transparency earned it: a second, fully independent verifier in pure Python — its own canonicalizer, a pure-Python Ed25519 validated against the RFC 8032 test vectors, and the RFC 6962 Merkle logic. It must agree with the Node verifier on every accept and every reject.
Byte-identical
The "anyone can verify, in any language" promise rests on deterministic canonicalization. The serializer follows RFC 8785 and throws on NaN / Infinity / undefined rather than silently corrupting them. Cross-language byte vectors are pinned as the conformance contract.
CI on every push
The full suite — including JS↔Python parity — runs across Node 18 / 20 / 22 and Python 3.10 / 3.11 / 3.12 on every change.

Built toward where the rules are going.

AXR is designed to map onto the record-keeping duties that are arriving — not to claim certified compliance with any of them. The EU AI Act's Article 12 requires high-risk systems to automatically record events for traceability, and Article 26 puts retention on deployers. GDPR Article 17 pulls the other way, toward erasure. NIST's AI Agent Standards Initiative is shaping the US side around identity and auditability. Signed, independently verifiable receipts are a primitive every one of those directions can build on.

Two pieces make that concrete. Redactable receipts resolve the GDPR-versus-append-only tension: sensitive fields are committed through a salted field-level Merkle tree, so the cleartext can be erased later while the signature, the chain, and the already-anchored proof all still hold. And the Compliance Report Generator turns a raw log into an auditor-ready HTML report — integrity, the key-governance timeline, anchoring status, and an EU AI Act Art. 12 / GDPR control mapping.

Precision matters here: "designed to map onto" is the claim. The report is a view over the verifier's verdict, not a replacement for it, and it asserts nothing it did not check.

AXR proves its own construction.

AXR was built by a three-AI workbench — Fable, Meridian and NEXUS — over a shared, append-only journal. That journal is itself a verifiable AXR log: every entry is an Ed25519-signed receipt, the whole set is Merkle-anchored into one signed tree head, and that tree head was cosigned by the two reviewer agents — each in its own process, with a key it generated and held itself, so the orchestrator never saw a private key. The committed snapshot re-verifies under the full 1.0 stack, in your browser.

Honest framing: this proves the journal is unaltered since signing, not that any entry was true when written. The cosignatures are genuinely process-independent; the one remaining gap to full zero-trust is that custody is still same-machine — production runs the witnesses in separate security zones.

Live, open, and honest about both.

AXR is open source, MIT-licensed, and developed in public. Since 1.0 the wire format and the CLI/verifier contract are frozen for 1.x; 1.1–1.4 added only backward-compatible records and a frozen library SDK. The core and anchoring layers run in production; the higher layers — key succession, quorum roots, the control log, and the full witness lifecycle (cosigning, emergency revocation, temporary suspension) — are tested, cross-impl verified, and additive, but not yet exercised by the live pilot. The project stays honest about its own gaps:

  • NextSwitch the production anchor backend from local to OpenTimestamps (Bitcoin) — a single flag, once the cadence has run stably.
  • NextRun the independent monitor at a party outside the operator, turning split-view / equivocation detection from latent into active.
  • NextExercise generative (LLM) step receipts on a live workflow — supported and tested end-to-end, not yet in production.
  • NextError-path receipts — sign failed runs too, via a mark node on the workflow's error path. A failure is often the most important thing to have evidence of; this extends generator coverage and leaves the frozen 1.x wire format untouched.
  • OpenSelf-declared agent identity, and PEM-file (not hardware-grade) key storage — both deliberately out of the current scope.

This site runs on the same primitive.

Every deploy of chrisconen.dev publishes a manifest of every file on the site, hashed with SHA-256 and signed with Ed25519. Your browser can verify the signature and re-hash any file against the manifest. It is AXR's core idea applied to a build pipeline instead of an agent — same receipt, different actor.