Specification
Hash-chained agent audit trail specification
A hash-chained agent audit trail is an ordered series of execution records in which each record commits to the prior record's digest. Verification recomputes every link, exposing edits, deletions, insertions, and reordering in the retained chain.

This specification defines a minimal public format for reviewing a tamper-evident agent execution history. It is intentionally implementation-neutral. The format can be produced by a single agent, a multi-agent orchestrator, or a conventional application that delegates actions to models and tools.
The design goal is narrower than immutability. A verifier should be able to detect whether the retained chain changed after it was committed. Authenticity, completeness, privacy, authorization, and durable retention require additional controls described below.
What must an agent audit trail record?
An agent audit record must connect identity, intent, authority, execution, and outcome. A text log saying that an agent "completed the task" is not enough for an investigator to reconstruct what happened.
Identity and delegation
Record the accountable human or service, the acting agent, the tenant or security boundary, and the delegation that allowed the agent to act. A model name is not an identity. A session identifier is not authority. The record should make it possible to answer who initiated the work and who remained responsible for it.
Task and action classification
Record the bounded task, the proposed action, the target resource, and the consequence class used by policy. Reading a public reference and transferring funds may both be "tool calls," but treating them as one event type prevents meaningful review.
Policy and approval
Record the policy decision, policy version, attributes evaluated, and any human approval. Approval must bind the exact parameters reviewed. A generic approval token that can be reused for a changed recipient, amount, destination, or data scope is not reliable evidence of consent.
Execution and outcome
Record the tool request through a protected representation, the downstream response or receipt, the resulting state, and any failure or retry. The audit event should distinguish "requested," "accepted," "completed," and "verified" rather than compressing them into one success flag.
Release context
Record the software release, model endpoint, policy bundle, tool adapter, and schema version relevant to the action. Without version references, the trail cannot explain which behavior or control was actually in force.
Which fields are in the public reference format?
The following table separates required linkage fields from recommended operational fields. Deployments may add fields, but removing required fields changes the profile.
| Field | Required | Purpose | Privacy guidance |
|---|---|---|---|
chain_id | Yes | Names one ordered record stream | Use a non-secret opaque identifier |
sequence | Yes | Establishes strict order inside the chain | Integer, starting rule must be documented |
recorded_at | Yes | States when the event was committed | Use UTC with explicit precision |
event_type | Yes | Classifies the lifecycle or control event | Use a versioned closed vocabulary |
actor | Yes | Identifies the human, service, or agent | Prefer stable internal IDs over email addresses |
on_behalf_of | Recommended | Identifies the principal represented | Required when an agent acts for another party |
task_id | Yes | Links events from one bounded task | Must not expose customer content |
action | Yes | Describes the proposed or completed operation | Separate verb, resource, and parameter reference |
authority | Yes | Names the evaluated policy or grant | Include decision and version |
approval | Conditional | Links parameter-bound human review | Required when policy calls for review |
outcome | Yes | Records result and state transition | Distinguish proposed, denied, failed, and completed |
evidence_refs | Recommended | Links receipts, attestations, or protected artifacts | Apply access checks at retrieval time |
schema_version | Yes | Selects canonicalization and validation rules | Version every incompatible change |
previous_hash | Yes | Commits to the preceding record | Fixed-length lowercase hexadecimal in this profile |
hash | Yes | Commits to this record and predecessor | Computed after canonicalization |
The public verifier on this site uses a reduced subset so a reader can inspect the chain without uploading real data. Production deployments normally need more identity, policy, evidence, and tenancy context than the browser example.
How is each record canonicalized and hashed?
The hash input must be deterministic. This profile uses UTF-8 encoded canonical JSON and a domain-separated prefix. RFC 8785 is a useful baseline for canonical JSON because it defines deterministic property sorting and primitive serialization.
Reference construction
payload = canonicalize(record_without_hash_and_previous_hash)
input = "TRUNNION-AUDIT-REF-V1\n" || previous_hash || "\n" || payload
hash = lowercase_hex(SHA-512(UTF8(input)))
The first record uses a documented genesis value. This profile uses 128 lowercase zeroes, the width of a SHA-512 hexadecimal digest. A deployment may use a signed chain-opening record instead, but the choice must be explicit.
Reference JSON
{
"chain_id": "ach_01J7REFERENCE",
"sequence": 42,
"recorded_at": "2026-09-20T14:06:31.482Z",
"event_type": "approval.resolved",
"actor": { "type": "human", "id": "usr_8421" },
"on_behalf_of": { "type": "organization", "id": "org_104" },
"task_id": "task_9018",
"action": {
"verb": "release",
"resource": "requirement_summary",
"parameters_digest": "sha512:..."
},
"authority": {
"policy_id": "policy.release-review",
"policy_version": "17",
"decision": "allow"
},
"approval": {
"approval_id": "apr_392",
"decision": "approved",
"parameters_digest": "sha512:..."
},
"outcome": { "state": "completed", "receipt_ref": "receipt_551" },
"evidence_refs": ["evidence://receipt_551"],
"schema_version": "aat-ref-1",
"previous_hash": "0f4d...",
"hash": "9b16..."
}
The example uses digests and references for sensitive parameters. A digest is not encryption, and low-entropy values may still be guessed. Whether a field is retained, tokenized, encrypted, or excluded belongs to the deployment's data-handling design.
How should a verifier check the chain?
Verification is a repeatable procedure, not a visual "verified" badge.
- Parse the records with strict size and count limits.
- Validate every record against the declared schema version.
- Confirm that all records carry the same
chain_idunless a rollover event explicitly changes it. - Confirm that sequence numbers are contiguous and follow the stated starting rule.
- Confirm that record one references the documented genesis value or signed opening record.
- Rebuild the canonical payload for each record.
- Recompute the digest using the stored predecessor.
- Compare the computed digest with the stored digest using an exact byte comparison.
- Confirm that the next record's
previous_hashequals the current record's digest. - Validate any external checkpoint, signature, or inclusion proof using separately trusted material.
- Report the first divergence, the verification scope, and the checkpoint used.
Verification pseudocode
previous = GENESIS
expected_sequence = 1
for record in ordered_records:
require record.sequence == expected_sequence
require record.previous_hash == previous
validate(record, schema=record.schema_version)
payload = canonicalize(without_linkage(record))
computed = sha512(PREFIX + "\n" + previous + "\n" + payload)
require constant_time_equal(computed, record.hash)
previous = computed
expected_sequence += 1
verify_checkpoint(previous, checkpoint)
The verifier must say what it did not check. A valid local chain with no trusted checkpoint may show internal consistency while remaining replaceable as a whole.
Which attacks should verification detect?
| Test mutation | Expected result | Why it matters |
|---|---|---|
| Edit one retained field | Digest mismatch at that record | Detects changed history |
| Delete a middle record | Sequence or predecessor mismatch | Detects omission from the retained series |
| Insert a new middle record | Next predecessor mismatch | Detects unauthorized insertion |
| Reorder two records | Sequence and predecessor mismatch | Protects causal ordering |
| Truncate the tail | Local chain may still verify | Requires a separately trusted checkpoint |
| Replace the whole chain | Local chain may still verify | Requires signature, witness, or external anchor |
| Omit an event before logging | Chain still verifies | Requires boundary coverage tests |
| Copy a valid record to another tenant | Schema may still validate | Requires tenant-bound identity and query enforcement |
These negative tests belong in release evidence. A verifier that has only seen a valid sample has not demonstrated detection behavior.
How do checkpoints and signatures strengthen the trail?
A checkpoint commits to a chain head outside the writer's immediate control. It may be written to a separately administered store, signed by a protected key, witnessed by another service, or represented as a Merkle tree head. The right pattern depends on threat model and scale.
Local signed checkpoints
A protected signing service periodically signs the chain identifier, highest sequence, latest digest, schema version, and checkpoint time. Verification requires the public key, certificate history, revocation status, and rotation record. A signature is valuable only if the chain writer cannot also rewrite key history without detection.
External witnesses
A deployment can send only a checkpoint digest, not the underlying sensitive records, to a separately controlled witness. This reduces disclosure while making whole-chain replacement harder. Disconnected deployments can export checkpoints through an authorized transfer process rather than relying on continuous connectivity.
Merkle transparency structures
Large systems may batch records into a Merkle tree and retain signed tree heads. This supports inclusion and consistency proofs without replaying the entire history for every query. RFC 9162 is a mature transparency-log reference, but an agent system still needs its own event model, tenancy rules, and failure behavior.
What are the main operational trade-offs?
| Design choice | Benefit | Cost or risk | Decision evidence |
|---|---|---|---|
| Hash every event synchronously | Immediate linkage | Adds write-path latency and dependency | Release load test and failure policy |
| Queue before hashing | Isolates action latency | Creates a window before durable commitment | Queue durability and reconciliation test |
| Retain full arguments | Easier reconstruction | Higher sensitivity and storage cost | Data classification and access review |
| Retain protected references | Lower log exposure | Evidence retrieval has more dependencies | Reference durability and authorization test |
| Sign every record | Strong per-record authenticity | Key operations and rotation overhead | Key custody and throughput evidence |
| Sign periodic checkpoints | Lower signing cost | Smaller undetected window | Checkpoint frequency rationale |
| Linear chain | Simple verification | Full scans grow with record count | Verification-time budget |
| Merkle batches | Efficient proofs | More complex implementation and operations | Independent proof test vectors |
There is no universally correct interval, retention period, or checkpoint method. A credible specification names the variables and the evidence used to choose them.
How should the system behave when recording fails?
Failure behavior should follow consequence. A system that continues a high-impact tool action after losing its audit boundary creates an unreviewable side effect. A system that blocks every low-risk read during a short logging interruption may create needless fragility.
Define at least three policies:
Fail closed
Actions that change durable state, transfer data, create an external commitment, alter permissions, or affect a person should normally stop before execution when the required audit commitment cannot be made.
Queue with a bounded lease
Some actions can remain pending for a short, visible period. The queue must be durable, bounded, observable, and incapable of executing after its authority expires.
Continue with explicit degraded evidence
Only actions whose consequence and data exposure permit it may continue. The degraded state must create its own operator-visible event and reconciliation obligation. "Best effort" without a named owner and deadline is not a control.
What privacy and tenancy rules apply?
Audit data often becomes the most concentrated record of a system's work. It may contain identities, document references, decisions, denials, and failure details. Treat it as a protected product surface.
- Partition storage and queries by deployment and tenant before retrieval, not through a post-query filter.
- Separate broad operational telemetry from decision records.
- Encrypt data at rest and in transit according to the deployment's requirements.
- Apply ABAC or comparably contextual authorization to audit queries and exports.
- Define field-level retention instead of assuming one period fits every record.
- Record authorized redaction or correction as a new event rather than silently rewriting history.
- Test cross-tenant denial, unauthorized export, expired access, and revoked reviewer credentials.
The chain protects evidence integrity only when the people and systems reading it are governed too.
How should buyers evaluate a vendor claim?
Ask for an artifact from the exact release and environment under consideration. The evidence package should include the record schema, canonicalization version, negative verification tests, boundary-coverage map, failure behavior, checkpoint design, key custody, cross-tenant tests, retention rules, and a supported export procedure.
The IETF Agent Audit Trail document is an Internet-Draft and may change or expire. It is useful as a public point of comparison, not as proof that an implementation is standards-compliant. FIPS 180-4 defines the underlying hash algorithms, not the application event model. RFC 8785 defines canonical JSON, not authorization or completeness. A credible audit design composes these pieces and states what each one contributes.
Direct answers
Frequently asked questions
What does a verified hash chain prove?
It proves that the supplied records match the retained order and content used to compute their stored digests. It does not prove that every real event was recorded, that the source was honest, or that the first checkpoint is authentic.
Is a hash-chained audit trail a blockchain?
No. A local hash chain uses cryptographic linkage without distributed consensus, tokens, miners, or a public ledger. External checkpoints or signatures can strengthen authenticity without turning the system into a blockchain.
Why does canonicalization matter?
Equivalent JSON can differ in key order, whitespace, number representation, or Unicode encoding. A verifier needs one exact byte representation or it will report false mismatches across serializers.
Can records contain prompts and tool arguments?
Only when the security and retention model permits it. Sensitive values should usually be represented by protected references, field-level digests, or redacted structures rather than copied into a broadly accessible log.
What happens when the audit store is unavailable?
The deployment must define which actions fail closed, which low-consequence actions may queue, how operators are alerted, and how any gap is reconciled. Silent continuation is not an acceptable default.
Is this Trunnion's production record format?
No. It is a public reference profile built from general logging, canonicalization, and secure-hash principles. Exact Trunnion fields, controls, and coverage are verified for the applicable release and environment.
Reference desk
Primary sources
- FIPS 180-4, Secure Hash Standard
- RFC 8785, JSON Canonicalization Scheme
- RFC 9162, Certificate Transparency Version 2.0
- IETF Internet-Draft, Agent Audit Trail
- W3C PROV-O
External standards remain authoritative for their own requirements and status. A Trunnion mapping does not create a certification or authorization.
