A colleague recently asked me how he would run financial analysis with AI over the books of an accounting system: the ledgers, the trial balances, the P&Ls. He had three options on the table and no strong preference among them. Generate the PDF reports the system already produces and hand those to a model as input. Point the AI directly at the relational tables and let it query. Or skip the AI and compute the analysis with deterministic code.
The question sounds like a tooling choice. It is an architecture decision, and it happens to be one I had already answered a couple of months earlier, in an independent prototype: a system that computes the 33 financial metrics I consider core, reads accounting PDFs from any source system, and confines AI to the two edges of the pipeline. It never touches the math.
Every metric is a formula
Financial analysis has a property that most AI conversations skip past: it is probably the most deterministic workload in the building. Every metric in my catalog is an arithmetic expression over named sums. The current ratio is current assets divided by current liabilities. Working capital is a subtraction. Margins are divisions. There is no judgment inside any of these, no interpretation, nothing that benefits from a model's flexibility. A formula that is allowed to be flexible has stopped being a formula.
That settles the third of my colleague's options first: the computation itself is code, and it should not be anything else. I made the general version of this argument in June: if you need the same answer twice, dont't use AI. A trial balance is the purest case of that rule I know. Ask the system for the current ratio twice, and anything other than the identical number to the cent is not intelligence showing initiative. It is a defect.
The other two options fail for more interesting reasons. Handing exported PDF reports to a model as the analysis input means taking numbers that were structured data a second ago, flattening them into a document, and asking a language model to re-derive them with no guarantee it reads every line the same way tomorrow. Pointing the model at the relational tables sounds more rigorous and carries the same flaw one layer down: the queries it writes and the aggregations it chooses can drift between runs, and in accounting, drift between runs has a technical name. It is called an error.
Two numbers that prove the rule
All 33 metrics compute the same way: by formula, with no exceptions and no heuristics in between; 14 of them carry thresholds that can raise findings. Most of those thresholds flag things worth investigating, not emergencies: a liquidity ratio drifting below its floor, receivables aging out too far. Two conditions sit in a different class, the only ones in the system marked as critical. And calling them the most important metrics would miss what they are. They are the alarms.
The first is trust liability coverage: cash held in trust minus the deposit liabilities it is supposed to cover. If that number goes negative, client money is not where it must be. That is not an analysis finding; that is a legal problem. The second is the balance sheet check: assets minus liabilities minus equity, adjusted for the year's income and expenses. Accounting says that expression equals zero. If it does not, the emergency is of a different kind: the source data contradicts itself, which means the other 32 metrics were computed from numbers that do not agree with each other.
Only two conditions in the system count as emergencies: client money not covering deposits, and books that do not balance. They are exactly the numbers no model should ever estimate.
The entrance: reading, then auditing the reading
So where does AI belong here? At the entrance, doing the one job deterministic code is genuinely bad at. Every accounting platform prints its own PDFs: different layouts, different column orders, different names for the same concepts. The classic answer is a rigid import template, which means every company adapts its exports to your tool before the tool does anything for them. The prototype I built inverts that. AI reads whatever the source system produced, extracts the figures, and writes them into the database. Interpreting messy, heterogeneous documents is precisely where non-determinism is a feature, because there is no formula for "understand this layout you have never seen."
The payoff is practical: 25 of the 33 metrics compute from the trial balance alone. One file, whatever it looks like, and most of the analysis lights up.
But the design does not even trust the reading. Before anything is ingested, a second, cheaper model call audits the first one: it compares the parsed table against a sample of the raw source and flags the classic misparses, a column shifted one position over, a subtotal ingested as if it were an account, a period detected wrong.
A deterministic rule decides when that second reader runs. For PDFs it always runs, because PDFs are where parsing goes wrong most often. For spreadsheets it runs only when the code itself finds a reason to doubt the parse: too many source rows dropped, or a value column that came back empty. Each of those calls costs money, so the same rule that guards quality also controls the cost: the system pays for a second opinion only when the numbers justify one.
Then the deterministic gates run. Before a single formula executes, the trial balance identity has to hold, receivables and payables have to tie to their aging reports, and periods have to be continuous, all within a tolerance of one dollar. A misread cell does not flow quietly into a ratio; it fails loudly, before the analysis exists. If the AI service is down, nothing stops: the file is still ingested, the metrics still run, and the system records that this particular check did not happen. The pipeline works without the models; what they add is checking, not dependency.
The exit: prose over a case file the code built
The other place AI earns its seat is at the exit, and this is where I expected to give the model the most freedom and ended up giving it the least. A current ratio below its threshold is just a finding; it is only useful once someone explains it. That explanation is not the model's to invent. Before the model writes a word, code gathers the evidence: up to six months of history for the metric that breached, the other metrics that breached in the same month, and, when a general ledger is loaded, the transactions behind the affected accounts. The model writes prose over that evidence and may cite only figures inside it; a validator then checks that every number in the sentences traces back to a value the code computed. The AI writes the sentences. Every figure inside them was calculated somewhere else.
The same discipline decides the month's verdict. Whether a period is clean, has issues, has critical issues, or failed validation is assigned by rules, never by the model; the model narrates the state it is handed. The design notes for the system state it as a flat rule: AI reads, suggests, and narrates; code verifies and computes.
My favorite consequence is what happens when nothing is wrong. Zero findings do not produce silence. They produce a verdict, computed by code, that the books came back clean, every accounting check passed, all 33 metrics inside their configured ranges, with the model writing the short summary a person reads. In the months when nothing is wrong, that verdict is the deliverable.
What the prototype refuses to do
When data is missing, the system says so instead of estimating. A metric whose source report has not been uploaded comes back empty, with the reason attached; growth rates simply do not exist until there are two months to compare. A model sitting in the middle of the pipeline would have filled those gaps fluently, and that is exactly the problem: here, the absence of an answer is information, and the system preserves it.
Two planned capabilities, cash forecasting and fraud detection, stay switched off until they can be built with the same discipline. And I should be equally plain about status: this is a prototype. It has processed the documents I have fed it; it has not run anyone's production books. What I am confident in is the pattern, and the pattern is the point.
In June I wrote that the shape is AI in the data, code in the process, and called it the architecture that actually scales. A summer of building later, I would sharpen the claim. The mature shape is not two layers but a guarded pipeline: AI reads at the entrance and a second model audits the reading, deterministic code computes everything in the middle, and AI explains at the exit from evidence the code assembled. AI at the edges, code at the core. It still scales. More to the point, it is an architecture you can answer for.