2026-05-12 · reviewed 2026-08-23

IETF Agent Audit Trail: What the Draft Standard Requires — and What It Doesn't

There is a live IETF Internet-Draft proposing a JSON format for AI agent audit records with hash chaining, trust levels, and mandatory fields. It cites EU AI Act Article 12 and ISO/IEC 42001. Here is what the draft requires, where it leaves gaps, and how AgenticRail aligns with — and goes beyond — it.

The Draft

draft-sharif-agent-audit-trail is an IETF Internet-Draft defining a standardised format for audit records produced by AI agent systems. It was published to address the absence of a common structure for agent audit logs — the gap that makes compliance attestation difficult when every deployment invents its own schema.

The draft expires September 29, 2026. At that point it either advances toward RFC status, is revised, or lapses. For now it represents the most developed public proposal that developers, auditors, and compliance teams can reference when building or evaluating agent audit infrastructure.

Draft Reference

draft-sharif-agent-audit-trail — IETF Internet-Draft, version -01, published 19 August 2026 (status re-verified 23 August 2026). Expires 2027-02-19. Regulatory references: EU AI Act Article 12, ISO/IEC 42001, SOC 2, PCI DSS.

Mandatory Fields

Every audit record under the draft must include the following fields. Optional fields can be added, but omitting any mandatory field renders the record non-conformant. Revision -01 added a twelfth: record_phase, carrying pre_execution, post_execution or concurrent.

Field Required Description
record_idRequiredUnique identifier for this record
timestampRequiredISO 8601 timestamp of the event
agent_idRequiredIdentifier of the agent that produced the record
agent_versionRequiredVersion string for the agent
session_idRequiredGroups all records from one agent session
action_typeRequiredCategorises the action (e.g. tool_call, lifecycle)
action_detailRequiredStructured object describing the specific action
outcomeRequiredResult: success / failure / timeout / denied / escalated
trust_levelRequiredL0–L4 verification assurance level
parent_record_idRequiredRecord that triggered this one (null for genesis)
prev_hashRequiredHash of the prior record; null for genesis

The session_id + prev_hash combination is what turns individual records into a chain. Every record knows what session it belongs to and cryptographically commits to the content of the record before it. This means you cannot insert, delete, or alter any record in the chain without invalidating all subsequent prev_hash values.

The Hash Formula

The draft specifies SHA-256 over JSON Canonicalization Scheme output (RFC 8785):

Hash chain formula
prev_hash(N) = hex(SHA-256(JCS(record(N-1))))

JCS (RFC 8785) produces a deterministic, canonicalised JSON encoding: alphabetically sorted keys, no insignificant whitespace, Unicode normalisation. The key property: two representations of the same logical record produce identical JCS output, and therefore identical hashes. Conversely, any change to field content, field order, or encoding in a prior record will produce a different hash, breaking the chain at the next record.

The genesis record — the session start record — has prev_hash: null and parent_record_id: null. It uses action_type: "lifecycle" and action_detail.event: "session_start". All subsequent records in the session chain back to it.

AgenticRail alignment

AgenticRail signs receipts with Ed25519 over canonical JSON (alphabetically sorted keys), and chains them with SHA-256 over the same canonicalisation via prev_receipt_hash (the draft's prev_hash) — the same structure the draft mandates. The sequence_id field maps directly to the draft's session_id.

Trust Levels

The trust_level field is mandatory on every record. The draft defines five levels:

L0
No verification. The agent asserts its identity and produces records with no external check. Records can be self-reported and cannot be independently verified.
L1
Self-signed. The agent signs its own records using a key it controls. The signature proves record integrity but doesn't verify the signing key itself came from a trusted authority.
L2
Authority-signed. A trusted third party countersigns or issues records. The signing key is externally verifiable.
L3
Mutual authentication. Both the agent and its counterparty verify each other's identity before records are produced.
L4
Full mutual auth with certificate revocation checking and continuous monitoring. The highest assurance level — every verification is checked against live revocation data.

Most production deployments today operate at L0 or L1. Compliance contexts targeting EU AI Act or ISO 42001 should aim for L2 minimum — authority-signed records that an auditor can verify without trusting the agent itself.

Special Record Types

Genesis Record

The first record in every session. Marks session initialisation. parent_record_id and prev_hash are both null. All records in the session chain back to this one.

Genesis record structure
{
  "record_id": "rec_0001",
  "timestamp": "2026-05-12T09:00:00Z",
  "session_id": "sess_abc123",
  "agent_id": "credit-approval-agent",
  "agent_version": "1.4.2",
  "action_type": "lifecycle",
  "action_detail": { "event": "session_start" },
  "outcome": "success",
  "trust_level": "L2",
  "parent_record_id": null,
  "prev_hash": null
}

Tombstone Record

Used for GDPR-compliant deletion. When personal data in a record must be erased, a tombstone replaces the original record. The tombstone preserves the record_id, timestamp, and chain linkage fields (prev_hash, parent_record_id) so chain integrity is maintained, while removing the personal data. This lets you honour right-to-erasure requests without destroying audit chain continuity.

What the Draft Requires

The draft is explicit about structure. It requires:

In revision -00 it specified none of the following: how long records must be retained, which storage backend to use, whether the recording system must be independent of the agent, or when in the action lifecycle the record must be written. Revision -01, published 19 August 2026, addressed all four. Retention now has floors (12 months for high-risk systems, 6 for general-purpose). Appendix C.6 recommends a two-plane store held by different principals. Section 5 sets out when an agent may write its own records and when an independent component should. Section 4 requires pre-execution records for denied and escalated decisions, and for state-modifying actions in high-risk systems. The remarks below were written against -00 and are kept because the direction of travel is the point: the gap argued here is narrower than it was, and it narrowed by the draft moving.

The Gap: Pre-Execution Recording

The most significant gap in revision -00 was timing: it defined records of events that occurred, recording outcomes after actions complete. Revision -01 closed most of it. Section 4 now requires a pre-execution record for denied and escalated decisions, and for state-modifying actions in high-risk systems, and a new mandatory record_phase field makes the timing of every record explicit rather than inferred. What remains is narrower and worth stating precisely: a permitted, non-state-modifying action in a system not classed high-risk can still be recorded after the fact and be fully conformant. The outcome values reflect completion states: success, failure, timeout, denied, escalated.

This means a fully conformant implementation could write all records after execution. An agent could complete every action in a session and then produce a conformant, hash-chained audit log retroactively. The chain would be internally consistent. The hashes would verify. But the records would not prove that any enforcement gate fired before execution — they would only record what the agent reported about itself.

Critical gap

Under -01 the draft requires a record at the moment of authorisation for the cases most likely to be disputed — refusals, escalations, and state-modifying actions in high-risk systems. Outside those cases a post-execution log remains fully draft-conformant. AgenticRail writes the record before the action for every decision, permits included, which is a difference of scope rather than of kind now.

This matters for EU AI Act Article 12. Article 12 requires logs enabling reconstruction of the sequence of events — which implies the log must be a faithful record of what was enforced, not a summary written after the fact by the system being audited.

How AgenticRail Aligns With the Draft

Draft Requirement AgenticRail Status
SHA-256 over canonical JSON SHA-256 over canonical JSON for the receipt chain (prev_receipt_hash); Ed25519 signatures over the same canonicalisation Aligned
session_id groups records sequence_id groups all receipts in a session chain Aligned
denied outcome value DENY decisions map to denied outcome; specific reason codes also provided Aligned
Tamper-evident record storage Receipts written to tamper-evident storage, Ed25519-signed at write time; sealed sequences copied to an independently held archive Aligned
Trust level per record Gate enforces key verification on all requests; receipts are signed by the gate — an authority independent of the agent (L2 characteristics) Aligned

Where AgenticRail Goes Further

Capability Draft standard AgenticRail
Record timing -01 §4: pre-execution records required for denied and escalated decisions, and for state-modifying actions in high-risk systems Pre-execution on every decision, permits included — receipt written at gate decision time, before action runs
Step order enforcement Not specified — records are individual events, no sequence enforcement Strict step-order enforced across session; SEQUENCE_VIOLATION returned for out-of-order steps
Replay protection -01 §3.2: optional nonce field, RECOMMENDED at L2+; replay covered in §13.5 Nonce ledger per session; REPLAY_NONCE for any reused nonce
Sequence sealing Not specified Session sealed at final step; SEALED_SEQUENCE for any subsequent request
DENY reason codes -01 §3.2: optional deny_reasons field with nine defined codes SEQUENCE_VIOLATION / REPLAY_NONCE / ACTION_NOT_ALLOWED / UNKNOWN_STEP / SEALED_SEQUENCE / STALE_TIMESTAMP / ARTIFACT_UNBOUND
Timestamp freshness -01 §3.2: optional external_timestamp for RFC 3161 anchoring, RECOMMENDED at L3+ |ts_ms − now| > 300s → STALE_TIMESTAMP, so the caller's asserted time is bounded by the gate's clock. No RFC 3161 token is issued — on this dimension -01 asks for more than AgenticRail provides.No RFC 3161 token is issued — on this dimension -01 asks for more than AgenticRail provides.

An AgenticRail Receipt Mapped to Draft Fields

Here is an AgenticRail ALLOW receipt with the IETF draft fields mapped:

AgenticRail receipt — IETF field mapping
{
  // draft: record_id (SHA-256, 64 hex chars)
  "pack_id": "24449424694a3f...e020",

  // draft: outcome ("success" / "denied")
  "decision": "ALLOW",
  "reasons": [],
  "executed": true, // permitted — not proof the downstream action performed

  // draft: session_id, agent identity, action_type, action_detail — carried in meta
  "meta": {
    "model_id": "client:acme-bank",
    "sequence_id": "credit-approval-20260512-001",
    "step": "intake",
    "function": "intake",
    "action_type": "CHECK_STATE"
  },

  // binds the full request — nonce, inputs, labels — into the record
  "payload_hash": "9080bd2ac4da...86cb",

  // draft: prev_hash — SHA-256 of the prior receipt's canonical JSON
  "prev_receipt_id": "a7f3c91b22e0...54da",
  "prev_receipt_hash": "b6a18d234e38...338d",

  // draft: timestamp
  "ts_ms": 1715507244154,

  "key_id": "k2_2026-06-07_ed25519",
  "signature_alg": "Ed25519",
  "signature": "TpQr8f3aXz9c2b1d...", // base64, over the canonical receipt
  "version": "slp8_pack_1.0"
}

The structural alignment is clear. And the pre-execution property needs no special field: the receipt is the gate decision, written at the moment of authorisation, before the action runs. The executed field records that the step was permitted — deliberately not a claim that the downstream action performed.

DENY Receipt: The denied Outcome

AgenticRail DENY — maps to draft outcome: "denied"
{
  "pack_id": "0098a55bab90...823e",

  // draft outcome: "denied"
  "decision": "DENY",

  // AgenticRail extension: specific reason codes, as an array
  "reasons": ["SEQUENCE_VIOLATION"],
  "executed": false,

  "meta": {
    "model_id": "client:acme-bank",
    "sequence_id": "credit-approval-20260512-001",
    "step": "execution",
    "function": "execution",
    "action_type": "SELECT_NEXT_STEP"
  },

  "payload_hash": "b6a18d234e38...338d",
  "prev_receipt_hash": "b1d8e27c9a04...61f2",
  "ts_ms": 1715507311208,
  "key_id": "k2_2026-06-07_ed25519",
  "signature_alg": "Ed25519",
  "signature": "Nq4wRz1c8f3aXz9c..."
}

The draft records denied. AgenticRail records DENY with SEQUENCE_VIOLATION in its reasons array — a step was submitted out of order. An auditor reading this receipt knows not just that something was denied, but exactly which policy rule fired and what the agent attempted.

Regulatory Context

The draft explicitly references the following regulatory frameworks:

Framework Relevant Requirement Draft coverage
EU AI Act Article 12 Automatic recording of events enabling reconstruction of the sequence Structural — no pre-execution mandate
EU AI Act Article 26 Deployers retain logs at least 6 months Not specified — retention policy outside draft scope
ISO/IEC 42001 AI management system risk controls and evidence Structure aligns; enforcement controls outside draft scope
SOC 2 Availability, confidentiality, integrity controls Hash chain satisfies integrity; storage controls outside draft scope
PCI DSS Audit log completeness and tamper evidence Chain tamper evidence aligns; field completeness depends on implementation

The draft is a structural foundation. It defines how records relate to each other and what fields every record must carry. It does not specify the enforcement architecture that produces those records — that is left to implementors. For EU AI Act purposes, the draft alone gets you a well-formed log. Pre-execution enforcement is what makes that log admissible as evidence of control rather than observation.

What This Means in Practice

If you are evaluating agent audit infrastructure against the IETF draft, the questions to ask are:

  1. When is the record written? At action completion, or at gate decision time before execution? The draft allows both. Only pre-execution records provide enforcement evidence.
  2. Who writes the record? The agent itself (L0/L1), or an independent gate (L2+)? The draft requires trust level to be declared — it does not require independence. Auditors will ask.
  3. Are all 11 mandatory fields present? Missing any one — including trust_level or prev_hash — makes the record non-conformant.
  4. Is the chain verifiable independently? JCS canonicalisation must be reproducible without the original system. Verify hashes offline before claiming chain integrity.
  5. What does denied mean in your implementation? The draft has one denied outcome. What rule fired? Which step was out of order? Reason codes are not required by the draft — but they are what compliance teams and auditors actually need.
11 Mandatory fields per record
L0–L4 Trust verification levels
RFC 8785 Canonicalisation standard (JCS)
2026-09-29 Draft expiry date

Summary

The IETF agent audit trail draft is the right structural starting point. It defines a hash-chained, tamper-evident record format with trust levels and mandatory fields that map cleanly onto EU AI Act, ISO 42001, and other compliance frameworks. If you are building agent audit infrastructure, building to the draft gives you a schema that regulators and auditors will recognise.

The gap the draft leaves open is enforcement. A conformant log can be written post-hoc by the agent itself. For compliance contexts where the question is not just "what happened?" but "what was the agent permitted to do, and was that permission granted before execution?" — you need a gate that fires before execution and signs a receipt at the moment of decision. That is what AgenticRail provides, on top of the structural alignment the draft defines.

See IETF-aligned receipts in the live demo

Run a sequence through AgenticRail and inspect the hash-chained receipts — canonical JSON, Ed25519-signed, hash-chained, written pre-execution.

Open Demo Read Docs
← All posts