Audit Trails for Autonomous Agents — Before It's Required
The EU AI Act enforcement deadline for high-risk AI systems is August 2, 2026. If you're shipping autonomous agents that make consequential decisions — routing logic, content moderation, financial recommendations — you now have a hard compliance surface. Not a best-practice. A deadline.
Most teams building agents today are logging to Datadog or CloudWatch. That won't be enough.
The problem with append-only logs
Standard logging is designed for debugging, not compliance. An append-only log proves what was recorded. It doesn't prove the record hasn't been altered after the fact. A determined attacker — or an undetected bug — can retroactively modify entries. CloudWatch doesn't know and neither do you.
EU AI Act Article 12 requires high-risk AI systems to maintain logs that enable post-hoc verification of decisions. That's a different standard. An agent that made 10,000 decisions last month needs to prove which model version made each one, what inputs it received, and that the record is unmodified. Append-only doesn't get you there.
Hash-chaining as the mechanism
The fix is the same mechanism Bitcoin uses: every record includes a hash of itself plus the previous record. If anyone modifies record #412, every downstream hash becomes invalid. The chain breaks detectably.
Here's how @stackbilt/audit-chain works:
import { writeRecord, verifyChain, GENESIS_HASH } from '@stackbilt/audit-chain';
// Write a decision record
const { record, newChainHead } = await writeRecord(bindings, {
namespace: 'agent-decisions',
chainHead: currentHead, // hash of last record (or GENESIS_HASH)
event_type: 'routing.decision',
actor: 'service:aegis',
payload: {
model: 'claude-sonnet-4-6',
intent_class: 'bizops_read',
confidence: 0.94,
input_hash: sha256(userQuery),
},
});
// Later: verify the entire chain is intact
const result = await verifyChain(bindings, 'agent-decisions');
// { valid: true, record_count: 10000 }
// or: { valid: false, broken_at: 'record-uuid-412', error: 'Hash mismatch...' }
The full record lives in R2 (immutable object storage). D1 holds a searchable index with a truncated payload summary. R2 is the source of truth — if someone alters the D1 index, the R2 records still have the correct hashes, and verifyChain catches the tamper.
Each record's hash is SHA-256(prev_hash_bytes + record_bytes). Breaking the chain anywhere makes every downstream record's hash wrong. You can't quietly patch a decision three months later.
Content provenance with EEAT scoring
Audit chains tell you that something happened. @stackbilt/evidence-core adds a layer: what quality standard did it meet?
The package runs EEAT (Experience, Expertise, Authoritativeness, Trustworthiness) gap detection against content before publishing — the same framework Google uses to assess AI-generated content under its November 2024 policy. The validation result is JSON-serializable and fits directly into an audit record payload.
We compose both in a single operation:
import { validateEvidence } from '@stackbilt/evidence-core';
import { writeRecord } from '@stackbilt/audit-chain';
const validation = await validateEvidence(content);
const { record } = await writeRecord(bindings, {
namespace: 'content-validation',
chainHead,
event_type: 'eeat.validation',
actor: 'service:aegis',
payload: validation, // ValidationResult flows directly in — no transform needed
});
// record.record_id is the cryptographic receipt
We expose this as POST /api/provenance/validate on the AEGIS worker. Every piece of content AEGIS publishes passes through this endpoint. The receipt travels with the content.
This post is signed
Before this post was published, its body was passed through that endpoint. The validator ran, assessed the content against the EEAT policy (flagged gaps, as it should for a blog post without a formal citations section — that's the validator doing its job), and wrote a tamper-evident record to the content-validation chain.
audit_record_id: cbf20f51-8778-447d-8f40-cf7e9670055f
chain_head: f0ee93f5959192e9be6911d37afd22b678f74bd114ec253b54fb64c903a61d9e
namespace: content-validation
actor: service:aegis
event_type: eeat.validation
That record is in aegis-audit R2. The chain head above is the SHA-256 of this record's bytes plus the previous record's hash. If this post were altered after publication and re-validated, the audit_record_id would be different — a new record, a new hash, a visible gap in the chain.
Both packages are Apache-2.0 and live on npm:
npm install @stackbilt/audit-chain @stackbilt/evidence-core
The moat isn't the packages. It's the operational history — edge cases baked in by running these in production before the compliance pressure arrived. The enforcement deadline is in 68 days. The chain has already started.