Build log · 2026-04-28

The ledger is the product

How VoidAi's audit log doubles as observability, accounting, and corporate trail — and what it unlocked that the agents didn't.

The ledger is the product

The most useful thing I built this month isn’t an agent. It’s the ledger.

Every action any of VoidAi’s 19 agents takes writes one row to a JSONL file. The schema is intentionally boring:

{
  "ts": "2026-04-25T20:09:24.604Z",
  "run_id": "de5b5ed3-...",
  "agent": "void-pulse",
  "action": "pulse.probe",
  "target": "env",
  "outcome": "success",
  "cost_usd": 0.0001,
  "duration_ms": 80,
  "reason": "status=green;detail=NNN keys ok",
  "playbook": "pulse-probe",
  "playbook_version": "0.1.0"
}

One row per action. Append-only. UTF-8 no BOM. The file lives at state/audit.jsonl and is the first thing every agent does before doing anything else: write the row.

That row turns out to be observability AND accounting AND the audit trail in one stream.

Why this is the wedge

Most AI consultancies ship you agents. They might ship you logs (“we use CloudWatch”). The thing they don’t ship you is the append-only ledger that survives an agent dying mid-action.

The hard part isn’t writing rows. The hard part is making sure they always land. VoidAi’s audit-write.ps1 v0.2.0 is a 220-line script that:

  • Atomic Win32 append via [System.IO.File]::AppendAllText (uses FILE_APPEND_DATA on NTFS — atomic for writes ≤ 4 KB).
  • Named mutex serializes cross-process appenders.
  • Auto-heal preflight: every call inspects the last logical line before appending. If it didn’t parse as JSON OR the file didn’t end with a newline, the bytes get quarantined verbatim and an audit.heal-truncation row replaces them.
  • Retry with spill fallback: 3 attempts at 50/100/150 ms backoff; on persistent failure the row goes to audit.spill.jsonl so it isn’t lost.

We stress-tested it under 16 parallel writers × 25 writes = 400 rows. Zero parse failures. Zero spilled rows. 8.57 seconds elapsed. Seeded corruption auto-healed on first preflight.

What this unlocked I didn’t expect

Behavior change. Watching today’s spend roll up against the $5/day global cap is more disciplining than any written policy. Every Claude call is a row; every row has a cost_usd field; the sum of today’s cost_usd is the burn rate. You start asking “do I actually need to leave the brand-steward agent on right now?” and the answer is more often “no” than I expected.

Customer trust. Pre-empts the “but what’s the AI actually doing?” conversation before it starts. The audit log is grepable. “Did your agent really write that email?” → grep email.draft state/audit.jsonl | grep <run_id>. One JSONL line is more convincing than any explanation.

Recovery. This is the one I didn’t see coming. When a row DOESN’T write — because the script died, the disk was full, something raced — THAT becomes a row at the next hourly sweep. The integrity-sweep walks the audit log, finds the broken JSON line, quarantines the bytes verbatim, heals the file, writes an audit.heal-truncation row carrying the original ts/run_id/agent forensically.

The system tells on itself.

What it doesn’t do (yet)

  • Per-customer ledger. All rows are in one file. When the first paying customer arrives, we’ll add a customer_id field to the schema and split rollups by customer. Today: trivial single-tenant.
  • Stream to a customer-facing surface. The ledger is private. A sanitized public mirror at voidco.com/build-log/live is on the roadmap (see this site’s Build Log archive, where a future post will announce it).
  • Real-time querying. Today the ledger is a 250 KB JSONL file with ~800 rows. At ~50 MB it migrates to SQLite. Today: not yet.

Where to read more

  • 06-Knowledge/architecture/auto-recovery-charter.md — what auto-fixes today, what escalates, what’s permanent human-only.
  • 06-Knowledge/specs/audit-write-hardening-spec.md — the v0.2.0 hardening pass that bulletproofed the write path.
  • 06-Knowledge/architecture/mit-grade-engineering-posture.md — the operational posture: detect → heal → prevent.

If you’re running agents in production

If your “audit story” is “we have CloudWatch logs,” you’re 80% of the way there but missing the 20% that compounds. The append-only ledger isn’t a feature you bolt on; it’s the ground floor every other feature stands on.

This is what we install. If your team needs it, the contact form is at /contact. First call is free.

Authored by founder + claude · reviewed by brand-steward