iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
You make an AI agent’s audit log tamper-evident by recording each action as a structured event, serializing every event into one fixed byte form, computing a SHA-256 digest over that form together with the previous record’s digest, and publishing the latest chain head to a place the agent runtime and the audit writer cannot rewrite. The chain does the detecting: a later edit, insertion, reordering, or truncation makes recomputation fail. The external head is what gives that detection meaning. Anyone who controls the writer and the storage can rebuild a consistent chain from scratch, so the design has to keep that party from replacing the head unseen.
What the chain proves and what it does not
Relative to a chain head that an attacker cannot replace, a SHA-256 chain makes these changes detectable:
- a changed field in any stored record, because its recomputed digest no longer matches;
- a record inserted, removed, or reordered in the middle of the log, because the links between neighboring digests break;
- trailing records removed after a checkpoint was taken, because the recomputed head no longer matches the witnessed one.
On its own, the chain does not detect the following:
- actions the control plane never logged, such as a tool call that bypassed the audit hook;
- events altered before they reach the writer;
- a privileged operator who rewrites the whole chain and republishes a matching head to a destination nobody is watching;
- truncation at the end of the log when no checkpoint exists after the removed records.
Hash-chained logs are often described as immutable. They are not. They make tampering evident to a verifier who already holds an earlier, trustworthy head. Describe the property that way in your documentation and threat model.
#1 Best Overall
Step 1: Define the event record before you hash anything
Start with the events that matter for reconstruction: what the agent asked for, what the control plane decided, what actually ran, and what came back. Instrument the trusted orchestration or control plane that mediates tool calls, not the model’s own account of what it did. A model that summarizes its actions can be wrong or manipulated, while the control plane sees the actual invocation. Record denied and failed attempts as well as successful ones. A denial is often the most informative event during an incident.
A record that supports reconstruction usually carries:
- sequence, a monotonically increasing integer per chain, so gaps are visible;
- session and event identifiers;
- agent identity and, where relevant, the human or service principal it acted for;
- timestamp_utc, in UTC with a fixed format;
- action_type and outcome, such as allowed, denied, failed, or completed;
- tool, the tool name, plus a reference or digest of the arguments and result;
- policy_decision and the policy, model, and software version identifiers needed to reconstruct why an action was permitted;
- previous_hash and entry_hash, which the chaining step adds;
- a signature or checkpoint reference, where used.
An illustrative record, with the digest fields omitted because Step 2 computes them, looks like this:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
{
"sequence": 42,
"session_id": "sess-2026-10-09-0117",
"agent_id": "invoice-agent",
"principal": "svc:billing-prod",
"timestamp_utc": "2026-10-09T14:03:22Z",
"action_type": "tool_call",
"tool": "payments.refund",
"policy_decision": "deny",
"outcome": "denied",
"policy_version": "2026-10-01.3"
}
Treat this field list as a design checklist, not a mandated schema. The Agent Audit Trail draft proposes a JSON record format with input and output hashes and action categories, and it is the closest thing to a shared vocabulary for these fields. Its status is covered in the standards section below.
Step 2: Fix the bytes you hash
A digest is reproducible only if the writer and the verifier feed identical bytes to SHA-256. JSON does not guarantee that. The same object can be serialized with different key order, whitespace, or number formatting, and each variant produces a different digest. Choose one canonicalization rule and state it. For JSON, RFC 8785, the JSON Canonicalization Scheme (JCS), is the IETF reference that the agent audit drafts point to. It was published as an RFC in November 2017.
Then document the chain rule precisely. Implementations differ on each of the following questions, so leaving any of them implicit causes verification failures later:
- Excluded fields. Remove the record’s own digest and the previous-digest field before canonicalization, or the hash becomes self-referential.
- Covered input. Decide whether the digest covers the canonical record alone or the canonical record plus the previous digest. Covering the previous digest is what links records into a chain.
- First record. Use a fixed genesis value or an empty previous-hash input, and write it down.
- Chain scope. A per-session chain is easier to verify in isolation. A global chain gives one head for the whole deployment but needs a single serialized writer.
- Digest encoding. Use lowercase hexadecimal and do not mix encodings within one log.
An example rule: the ACS v0.1 formula
The Agent Control Standard Instrument Specification v0.1 defines a concrete, normative version of this rule:
Free tools Windows power users keep installed
One-click scans. No signup required.
content_bytes = JCS(record with "entry_hash" and "previous_hash" removed)
entry_hash = lowercase_hex(SHA-256(content_bytes || prev_hash_bytes))
For the first entry, prev_hash_bytes is an empty byte string. This formula belongs to that specification and should not be treated as a universal convention. Before implementing it, check whether prev_hash_bytes means the raw 32-byte digest or the hexadecimal text of the previous entry_hash. The two choices produce different hashes, so a verifier written for one will reject a log written for the other.
A minimal writer that follows this pattern looks like this. It assumes an RFC 8785 implementation of your choice and a single serialized writer per chain:
import hashlib
GENESIS_PREV = b"" # used only for the first entry
def append(log_state, record):
body = {k: v for k, v in record.items()
if k not in ("entry_hash", "previous_hash")}
content_bytes = jcs_canonicalize(body) # RFC 8785 implementation
prev_bytes = log_state.prev_hash_bytes or GENESIS_PREV
entry_hash = hashlib.sha256(content_bytes + prev_bytes).hexdigest()
stored = dict(body,
previous_hash=log_state.head_hex or "",
entry_hash=entry_hash)
log_state.write(stored) # must succeed before the head advances
log_state.head_hex = entry_hash
return stored
The ordering in the last two lines matters. Advance the head only after the record is durably stored. Otherwise a failed write leaves the in-memory head pointing at a record that does not exist, and every later record links to nothing.
Step 3: Keep the writer and the storage out of the agent’s reach
A chain is only as trustworthy as the process that writes it. If the agent runtime can write to the audit store, it can append, rewrite, and recompute a consistent chain. OWASP’s APTS Auditability Implementation Guide warns against relying on a hash chain once the runtime has access to the audit store. It names two common pitfalls: writes made directly from the runtime, and runtime and audit operations sharing credentials.
- Give the agent runtime no credentials for the audit store. It should send events to a separate writer or control-plane endpoint that holds the only write credential.
- Use separate credentials for audit writes and for runtime operations, so a compromised agent cannot reuse them.
- Enforce append-only behavior in the storage layer, and confirm that administrative roles cannot overwrite or delete records, not only the application role. Make retention settings stop ordinary cleanup jobs from shortening the log.
- Serialize appends for each chain. Two writers that read the same head will each produce a valid-looking successor, which creates a fork that verification cannot resolve.
The Agent Audit Trail draft describes a two-plane pattern: a queryable plane for search and dashboards, and an append-only plane that holds the authoritative records. Run dashboards against the queryable copy and verify against the append-only plane.
Budget the write path against your own workload. None of the documents discussed here publishes runtime-overhead or detection-rate figures, so measure write latency and storage growth before choosing a blocking policy.
If you are choosing between a self-managed design and a hosted audit service, the same six questions apply to both. None of these documents ranks providers or gives pricing, so use the table as a list of what to verify.
| Question | Self-managed design: what to verify | Hosted service: what to ask |
|---|---|---|
| Who controls the writer and storage credentials? | Only the audit writer holds write keys. No agent-runtime role can write, delete, or administer the log. | Which provider staff and automated systems can alter stored records, and is that access logged? |
| Is append-only behavior enforced? | Storage-level write-once or retention controls apply to administrators as well as applications. | Is append-only behavior enforced at the storage layer, and can the customer verify it? |
| Are chain heads witnessed independently? | Heads are published to a destination the writer cannot overwrite. | Can heads be exported to storage or accounts the customer controls? |
| Can signatures be verified offline? | Public keys are distributed to verifiers, and verification runs without the writer. | Does verification work without calling the provider, and in which key format? |
| How are privacy, retention, and deletion handled? | You set the hashing, retention, and tombstone rules. | What are the retention periods, the deletion procedure, and the storage location? |
| What is the operational effort and interoperability? | You own key rotation, storage, monitoring, and canonicalization upgrades. | Can logs be exported in an open format, and is the canonicalization rule documented? |
Step 4: Publish checkpoints an outsider can see
The Agent Control Standard Instrument Specification v0.1 states the requirement directly: “The audit chain is only tamper-evident to an outside party if its head is committed where that party can see it.” The same specification notes that a private chain head can be rewritten, and that a holder of a symmetric key can re-sign a rewritten head. A checkpoint protects anything only when it is published where the writer cannot quietly change it.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Each checkpoint should contain at least:
- the chain identifier, whether session or deployment scope;
- the sequence number of the latest record covered;
- that record’s entry_hash;
- a UTC timestamp;
- a signature, if you use one, and the identifier of the key that made it.
Publish on a schedule you can justify, such as at session close and at fixed intervals during long sessions. A checkpoint taken at session close protects the session’s records against later truncation only if it is stored externally. Records written after the last checkpoint have no external witness yet, and your documentation should say so.
Symmetric MAC (HMAC)
An HMAC tag can be produced by every holder of the shared secret. A verifier holding that same key cannot tell which holder generated a given tag, and the scheme gives no third-party non-repudiation against the key holder. It can support consistency between parties that already trust each other. It is not enough when an outside party must rely on the evidence.
Asymmetric signatures and offline verification
The Agent Audit Trail draft describes optional ECDSA signatures. The AI Forensics Audit Trail Specification v1.0 describes offline verification using an audit envelope and a public JSON Web Key Set (JWKS). Keep the private signing key inside the trusted writer or in a key service the agent runtime cannot call. Distribute public keys through a channel that verifiers trust, and record the key identifier in each checkpoint so older checkpoints still verify after a rotation. These are design descriptions in specifications. They do not show how any particular deployment protects its keys.
How to verify an agent audit log
Verification needs three inputs: the trusted checkpoint, the public key for that checkpoint’s key identifier if it is signed, and the records themselves. Then proceed in this order:
- Fetch the checkpoint from the witness destination, not from the audit store. Note its chain identifier, sequence number, and head.
- If the checkpoint is signed, verify the signature with the public key you trust for that key identifier. Stop if verification fails.
- Read records from sequence 0 through the checkpoint’s sequence number, in order. Confirm that each sequence value is exactly one greater than the previous.
- For each record, remove entry_hash and previous_hash, canonicalize the remainder with RFC 8785, and recompute entry_hash using the chain rule your implementation defines.
- Confirm that each stored previous_hash equals the prior record’s entry_hash.
- Compare the recomputed hash at the checkpoint’s sequence number with the checkpoint’s entry_hash. A match shows that records 0 through that sequence are consistent with the witnessed head.
- Treat records after the checkpoint as unverified until a later checkpoint covers them.
When verification fails
| Symptom | Likely cause | What to do next |
|---|---|---|
| Recomputed head at sequence N differs from the checkpoint. | A record at or before N changed after checkpointing, or the writer and verifier apply different canonicalization or chain rules. | Find the first sequence where the forward recomputation diverges. Compare that record’s canonical bytes against the writer’s copy in the append-only plane before concluding that tampering occurred. |
| previous_hash does not match at sequence k. | Record k or k-1 was altered, deleted, or reordered. | Compare both records with the append-only copy and with any other checkpoint covering that range. |
| Sequence gap. | Records were never written, or a write failed and was not retried. | Check the writer’s error logs and compare the count of attempted events in the control plane with the count stored. |
| Signature check fails. | Wrong key, a rotated key without key history, or an altered checkpoint. | Confirm the key identifier and key history from the trusted key channel before deciding the log is at fault. |
| Checkpoint cannot be found. | Publication failed, or the destination changed. | Do not treat the segment as verified. Investigate the publication path. |
| Chain verifies, but an action is missing. | The action never reached the audit hook. | This is outside what any chain can show. Check hook coverage on every tool-invocation path. |
Decide what happens when the writer cannot write
Define in policy what the system does when an audit append fails. There are two defensible positions:
Best Value
- Fail closed for high-impact actions. Do not execute a tool call until its record is durably written. This adds latency and turns audit outages into availability incidents.
- Fail open with a durable queue for low-impact actions. Execute the action, queue the record in the trusted writer’s local durable store, alert, and append the queued records in sequence once storage returns. Queued events have no external witness until they are written and checkpointed.
Record the policy decision itself, including degraded-mode operation. A denial or a fallback event belongs in the audit trail.
Protect sensitive content
Store only what the purpose requires. The Agent Audit Trail draft describes input and output hashing, so a record can commit to the content of a prompt, tool argument, or result without storing that content in the log. Three cautions apply:
- A plain SHA-256 digest of a predictable value can be confirmed by anyone who guesses the value. For short or structured fields such as account numbers, names, or yes/no decisions, use a keyed digest or store an encrypted payload in a separate restricted store.
- Decide how an authorized investigator retrieves the underlying evidence, who may do so, and how that access is itself logged. A digest proves what content existed. It does not return the content.
- Define deletion before you need it. The Agent Audit Trail draft describes tombstone-based deletion. In your implementation, removing a payload must not break the chain, which means the record’s digest fields must remain in place after the content is removed. Document the retention period for each class of data.
OWASP’s APTS Auditability Implementation Guide also calls for sensitivity classification and handling of audit data. Classify what enters the log before you choose where it is stored.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Standards and document status
Check each document’s status before citing it in a design review. Status is stated as of 9 October 2026.
| Document | Status | What it contributes |
|---|---|---|
| RFC 8785, JSON Canonicalization Scheme (JCS) | IETF RFC, published November 2017 | Deterministic JSON serialization before hashing |
| Agent Audit Trail, draft-sharif-agent-audit-trail-06 | Individual Internet-Draft by Raza Sharif. Its Datatracker page lists an update dated 29 September 2026. | A record format proposal with input and output hashes, action categories, a two-plane storage pattern, optional ECDSA signatures, and tombstone-based deletion |
| Agent Control Standard Instrument Specification v0.1 | Specification v0.1 | A normative chain formula and a chain-head publication requirement |
| AI Forensics Audit Trail Specification v1.0 | Draft reference specification, published 2026-05-15 | Offline verification using an audit envelope and a public JWKS |
| OWASP APTS Auditability Implementation Guide | Implementation guidance | Independent audit infrastructure, credential separation, and evidence handling |
The Datatracker status notice for the Agent Audit Trail draft reads: “This document is an Internet-Draft (I-D). Anyone may submit an I-D to the IETF. This I-D is not endorsed by the IETF and has no formal standing in the IETF standards process.” Treat the draft as a proposal, not an approved standard. Specifications that define a chain formula or key format are binding only for implementations that adopt them.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

