Agent audit trails are built from cryptographic primitives that are genuinely standardised, wrapped in proposals that mostly are not. The difference decides what an auditor will accept. Here is what each piece actually rests on, who holds it, and how to check a standards claim yourself.
A tamper-evident agent audit trail needs three things: a deterministic way to serialise a record, a hash over that serialisation, and a signature. All three are settled, published and permanent. None of them is new, and none of them belongs to any vendor.
| Mechanism | Document | Custodian and status |
|---|---|---|
| Canonical JSON | RFC 8785 — JSON Canonicalization Scheme (JCS), 2020 | RFC Editor. Informational, Independent Submission |
| Hashing | FIPS 180-4 — Secure Hash Standard, 2015 | NIST. Federal standard; revision announced 2023 |
| Signing | RFC 8032 — Edwards-Curve Digital Signature Algorithm, January 2017 | RFC Editor. Informational, IRTF stream |
Neither RFC is IETF Standards Track. RFC 8785 is an Independent Submission and RFC 8032 comes through the IRTF. That is worth saying plainly, because "we implement IETF standards" is the kind of claim that sounds stronger than it is. What these documents do have is a permanent number, a fixed text, and a custodian who will still be holding them in ten years. That is the property that matters for evidence, and it is the property a proposal does not have.
Linking records so that each one commits to the content of the last is a technique from 1991 — Haber and Stornetta's work on timestamping digital documents. Every tamper-evident log since is a variation on it. The chain is unremarkable engineering, and anyone claiming it as an innovation is describing the state of the art in 1991.
prev_hash(N) = hex(SHA-256(canonical_json(record(N-1))))
Canonicalisation is the part people get wrong. JCS (RFC 8785) sorts object properties recursively by UTF-16 code unit, strips insignificant whitespace, fixes number formatting to IEEE 754 double-precision rules, and emits UTF-8. Two representations of the same logical record therefore produce identical bytes, and identical hashes. Change field content anywhere in the chain and every subsequent hash stops matching. Change only the field order, whitespace or number formatting and none of them does, which is the point of canonicalising.
That property is the whole value. Without a canonical form, a hash chain proves only that nobody reformatted your JSON.
The EU AI Act's Article 12 requires high-risk AI systems to technically allow the automatic recording of events (logs) over the lifetime of the system, with logging capabilities enabling a level of traceability of the system's functioning appropriate to its intended purpose. It names no file format, no hash algorithm and no schema.
Two dates worth knowing, because they moved. The Digital Omnibus on AI — Regulation (EU) 2026/1744, in force 27 July 2026 — deferred the high-risk obligations to 2 December 2027 for standalone Annex III systems and 2 August 2028 for AI embedded in regulated products. Article 12 itself was not amended. The reasons the regulation gives include the delayed availability of standards, common specifications and guidance, and the delayed establishment of national competent authorities.
One of the constraints the EU itself names on high-risk enforcement is an absent standard, in exactly this lane. That is why proposals in this space are appearing faster than they can be reviewed, and why the difference between a proposal and a standard is currently worth money to somebody.
ISO/IEC 42001 asks for evidence that an AI management system's controls operated. SOC 2 asks for integrity of the record. None of them tells you when in the lifecycle the record must be written — which is the question that decides whether your log is evidence of control or merely a description of events.
AgenticRail is a sequence-enforcement gate. It returns ALLOW, DENY or HALT, and it issues a signed receipt at the moment of the decision, before the action runs; the durable copy is stored just after. That timing is the substantive claim; the cryptography underneath it is the standard, unremarkable stack above.
{
"pack_id": "74598da63e1f...1fee",
"decision": "ALLOW",
"reasons": [],
"executed": true, // permitted — NOT proof the action performed
"sealed": false,
"decision_index": 2, // second decision in this sequence, ALLOW or DENY
"meta": {
"model_id": "client:acme-bank",
"sequence_id": "credit-approval-20261008-001",
"step": "disruption",
"function": "disruption",
"action_type": "CHECK_STATE",
"policy_map_ids": ["policy_disruption_distraction_signal",
"policy_disruption_somatic_override"]
},
"step_order": ["intake", "disruption", "instability", "state_read",
"internal_driver", "execution", "boundary", "settle"],
"attestation": null,
"payload_hash": "cfeb95664f30...4b7d",
"prev_receipt_id": "adc092661517...983a", // the intake receipt
"prev_receipt_hash": "4062ff4a9b8f...1dda", // SHA-256, canonical JSON
"ts_ms": 1791406826000, // caller-asserted, gate-bounded
"key_id": "k2_2026-06-07_ed25519",
"signature_alg": "Ed25519",
"signature": "meADmOaDu5ICJulE...", // base64, RFC 8032
"version": "slp8_receipt_v2"
}
Four fields carry the properties that are easy to overstate, so here is what each one does and does not assert.
| Field | What it establishes | What it does not |
|---|---|---|
executed | The enforcement decision was ALLOW — the step was permitted | That the downstream action ran, or succeeded. The executor outcome is not signed into the receipt. |
ts_ms | A time, covered by the signature, so it cannot be altered afterwards without breaking verification | That the time is true. The caller supplies it. The gate refuses anything more than 300 seconds from its own clock, so the claim is bounded, not attested. |
prev_receipt_hash | SHA-256 over the prior permitted receipt's full canonical JSON, signature included | Anything about refused steps: the chain runs through ALLOWED receipts only, so nothing links to a refusal. Nor protection against a signing-key holder rewriting the whole chain downstream; only an independently held copy catches that. |
decision_index | This decision's number among every decision in the sequence, permitted or refused, so a removed receipt of either kind leaves a missing number the report names | Anything missing after the highest number present, or why a number is missing: never written and removed look the same. |
A DENY carries the same structure with the reason named, which is the part compliance teams actually need:
{
"pack_id": "30cd50b4d80e...228e",
"decision": "DENY",
"reasons": ["SEQUENCE_VIOLATION"],
"executed": false,
"decision_index": 3,
"meta": {
"sequence_id": "credit-approval-20261008-001",
"step": "execution",
"function": "execution",
"action_type": "SELECT_NEXT_STEP"
},
"prev_receipt_id": "74598da63e1f...1fee", // the last ALLOW, not this step's neighbour
"prev_receipt_hash": "3ea779ee89e6...f96a",
"ts_ms": 1791406827000,
"key_id": "k2_2026-06-07_ed25519",
"signature_alg": "Ed25519",
"signature": "ILI+EH0igsYBZ7Ra...",
"version": "slp8_receipt_v2"
}
An auditor reading that knows not only that something was refused, but which rule fired and what the agent attempted. The sequence was enforced before the action, not described after it.
This is the part worth taking away, because it outlasts any particular document. Agent governance is currently full of specifications that sound settled and are not. The checks are quick, and you can run all of them from a browser.
Anyone can submit one. There is no review gate on submission, no endorsement implied by publication, and the document expires after six months. Every Internet-Draft carries this in its own Status of This Memo section:
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."
The IETF has ruled, in the document itself, on how it may be cited. If a vendor cites one as a specification they conform to, they are citing it in a way its own text calls inappropriate.
A working-group document is named draft-ietf-<wg>-<topic>. An individual submission is named draft-<surname>-<topic> (the convention is described in RFC 7221). The second form means one person wrote it and posted it. It may still be excellent work — but no working group has adopted it, and no review has occurred.
datatracker.ietf.org shows every draft's stream, working group, IESG state, revision history and expiry date, free and without an account. It takes about thirty seconds. A document with no working group, no IESG state and an expiry date a few months out is a proposal, whatever a website calls it.
It has a permanent number, a text that is never revised, and it cannot expire. But read its stream too: Standards Track, Informational, Experimental and Independent Submission are not equivalent, and the two RFCs at the top of this page are Informational.
Several proposals define trust or assurance tiers and imply they map onto recognised frameworks. They generally do not. NIST SP 800-63-4 — which superseded 800-63-3 in August 2025 — defines three levels each for identity, authenticator and federation assurance. ISO/IEC 29115:2013 defines four levels of entity authentication assurance and is itself under revision. A five-tier ladder matches neither. If somebody's levels do not line up with a named framework, they are that author's own construction, and an auditor will treat them as such.
A citation is worth the standing of whoever holds the document, not the quality of the argument in it. A regulator, a statute or a standards body is citable. A six-month proposal is not, however good the work — and treating it as one lends your credibility to it rather than borrowing any.
The cryptography in an agent audit trail is settled and shared: canonical JSON per RFC 8785, SHA-256 per FIPS 180-4, Ed25519 per RFC 8032, chained the way tamper-evident logs have been chained since 1991. Nobody in this market owns those, and any product claiming otherwise is describing the state of the art in someone else's field.
What is genuinely unsettled is when the record gets written and who writes it. A log produced by the agent after the fact is a description of events. A receipt signed by an independent gate at the moment of authorisation, before the action runs, is evidence that a control operated. Both can be hash-chained. Only one answers the question an auditor is actually asking.
Run a sequence through AgenticRail and inspect the receipts - canonical JSON, SHA-256 chained, Ed25519-signed, issued before the action runs.
Open Demo Read Docs