ai newsDo., 15. Okt.
EilmeldungMeta and Apple team up to make Muse AI models run better on Macs

Hash-chained audit logs for AI agent actions, in 40 lines

When an AI agent calls a tool — reads a file, applies a manifest, installs a package — you want an audit log you can trust weeks or months later. Tamper-evident doesn't require a blockchain or a signing service. A SHA-256 hash chain over append-only entries is enough to detect a rewrite. Here's a m

dev.toFreitag 17:00 · 09.10.3 Min. Lesezeit
Bild: dev.to

When an AI agent calls a tool — reads a file, applies a manifest, installs a package — you want an audit log you can trust weeks or months later. Tamper-evident doesn't require a blockchain or a signing service. A SHA-256 hash chain over append-only entries is enough to detect a rewrite.

Here's a minimal TypeScript example you can drop into an MCP server, a tool proxy, or an agent harness.

Each event captures the who, what, and when:

interface AuditEvent { id: string; // unique id, e.g. ulid or uuid timestamp: number; // epoch ms, set by the log caller: string; // agent / client identity action: string; // tool name or operation input: string; // canonicalized, redacted JSON string outcome: " ok " | " err " | " denied "; priorHash: string; // hash of the previous event } Enter fullscreen mode Exit fullscreen mode priorHash is the chain. Event 0's priorHash is a fixed genesis constant; every subsequent event's priorHash is the SHA-256 of the previous event's serialized text.

import { createHash } from " crypto "; const GENESIS = " 0000000000000000000000000000000000000000000000000000000000000000 "; function eventHash ( event: AuditEvent ): string { return createHash ( " sha256 " ). update ( JSON. stringify ( event, null, 0 )). digest ( " hex " ); } class ChainedLog { private events: AuditEvent [] = []; append ( event: Omit < AuditEvent, " timestamp " | " priorHash " > ): AuditEvent { const priorHash = this. events. length === 0? GENESIS: eventHash ( this. events [ this. events. length - 1 ]); const entry: AuditEvent = {... event, timestamp: Date. now (), priorHash, }; this. events. push ( entry ); return entry; } /** Serialize one event to the canonical line you'd write to a file. */ line ( event: AuditEvent ): string { return JSON. stringify ( event, null, 0 ); } } Enter fullscreen mode Exit fullscreen mode To make it append-only on disk, each line(entry) is appended to a file with O_APPEND (Node's fs/promises fd.appendFile ), and no write removes or overwrites prior bytes.

Verification walks the chain forward and recomputes each hash. If any priorHash in the log doesn't match the recomputed hash of its predecessor, the log was rewritten between those two entries.

function verify ( events: AuditEvent []): { valid: boolean; badAt: number | null } { let expectedPrior = GENESIS; for ( let i = 0; i < events. length; i ++ ) { const e = events [ i ]; if ( e. priorHash!== expectedPrior ) { return { valid: false, badAt: i }; } expectedPrior = eventHash ( e ); } return { valid: true, badAt: null }; } Enter fullscreen mode Exit fullscreen mode Usage is straightforward:

const log = new ChainedLog (); log. append ({ id: " evt-1 ", caller: " agent-42 ", action: " read_file ", input: ' {"path":"README.md"} ', outcome: " ok " }); log. append ({ id: " evt-2 ", caller: " agent-42 ", action: " kubectl_apply ", input: ' {"manifest":"deploy.yaml","namespace":"prod"} ', outcome: " denied " }); const snap = log. events; const result = verify ( snap ); console. log ( result ); // { valid: true, badAt: null } Enter fullscreen mode Exit fullscreen mode If someone replaces evt-1 's action with write_file or deletes evt-2, verify returns badAt: 1 on the first walk. The chain catches insertions, deletions, and in-place edits without any cryptography heavier than SHA-256.

A hash chain makes rewriting detectable. It does not, by itself:

The chain is the same everywhere. The identity in caller is what makes the entries attributable.

I'm building Cirvix AgentControl, an open-source default-deny policy layer for agent tool calls: https://github.com/CIRVIX/agent-control (try npx @cirvix_ai/agent-control scan ).

Quelle: dev.to (dev.to). Original öffnen
Hash-chained audit logs for AI agent actions, in 40 lines · AI News