Accounting Runs on a Chain of Exports. That Is Why AI Cannot Do It Yet.

Joey French22 min read
#ai native accounting#accounting automation#month end close#financial knowledge graph#MCP#XBRL

Listen to this story

Your books are in QuickBooks. Almost nothing else is.

The depreciation schedule is a spreadsheet, and QuickBooks does not know it exists. The close checklist is a spreadsheet, so the accounting system has no idea what is still outstanding. The GAAP mapping is a spreadsheet: you export the trial balance and map it by hand into standardized financials. The operating model is a spreadsheet, built on top of an export of those financials.

Four artifacts, four exports, and after each one a human quietly re-links what the export just disconnected.

That is not a complaint about spreadsheets. Excel is a superb lens. The problem is what an export costs, and the cost is always the same: everything except the numbers.

A cell is a number that has forgotten it was ever an accounting fact

When 161,432 lands in a spreadsheet cell, here is what came with it: 161,432.

Here is what did not. That it is accounts receivable, net, current. That it is a balance as of March 31 rather than something that happened during March. That it was pivoted from 47 posted line items. That those postings arrived under a chart-of-accounts mapping somebody approved on a Tuesday. That it belongs to a rollup that has to foot to total current assets, which has to foot to total assets, which has to equal liabilities plus equity. That two of those 47 postings came from a bank feed and the rest were journal entries with a person's name on them.

All of that was real, and all of it existed a moment earlier. The export dropped it, because a grid has nowhere to put it.

Every step after that reconstructs some of the lost meaning by hand. The mapping tab is a person remembering which accounts roll up where. The check row at the bottom of the model is a person remembering that the balance sheet is supposed to balance. The close checklist is a person remembering that March depreciation has not been booked yet.

Accounting is not short of data. It is short of connections, and the connections are stored in people.

Which is why AI keeps failing at this

Every serious attempt to put AI on the books points it at the end of that chain.

Point Claude at a spreadsheet and it does something genuinely useful. I have written about that before and I stand by it: pointing Claude at an export is real work, and the instinct behind it is right. Anyone who reached for it has correctly identified where this is going, and they have already conceded the expensive part, which is that AI should be touching the numbers at all.

But it is aimed at the most degraded link in the chain. A model reading a grid can pattern-match across values. It cannot reason about accounting, because by the time those numbers reached the grid there was no accounting left in them. It does not know that cell B14 has to foot. It cannot tell a live tab from a dead one, because they look identical. It cannot answer "why is this number what it is," because the why was discarded four exports ago.

The ceiling is not the model. The ceiling is that we hand it the residue.

And the fix is not a better prompt or a longer context window. It is to stop exporting.

Four exports, four connections

Rebuilding the middle of that chain meant turning each export into a connection the system actually holds. Four of them, in the order a controller meets them.

The schedule became an obligation the ledger already knows about

In the spreadsheet world a depreciation schedule is a tab. It computes the right number every month, and then a person reads that number and types a journal entry. Nothing in the accounting system knows the schedule exists. If you forget March, nothing stops you from closing March.

Declare a schedule here and something different happens immediately: the system writes every future period's entry into the event store on the spot. One pending obligation per period, across the full life of the asset, each one linked back to the schedule that created it. The future is not a formula waiting to be evaluated by a person. It is rows, now, that the ledger can see.

Then the close reads them. A period will not close while an obligation against it is outstanding, and the refusal comes back naming the count and the specific items. Retire the asset early and the unrealized future obligations are voided in a single sweep, because the system knows exactly which ones came from that schedule.

The entries still get made. They derive themselves from the obligation instead of being retyped from a tab, and each posted entry keeps a pointer back to the event that caused it.

Forgetting to book depreciation stops being a discipline problem and becomes something the data model will not let you do.

That is the piece I would most want an accountant to look at, because it sounds like a small feature and it is actually the entire thesis. The schedule and the ledger used to be two artifacts held together by somebody remembering. Now they are one thing.

The mapping moved into the system

Standardized financials normally require the export. Pull the trial balance, open the mapping workbook, assign each account to its GAAP concept, rebuild the statements downstream of that.

Here the mapping is not a workbook. It is data: validated associations from each chart-of-accounts element to its canonical concept, suggested by a model, approved by a person, and then checked in a way a spreadsheet has no equivalent for. Accounts map only to the leaves of the calculation hierarchy, never to subtotals, because subtotals are always derived rather than assigned. And a validator rejects any mapping whose fact would land on a branch that never reaches a statement root.

That last one is worth dwelling on, because it is the failure nobody catches. In a workbook, an account mapped to the wrong level looks mapped. It produces no error. It simply never appears on the balance sheet, and you find out during review, if you find out. You cannot write that validator against a spreadsheet, because there is no hierarchy there to walk.

The report became a view rather than a file

You do not create a balance sheet here. You create a report, and the statement is a walk over a structure. The same facts walked over a different structure are a different statement, which is why a tax-basis balance sheet is not a second copy of anything and cannot drift from the first.

Four things follow from that, and they are the ones a controller feels.

The statements exist before the close. Because a statement is a computation over facts rather than a document somebody assembles, the balance sheet, income statement and cash flow render off the live ledger at any moment, with nothing closed. The close is still a real act with real consequences. But "what do the books look like right now" stopped being a question that requires a month-end.

The footnotes are bound to the numbers. Narrative disclosures are facts too. A revenue-recognition policy note or a segment description is bound to the document it came from, carrying a hash of that text, so if the document changes underneath a report the mismatch surfaces instead of sitting there quietly. In most reporting processes the words and the numbers are maintained in two different files by two different people, and reconciling them is somebody's weekend. Here they are the same kind of object.

The checks travel with the report. Two dozen arithmetic rules ride along: every rollup foots, assets equal liabilities plus equity, the cash flow net change ties to the balance sheet cash walk, the schedules tie to the balances they feed. Most of them are generated from the calculation relationships themselves rather than written by hand, which is the only reason they cannot drift out of sync with the structure they are checking.

Filing is a lifecycle, not a save. Draft, under review, filed, archived. Once filed a report is immutable, and a restatement is a new report that supersedes the old one rather than an edit to it. You keep both and the link between them is explicit. That is what "we restated Q2" is supposed to mean, and what a folder of workbooks named Q2_final_v3_REVISED can never quite deliver.

And then there is what happens when the report leaves. You can take it out as XBRL, the format public companies already file in. Or as JSON-LD, where every number arrives carrying its concept, its period, its unit, its place in the calculation hierarchy, and where it came from.

That is an export that severs nothing. Hand that file to an AI and it does not receive a grid, it receives the accounting. Which is the quiet inversion in this whole project: the format we hand to machines is now richer than the one we hand to spreadsheets, out of the same underlying data. It turns out you can do considerably more with that file than store it, and I come back to what near the end.

CSV is still there on the browse grids, clearly labeled as the spreadsheet handoff. It is a fine way to look at things. It is just not allowed to be the way anything comes back in. There is no path to import a spreadsheet into these books, and that is deliberate rather than unfinished. The moment a cell becomes the source of truth for a posted number, that number's provenance is severed at the point of entry, and nothing downstream recovers it.

The model moved on top of the ledger instead of downstream of it

An operating plan is normally the last export in the chain and the furthest from the truth. Export the financials, build the model beside them, then maintain the seam between actuals and forecast by hand, forever.

Our own plan was a seven-year workbook, and replatforming it taught the lesson better than a design session would have. Of roughly 178 rows, about 14 were decisions. Everything else was a lookup into actuals or a formula chained off those 14. That ratio is not unusual. It is every operating model anyone has ever opened.

So only the levers are authored. Growth, days sales outstanding, bill rate, capex. Everything else derives: the income statement closes, working capital follows from the flow rates, the balance sheet rolls, retained earnings computes itself, cash is the balancing figure, and the cash flow statement comes from the period-over-period deltas. The boundary between actual and forecast is not a setting anyone maintains. A month becomes actual when it closes.

A scenario is an object, not a copy of the file. Budget, rolling reforecast, downside case: each one is a named set of levers, and switching between them is a filter over the same statements rather than a different workbook with a different set of bugs. Which makes variance analysis stop being a reconciliation exercise. Actuals are simply the scenario with no levers in it, so budget versus actual is arithmetic over two slices of the same numbers rather than a comparison of two documents that were built by different people at different times.

Schedules turned out to be forecasts. This was the surprise, and it closes the loop back to where this section started. A depreciation schedule already says what will happen for the next thirty-six months. So the forecast engine does not model depreciation separately, it consumes the schedule that is already sitting there. The register that blocks your close is the same register that populates your forward D&A line. Two things that live in two different tabs and get reconciled by hand every quarter turned out, once they were in the same system, to be one thing.

Levers derive backward and assert forward. Days sales outstanding is a measurement in the months that have closed and a decision in the months that have not, and the same element carries both. So authoring a lever is not staring at an empty box. The system computes your trailing DSO out of the actuals and asks whether you want to assert something different going forward.

And the check rows changed jobs. Every model has a row near the bottom labeled CHECK that displays zero, and I have never once seen one stop anything. Here the same rules that verify the actuals verify every forecast month, and they gate rather than display. A scenario that does not foot does not publish.

You can still override a number. That was non-negotiable, because a model you cannot override is a model nobody will use. But you override it by asserting a leaf, and the assertion still articulates upward through the rollups, into retained earnings, into cash, into the cash flow statement, and stays subject to verification. You change the number without leaving the model.

In a spreadsheet, typing over a formula is precisely the act of leaving the model, and it leaves no trace that you did.

What you can do once nothing is disconnected

Individually those are four features. Together they change the class of question you are allowed to ask, and that is the part worth staying with.

You can ask the ledger instead of an export. "Why is consulting revenue down eight percent this quarter" is answerable, because the path from the number on the statement to the facts beneath it to the postings beneath those to the events that caused them is unbroken. The answer is a traversal rather than an inference. Nobody has to go find out first.

Every number decomposes. Take a figure on a statement and it opens into the facts it summarizes, the postings under those, and the events that caused the postings, each one stamped with how it was constructed. That is the request an auditor makes in week one, and satisfying it is normally an archaeology project across four artifacts and two people's memories.

One block, seven lenses, no export in between. Anything in the system can be looked at as a rendered statement, a flat table of facts, its underlying structure, the elements it uses, the rules governing it, the verification results, or a chart. Those are not seven exports of one thing. They are seven views of one thing, and switching between them costs nothing because nothing is being converted.

Metrics stop being a separate tool. A metric is defined once as a formula over concepts you already have, then computed as a standing time series alongside the statements. Gross margin, DSO, revenue per head. They live in the same place as the numbers they are computed from, which means they cannot silently be computed from a stale copy, which is the ordinary fate of a metrics dashboard fed by an export.

The reporting package can be sent, not attached. A report goes to a recipient as the package, carrying its facts and provenance, rather than as a PDF that has to be trusted and a workbook that has to be re-keyed.

And it composes better than we expected. The most persuasive evidence that the shape is right is how little the forecast layer needed. The articulation reused the rendering engine. Verification extended into forward months without modification. Schedules turned out to already be forecasts. Almost nothing had to be built a second time, which is what happens when the pieces share a substrate instead of sharing an export format.

The report that keeps working after it leaves

Here is the part I did not expect to be possible, and it turned out to be the clearest proof of everything above.

Everything described so far runs inside a system. The application talks to a backend, the backend serves the ledger, and the connections between things are alive because they are all in the same place. That is the easy case. The hard case, and the one that has always broken, is what happens when the report leaves.

So take a finished report out as JSON-LD and download it. It is now detached. No API behind it, no authentication, no session, no relationship of any kind to the system that produced it. It is a file on a laptop, which is exactly what a financial report has always been.

Except this one still knows what it is. Every fact still carries its concept, its period, its unit, its balance type, its place in the calculation hierarchy, and its label. Everything a filed XBRL report would carry, it carries, because it is the same information expressed in a form that does not need a reader to already understand XBRL.

Open it in a static web page with no backend behind it and the page reconstructs the entire report out of the graph: balance sheet, income statement, cash flow, equity, every disclosure section, the dimensional breakdowns, the text of the notes. Not a preview of a report. The report.

Now the part that matters. Point an LLM at that file and it does not summarize a document, because there is no document to summarize. It has two tools: one that hands back the report's own vocabulary and the concepts and periods actually present in it, and one that runs a read-only query. So it asks the file what it contains, writes a query, reads the rows, notices something, writes another query to check it, and builds an analysis out of what it found.

That is a different act from answering a question. The narrative it produces is derived from the report rather than asserted about it. When it tells you margin compressed in the second half, it got there by querying for the margin in each half. Its instructions are to look up the vocabulary first and never guess at it, and never to state a figure the report does not contain. It has no reason to invent one. The numbers are right there and it can go and fetch them.

The query engine runs in the browser. There is no server anywhere in that loop. Open the file on a plane and it still works.

And then it will read the whole thing out loud, if you want it to.

Compare that with sending a financial report today. Send a PDF and the recipient's AI can read the pixels and infer. Send a workbook and it gets a grid with the meaning stripped out. Send an XBRL instance and it is genuinely machine-readable, which was real progress and remains so, but it is close to unusable without specialist tooling and there is no way to have a conversation with it.

Send this file and it renders like a report, queries like a database, and analyses like an analyst. One file, detached from everything, and none of that capability came with a server attached. No account, no vendor, no network connection.

The idea is not without precedent, and the lineage is worth naming: Arelle's inline XBRL viewer has done the rendering half for years, and it is good work we learned from. What is different here is that the artifact underneath is a graph rather than a document. That is the whole reason the second half is possible at all. You cannot run a query against a document. You can run one against a graph, and once you can do that, the difference between reading a report and interrogating one collapses.

That is what an export looks like when the meaning survives it. Every other argument in this essay is a case for why a number should keep its context. This is what you get to do once it has.

It is live at holon.robosystems.ai, and you can go and try it on a real report right now without signing up for anything, because there is nothing to sign up to. Rendering a report needs no key at all. Asking it questions needs your own Anthropic key, and hearing the answer needs your own ElevenLabs key, both of which stay in your browser, because a static page has nowhere else to put them. That arrangement is not a limitation we are apologising for. It means your financial report is never handed to somebody else's server in order for you to read it.

What actually makes it AI-native

Not the chat box.

Because meaning survives every step now, an AI can operate this system rather than describe it. When you want a new scenario, you describe it in plain language and the levers are authored through the same envelope the user interface uses. Not a parallel endpoint that does something similar. The same operations, so a block created by an agent and a block created by a person are the same object made the same way.

The division of labor underneath deserves to be precise, because "AI does your accounting" is a claim that should make an accountant suspicious.

The model proposes. It suggests a mapping, drafts an event, argues for a lever value. The engine derives, and the cascade that walks a forecast forward is ordinary deterministic code with no model in the loop at all, which is also why running it costs nothing. Verification gates, using the same rule corpus that governs the actuals. And a person approves, because every transaction arriving from a connected system lands as captured rather than posted, and the decision to post is theirs.

Nobody is being asked to trust a language model with the general ledger. They are being asked to review proposals in an inbox, which is a thing accountants already do all day.

What it does not do

Being straight about the limits is the only thing that makes the rest of it worth believing.

It does not fix a bad chart of accounts. If your accounts encode meaning inconsistently, this system will represent that inconsistency faithfully and then reason over it with total confidence. Structure amplifies whatever you give it. A connected system built on a muddled chart of accounts is a muddle you can now query quickly.

Verification certifies reconciled, never right. The rules confirm that the numbers are present and that they tie. They say nothing about whether the number is the correct number. A forecast can foot perfectly in every period and still be a fantasy, and the system will publish it without complaint, because adequacy is a judgment and judgment is not what a rule engine does.

The authoring surfaces are uneven. Some of this system has the polished form you would expect and some of it does not. Scenarios are the clearest example: you can read and compare them in the interface, but you author them by describing what you want to Claude, because the typed lever form has not been built yet. That is honest about where we are. It is also the reason the previous section is not a marketing line. Talking to the model is not the demo version of the lever form, it is what we actually use, and it turned out to be a better interaction than the form would have been.

And it does not remove the accountant. Nothing here decides anything. It proposes, derives, checks, and refuses. Every one of those is in service of a person who is still the one who says yes.

Why it is open source

You cannot ask a controller to trust a black box with the books.

The entire claim of this system is that every number can be walked back to why it exists. The database enforces that literally: a fact cannot be written without declaring how it was constructed, and the constructor rejects any attempt that does not. Pivoted from posted transactions, generated by a schedule, derived by formula, asserted by a person, bound to a document, projected by the forecast engine, or filed with a regulator. Seven origins, mandatory at the moment of writing, with no back door.

A claim like that is worth exactly as much as your ability to check it. So the code doing the walking is public. The platform and the applications are Apache 2.0. The clients, the shared rendering library and the report viewer are MIT, on the reasoning that anything you might embed in your own work should carry the least restrictive terms we can give it. You can read the enforcement yourself. You can run the whole thing against your own books and never talk to us.

The viewer is the case where being open stops being a principle and becomes load-bearing. It is a static page with no backend, which means the only way to trust what it tells you about your report is to be able to read how it got there. Any key you give it stays in your browser, because there is nowhere else for it to go.

Open source here is not a marketing position and it is not a pricing tier. It is the only honest way to make an auditability claim.

The thing underneath all of it

What changed here is not any single feature. It is that the chain of exports stopped.

Once it stops, the things that were hard because of it stop being hard. Not because the tools got smarter, but because we stopped handing them the residue. A close that knows what is outstanding, a statement you can render at any moment, a footnote bound to the number it explains, a forecast that cannot publish without footing, an answer to "why is this number what it is" that takes a second: none of those are clever. Every one of them was blocked by the same thing, and it was never intelligence. It was that the connections had been thrown away four steps earlier and stored in a person.

The books have always known why every number is what it is.

We just kept throwing that away on the way to the spreadsheet.

J

Joey French

Writing about what changes when accounting runs on a ledger Claude can query.

See it on your own books

Connect QuickBooks and ask Claude the first question. Nothing writes to QuickBooks until you post an entry. We close our own books this way.

Get Started

Already have an account? Login