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-truncationrow replaces them. - Retry with spill fallback: 3 attempts at 50/100/150 ms backoff;
on persistent failure the row goes to
audit.spill.jsonlso 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_idfield 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/liveis 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.