Skip to content

Necessary technology is always active because it provides security and remembers this choice.

Resources

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.

Published Reviewed
AI-generated editorial image of precision metal links arranged on an engineering inspection table
AI-generated editorial illustration. The public format below is a reference design, not Trunnion's private production schema.

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.

FieldRequiredPurposePrivacy guidance
chain_idYesNames one ordered record streamUse a non-secret opaque identifier
sequenceYesEstablishes strict order inside the chainInteger, starting rule must be documented
recorded_atYesStates when the event was committedUse UTC with explicit precision
event_typeYesClassifies the lifecycle or control eventUse a versioned closed vocabulary
actorYesIdentifies the human, service, or agentPrefer stable internal IDs over email addresses
on_behalf_ofRecommendedIdentifies the principal representedRequired when an agent acts for another party
task_idYesLinks events from one bounded taskMust not expose customer content
actionYesDescribes the proposed or completed operationSeparate verb, resource, and parameter reference
authorityYesNames the evaluated policy or grantInclude decision and version
approvalConditionalLinks parameter-bound human reviewRequired when policy calls for review
outcomeYesRecords result and state transitionDistinguish proposed, denied, failed, and completed
evidence_refsRecommendedLinks receipts, attestations, or protected artifactsApply access checks at retrieval time
schema_versionYesSelects canonicalization and validation rulesVersion every incompatible change
previous_hashYesCommits to the preceding recordFixed-length lowercase hexadecimal in this profile
hashYesCommits to this record and predecessorComputed 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.

  1. Parse the records with strict size and count limits.
  2. Validate every record against the declared schema version.
  3. Confirm that all records carry the same chain_id unless a rollover event explicitly changes it.
  4. Confirm that sequence numbers are contiguous and follow the stated starting rule.
  5. Confirm that record one references the documented genesis value or signed opening record.
  6. Rebuild the canonical payload for each record.
  7. Recompute the digest using the stored predecessor.
  8. Compare the computed digest with the stored digest using an exact byte comparison.
  9. Confirm that the next record's previous_hash equals the current record's digest.
  10. Validate any external checkpoint, signature, or inclusion proof using separately trusted material.
  11. 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 mutationExpected resultWhy it matters
Edit one retained fieldDigest mismatch at that recordDetects changed history
Delete a middle recordSequence or predecessor mismatchDetects omission from the retained series
Insert a new middle recordNext predecessor mismatchDetects unauthorized insertion
Reorder two recordsSequence and predecessor mismatchProtects causal ordering
Truncate the tailLocal chain may still verifyRequires a separately trusted checkpoint
Replace the whole chainLocal chain may still verifyRequires signature, witness, or external anchor
Omit an event before loggingChain still verifiesRequires boundary coverage tests
Copy a valid record to another tenantSchema may still validateRequires 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 choiceBenefitCost or riskDecision evidence
Hash every event synchronouslyImmediate linkageAdds write-path latency and dependencyRelease load test and failure policy
Queue before hashingIsolates action latencyCreates a window before durable commitmentQueue durability and reconciliation test
Retain full argumentsEasier reconstructionHigher sensitivity and storage costData classification and access review
Retain protected referencesLower log exposureEvidence retrieval has more dependenciesReference durability and authorization test
Sign every recordStrong per-record authenticityKey operations and rotation overheadKey custody and throughput evidence
Sign periodic checkpointsLower signing costSmaller undetected windowCheckpoint frequency rationale
Linear chainSimple verificationFull scans grow with record countVerification-time budget
Merkle batchesEfficient proofsMore complex implementation and operationsIndependent 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.

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.

Primary sources

External standards remain authoritative for their own requirements and status. A Trunnion mapping does not create a certification or authorization.

Evaluate the controls against work you actually run.

We will scope the action boundary, decision authority, deployment environment, and release evidence before discussing a solution.