pliuzv0.1.x

Audit & compliance

How to Make Your AI Agent Audit Trail Tamper-Evident

A logs table is not an audit trail. Here is how to build a record of agent decisions that an auditor will accept — append-only, hash-chained, and verifiable by anyone — plus an honest read of what the EU AI Act Article 12 actually demands.

Jorge Juan Moscoso Chacón, Co-founder & CTO, Pliuz
Jorge Juan Moscoso Chacón · Co-founder & CTO, Pliuz

Published June 28, 2026 · 13 min read

In short

An AI agent audit trail is tamper-evident when three things are true: every decision is appended to a store that blocks edits and deletions; each record is cryptographically chained to the previous one with a hash (SHA-256 over a canonical serialization); and anyone can re-compute the chain to detect a single altered byte. Mutable database rows are not tamper-evident. A hash chain that you — or an auditor — can verify offline is.

Key takeaways

  • A plain logs table proves nothing under audit: a row you can UPDATE is not evidence.
  • Tamper-evident = append-only enforcement + hash chaining + independent verifiability. All three, or none of it counts.
  • Hash the arguments, do not store raw PII in the chained payload — that is how you keep GDPR erasure and audit integrity at the same time.
  • The EU AI Act Article 12 requires automatic, traceable logs for high-risk systems; a verifiable hash chain is a direct way to meet the mechanism.
  • Do not make the hash chain your only differentiator — it is becoming table stakes. The value is a verifiable record combined with a real-time gate.

Why a logs table is not an audit trail

The most common “audit trail” for an AI agent is a database table the application writes to with a plain INSERT. It is better than nothing, and it is not evidence. The problem is simple: the same credentials that write the log can rewrite it. A row you can UPDATE or DELETE tells an auditor what the database currently says happened — not what actually happened. There is no way to distinguish an untouched history from one that was quietly edited after an incident.

For agent decisions, that gap matters more than for ordinary logs, because the stakes are actions: a payment that moved, a record that was deleted, an email that went out. When a security review or a regulator asks you to prove that every agent action was policy-approved or human-reviewed, “here is our logs table” is not an answer. “Here is a record you can verify yourself, and here is the math” is.

What “tamper-evident” actually means

Tamper-evident is not the same as tamper-proof. You cannot always stop someone with deep access from attempting to change history. What you can do is guarantee that any such change is detectable — that the record carries its own proof of integrity. Three properties, together, get you there:

  • Append-only. The store physically rejects updates, deletes, and truncation. New events can be added; existing ones cannot be changed or removed.
  • Hash-chained. Each event embeds a hash of the previous event, so the records form a chain in which any alteration cascades.
  • Independently verifiable. A third party can re-compute the chain from the data and a public key, and confirm it — without trusting the system that produced it.

Drop any one and it stops being an audit trail. Append-only without chaining can be bulk-replaced. Chaining without append-only can be re-chained. Either without independent verification asks the auditor to take your word for it — which is the one thing an audit exists to avoid.

How to build one

The mechanics are not large, but the order and the details matter. This is the build, step by step.

  1. 1

    Make the event store append-only at the database

    Enforce it where the data lives, not in application code that a bug or a console can bypass. In Postgres, that is triggers that raise on UPDATE, DELETE, and TRUNCATE against the events table. If a delete fails there, that is the protection working.

  2. 2

    Serialize each event canonically

    A hash is only stable if the bytes are stable. Define a canonical serialization — a fixed set of fields, in a fixed key order — so the same logical event always produces the same string. Without this, two correct systems compute two different hashes and verification is meaningless.

  3. 3

    Chain each event to the previous with SHA-256

    Compute each event’s hash over the previous hash plus the canonical event, per tenant. Now every hash depends on all history before it.

  4. 4

    Anchor the arguments by hash — never store raw PII in the chain

    Include a hash of the approved arguments in the chained payload, not the arguments themselves. This binds “these exact arguments were approved” into the chain while letting you null the raw personal data later for a GDPR erasure request without breaking verification.

  5. 5

    Sign exports so they verify offline

    Let anyone export the chain with an Ed25519 signature over the exact canonical bytes. The signature is what makes the export verifiable away from your database, by a party who does not trust you.

  6. 6

    Verify continuously, and let others verify too

    Provide a function that walks the chain and returns OK or the first event whose hash does not match. Run it on a schedule, and publish it so a customer or auditor can run it themselves.

the shape of the chain
# Per tenant, for each event n:
hash[n] = SHA-256( hash[n-1] || canonical(event[n]) )

# canonical(event) = a fixed-field, fixed-order serialization
# event payload contains a HASH of the approved args, not the raw args

# Verify online — returns OK, or the id of the first broken event:
SELECT * FROM pliuz_verify_chain();
The erasure test
The right design passes a simple test: you can satisfy a right-to-erasure request — null the raw personal data — and the chain still verifies. If deleting personal data breaks your audit trail, you stored the wrong thing in the chain.

Mutable log vs tamper-evident chain

A plain logs table vs an append-only, hash-chained, verifiable audit trail for agent decisions.
DimensionPlain logs tableTamper-evident chain
Edit a past recordPossible and undetectablePossible to attempt, but detectable
Proof for an auditor“Trust our database”Re-computable math + signature
Who can verifyOnly you, by assertionAnyone, offline, with a public key
GDPR erasureDelete the row (loses the record)Null raw PII; chain still verifies
Detect a bulk rewriteNoYes — chain break
A plain logs table vs an append-only, hash-chained, verifiable audit trail for agent decisions.

What the EU AI Act Article 12 actually requires

The EU AI Act (Regulation (EU) 2024/1689) is the concrete forcing function behind a lot of audit-trail work right now. The relevant parts for agent decisions:

  • Article 12 — Record-keeping. High-risk AI systems must technically allow the automatic recording of events (logs) over the lifetime of the system, to ensure a level of traceability appropriate to its purpose.
  • Article 14 — Human oversight. High-risk systems must be designed so humans can effectively oversee them, including the ability to intervene or interrupt — which is exactly what a runtime approval gate provides.
  • Article 26 — Deployer obligations. Deployers of high-risk systems must, among other things, keep the logs the system generates.
Honest caveats
Whether your agent is “high-risk” depends on its use case under the Act — many are not. Article 12 obligations for high-risk systems are tied to the Act’s phased timeline (the high-risk provisions are set around August 2, 2026, with a possible further delay under discussion at the time of writing). And none of this is legal advice — the point is that a verifiable, append-only log is a direct, demonstrable way to meet the record-keeping mechanism, whatever your exact obligations turn out to be.

Do not make the hash chain your only moat

Here is the part vendors rarely say: hash-chaining a log is becoming table stakes. Standards bodies are working to standardize chained, verifiable logs; audit-only products already market the same SHA-256 framing; the technique is well understood. If your entire pitch is “we hash our logs,” that is not a durable difference.

The difference that lasts is the combination: a record that is verifiable and a gate that blocks the action before it executes — so you are not only documenting what an agent did, you are deciding whether it gets to. Add EU data residency and a clean answer to the erasure test, and you have something an audit-only logger cannot match. A tamper-evident trail tells you the truth about the past; pairing it with a runtime gate lets you change the future.

How to verify it yourself

The whole point of a tamper-evident trail is that you do not have to trust the vendor — including us. With Pliuz there are two paths. Online, call pliuz_verify_chain() and it returns OK or names the first broken event. Offline, export the chain as Ed25519-signed JSONL and run the open-source verifier: the server emits the exact canonical bytes it hashed, the signature covers them, and the verifier checks sha256(prev || canonical) against each stored hash. Pin the signing key through an independent channel — a key shipped inside its own export proves consistency, not identity.

That is the bar to hold any vendor to, ours included: not “we keep good logs,” but “here is the record, here is the public key, verify it without us.”

Sources & further reading

Frequently asked questions

What is a tamper-evident audit trail?

A tamper-evident audit trail is an append-only, cryptographically chained record of events where any change to a past record is detectable. Each entry is hashed together with the previous entry, so altering one record breaks every hash after it. It is "tamper-evident" rather than "tamper-proof": you cannot necessarily prevent someone with database access from trying to change history, but you can prove, mathematically, that they did.

How does a hash chain make logs tamper-evident?

Each event stores a hash computed as SHA-256 of the previous event’s hash concatenated with the current event’s canonical (deterministically serialized) content. Because every hash depends on the one before it, changing any single field in any past event changes that event’s hash, which no longer matches the next event’s stored previous-hash — and so on down the chain. Re-computing the chain and comparing reveals the first altered event.

Does the EU AI Act require AI agent logging?

For high-risk AI systems, the EU AI Act (Regulation (EU) 2024/1689) Article 12 requires automatic recording of events (logs) over the system’s lifetime to ensure traceability. Article 14 requires effective human oversight, and Article 26 sets deployer obligations including keeping logs. Whether a given AI agent is "high-risk" depends on its use case under the Act. A hash-chained, verifiable record of every agent decision is a direct way to satisfy the record-keeping mechanism; this is guidance, not legal advice.

Can you delete personal data without breaking the hash chain?

Yes, if the chain hashes the arguments rather than storing them raw. Pliuz anchors the approved arguments by hash, so the raw personal data can be nulled on a right-to-erasure request while the chain still verifies — the hash that the chain depends on does not change. Storing raw PII inside the chained payload is the mistake that forces a false choice between GDPR erasure and audit integrity.

How do I verify an AI agent audit trail myself?

Two ways with Pliuz. Online: call the public function pliuz_verify_chain(), which returns OK or names the first broken event. Offline: export the chain as Ed25519-signed JSONL and verify it with the open-source verifier — the server emits the exact canonical bytes it hashed, and the signature covers them, so you check sha256(prev || canonical) against each stored hash plus the signature, without trusting the vendor. Pin the signing key through an independent channel; a key delivered inside its own export proves consistency, not identity.

Keep reading