⚡ Powered by Finn · Day 139 of 365
139

Building an AI Financial Controller Agent, the Thin Harness Way

Last week an AI agent closed the month for an enterprise client, and all four entities tied to their bank statements to the cent. I have been building this AI financial controller agent since spring, on top of the client's AccountsIQ database, and July was the first close it ran end to end with zero unexplained differences. A separate script read the ledger after the final write and confirmed the tie-out, because the code that writes the numbers has been wrong about itself before.

Damn it feels good to write that. This has been a beast of a project.

Two things pushed me to write the build up this week. Garry Tan has been posting about "thin harness, fat skills", calling it a powerful way to cut bugs in agent systems, and he kept going: "Thin Harness Fat Skills Fat Code = THE NEW DRY". I wrote about the same approach on Day 18 back in April, when it was the method behind a tech-grant sprint, and people now reach that post by googling his name next to the phrase. Meanwhile Search Console showed me something smaller. One in four people who search "ai financial controller" and see my page on it click through. Four impressions in a week, so a tiny sample, but this is a high intent search term. A person typing those three words has a books problem and a budget conversation coming.

Client unnamed, figures kept out of it. The rest as it happened. This has been the biggest engineering project of the 365-day build by a mile.

The thin harness

The harness is small on purpose. Scripts turn each bank's statement export into one common format. A matcher pairs statement lines with ledger entries, and a proposer drafts writes for whatever remains. There are 973 tests behind that layer, all green, and it behaves the same way in month nine as it did in month one. The AI has no hand in any of it.

The agent sits on top and handles what the code cannot read: a direct debit whose invoice arrives three weeks later, or two lines sharing one description that need separating by amount and date. When it writes, it goes through the harness's controlled paths. Pure Garry Tan style.

The fat skills

Most of the intelligence is written down. Before the agent acts it reads a procedure file, and behind that sits a decision ledger holding 281 rulings from the client's accountant. Software goes to one GL code and subscriptions to another because they said so, in writing, with the date attached. Differences under one unit of currency go to bank charges, their words, recorded the day they were said. The rules were decided once, but it doesn't mean they can't change later. The machine has applied them every month since, and when the agent meets a situation with no ruling, it drafts a question to find out.

The ledger read does two jobs at once. It keeps the agent from improvising an accounting treatment, and it makes the whole system portable, because the judgement lives in a file the CFO owns rather than in anyone's head. Or worse, the agent making things up that sound plausible, but are not.

The rules that took longer than the code

Early on the agent told me three closes in a row that its writes were done, because the API had returned an id. Some of those ids were zero. Since then a write counts as done when a fresh read of the ledger shows the lines and the amount against the right counterparty, and the month-end tie-out gets verified by a script that has no write access at all. This part took a lot of hours to figure out and now it seems obvious. I'm a bit embarrassed to admit, but there you go. Learn from it.

There is no path from a script straight to the live ledger. The client's accountant signs every close, and each write lands in a hash-chained audit log. Give an AI unsupervised posting rights to a general ledger and you have bought yourself a liability with an API key. I had to back out 25 duplicated charges by hand that the agent didn't see. That was stopped a few months back, and the ai controller system is booking clean books, taking a job that was 30 hours of a top CFO manually keying, down to a few minutes here and there checking the dry run before it posts.

The defect that keeps coming back has a name in our notes: fixed in the unit, missed in the caller. Ten times now, give or take, a control got added to one function while the same hole sat open in another path calling the same write. A fix counts as finished after someone has grepped for every other caller.

Another hard won lesson. You can spend as much time as you want building an AI brain, but the agent won't remember the rules. Fixes go into deterministic code immediately and after each session. It may make you feel better to post the lessons into the AI brain, but they get glossed over every time. The brain helps, and I test mine cold, but it's not perfect. At least I haven't been able to create the perfect AI brain yet.

What the close looks like now

July's close left five open questions, judgement calls every one, and the accountant answered them in a single message. Each answer was actioned and verified live the same day. Their hours went into deciding. The matching had already happened overnight.

Underneath, this is the AI financial controller service I sell. A thin harness, a set of written skills, a decision ledger your accountant owns, and a machine that gets its homework marked by someone else.

August's statements arrive in a few weeks. The harness will treat them exactly like July's.

Day 139 of 365.

Get the next build-in-public post by email

One short dispatch most days — the AI ops builds, what's working, what isn't. No spam.

← Day 138 All posts Day 140 →

Follow the BIP

AI Deployment as a Service. One workflow at a time.

Book 15 minutes. We see if your workflow is one we'd build.

Schedule a call