
I Tried to Make an LLM Catch Its Own Tax Errors. It Can't, and That Turned Out to Be the Whole Business.
The claim was grammatically perfect. That was the problem.
I still remember the first position that made me stop and put my coffee down. An AI had drafted a line about the new OBBBA car-loan interest deduction, and it read: "the new OBBBA car-loan interest deduction is an above-the-line deduction that reduces the client's AGI." The sentence was clean. It was confident. It was formatted like every defensible position I had ever read. And it was wrong in the exact way that costs a real person real money.
The qualified passenger vehicle loan interest deduction (QPVLI) is a below-the-line deduction under §63(b)(7). It does not reduce adjusted gross income. Putting it above the line is not a spelling mistake you catch on a reread. It quietly moves AGI, and AGI is the number half the return keys off. What surprised me was not that a model got a statute slightly wrong. It was how good the wrong answer looked.
A hallucinated citation is easy to catch. A confident misclassification, written in perfect tax English, is the one that gets filed.
That was the moment the actual problem came into focus for me. The industry has spent three years automating the drafting of tax work, and it did a genuinely good job. Thomson Reuters auto-prepares 1040s. CCH Axcess drafts advisory insights across thousands of firms. Blue J answers research questions in plain language. Preparation is being solved. But the step after preparation, the one where somebody has to decide whether the position is actually defensible under the statute, got handed to the same probabilistic model that drafted it. And under IRC §6662, the 20% accuracy-related penalty lands on the human who signed the return, not on the algorithm that wrote it.
I spent a week trying to make the model grade its own homework.
My first instinct was the obvious one, and I want to be honest that I chased it for longer than I should have. If the model can draft the position, surely a good enough prompt can make it check the position. So I tried. I gave it the statute. I gave it the QPVLI rule spelled out. I asked it to audit its own output and flag anything that put a deduction on the wrong line.
It caught some. It missed others. And the misses were the scary kind, because when it was wrong on the audit it was wrong with the same fluent confidence it had when it drafted. The self-check ran through the same weights that produced the error in the first place. Asking a model to police itself is asking the thing that made the mistake to also be the thing that notices the mistake, using the identical reasoning that made it.
I remember explaining this to a colleague and hearing myself say it out loud: "we cannot trust an LLM to police an LLM." That sentence is when the design flipped for me. I had been trying to make the model more accurate. The real answer was to stop trusting the model to be the judge at all.
You cannot make a probabilistic system deterministic by asking it nicely. You move the verdict outside it.
The distinction that took me too long to internalize is that drafting and verification are not the same task made easier or harder. They are different problems. Drafting rewards fluency, coverage, and plausibility, which is exactly what a language model is built for. Verification rewards being provably right about one specific rule, and being able to show your work to an examiner who was not in the room. Those are opposite temperaments. I stopped trying to make one system do both.
What does "agent advises, code decides" actually mean?
I want to be precise about the architecture I landed on, because the phrase can sound like marketing until you see where the line is drawn. In StatuteGuard, the demo I built, the language model does exactly one job: it reads messy natural-language tax language and proposes a structured, typed claim. That is the only neural step. It is genuinely good at that, and when it is not sure, it abstains and the position escalates to a human instead of getting a guessed verdict.
Everything after that is code. The verdict is decided by a deterministic policy engine, real OPA/Rego with an identical pure-Python twin, running rules I wrote out against the primary law. Neural extraction, symbolic verification. The model advises. The code decides. And the difference is not academic, because the code cannot be talked out of its answer by a well-written paragraph.
The part I did not expect to care about as much as I do is readability. The policies are not a black box I am asking you to trust. They are decision tables and Rego source you can open and check against the statute yourself.

That screenshot is the whole thesis in one panel. A Head of Tax should be able to sit with their compliance partner, open the rule, and confirm it against §30D before trusting a single verdict. When the logic is a paragraph of model reasoning, you cannot do that. When it is a rule you can read, you can.
So what happens when the code says no?
The first time I ran that OBBBA car-loan position through the finished gate, I actually smiled. The model had drafted the "above-the-line, reduces AGI" claim exactly as it had before. But this time the deterministic engine looked at the extracted claim, matched it against the encoded §63(b)(7) rule, and returned a hard verdict: BLOCK. Do not file.

What I find persuasive about this view, and what I hope a tax reader finds persuasive, is the cascade. The engine does not just say "wrong line." It shows you the five downstream places a false AGI reduction would corrupt: adjusted gross income itself, AGI-coupled state income tax, the Medicare IRMAA premium surcharge, the 7.5% medical-expense deduction floor, and student-loan income-driven repayment. One misclassified deduction is not one error. It is a small blast radius, and the panel makes the radius visible.
Then it animates the reason, which is the piece I am most attached to. It walks the citation chain across the IRC cross-reference graph, node by node, so the "no" is never a bare assertion.

Here is the detail I keep coming back to, because it is the one that proves this is not a toy problem. Per the demo's own README, the "above the line" mislabel is not something I invented to have a villain. It is a documented consensus error that mainstream tax-prep guidance, including H&R Block's site, has published. A plausible, well-written, widely-repeated wrong answer is exactly the failure mode a deterministic gate is for. The crowd being confident does not make the deduction move to AGI. The statute decides that, and now so does the code.
The most dangerous tax error is not the one that looks wrong. It is the one that looks right, sounds right, and shows up in three vendors' guidance.
If you want to sit with any of this, the running demo is at veriprajna.com/demos/tax-compliance-ai. You can paste your own position and watch the gate decide.
The feature I almost got wrong: knowing when to say "I don't know"
I have to admit the mistake I nearly baked in, because it is the one every engineer building a verification tool wants to make. My early instinct was to make the machine answer everything. Coverage felt like the goal. A tool that returns a verdict on every position looks more finished than a tool that sometimes shrugs.
That instinct is wrong, and a specific position taught me why. Consider the §280A home-office deduction. Whether a spare bedroom is used "regularly and exclusively" as a principal place of business is a facts-and-circumstances test. There is no clean rule to encode, because the answer depends on how a real person actually uses a real room. If I forced the deterministic engine to rule on it, I would be doing the exact thing I built this to prevent: manufacturing a confident verdict where the honest answer is "a human needs to look at this."

So the gate has four verdicts, not two. PASS when the position is defensible. BLOCK when it contradicts the encoded statute. NEEDS-REVIEW when it is a genuine gray area. OUT-OF-COVERAGE when the provision simply is not encoded in this version. The last two both mean the same honest thing: a person decides this one, not the machine. Building the escalation path felt like admitting a limit. It is actually the most important feature in the product, because a verification layer that never says "I don't know" is just a second model bluffing with extra steps.
The numbers, and exactly what they do not claim
I am careful with the benchmark, more careful than a marketer would want me to be, because the way these numbers are usually stated is a lie. I ran the deterministic engine against a labeled golden set of 42 pre-classified positions (14 clean, 16 error, 12 escalate) and measured what the layer does.

On that 42-case golden set: 71.4% deterministic coverage, meaning the engine resolved that share to PASS or BLOCK on its own and correctly escalated the rest. 100% gate precision, meaning zero correct positions were wrongly blocked. 100% error-catch completeness on the encoded provisions. 100% of gray areas correctly escalated. Throughput ran in the tens of thousands of positions a second (about 58,000 in the run I screenshotted, though that is machine-dependent), because verification is infrastructure, not a model call.
Now the part I insist on. Those numbers are true on that golden set, not as an open-world guarantee. I will not tell you StatuteGuard is "100% accurate," because that sentence is dishonest the moment you leave the labeled set. What I will tell you is subtler and, I think, more durable: because the verdict is deterministic code, its behavior on the encoded provisions is reproducible and provable, not a probability that drifts. I even cross-checked every one of the 42 verdicts against OPA 1.17.1 and the pure-Python twin, and they matched exactly. That is the claim I can stand behind. It describes the layer, not the model.
"100% accuracy" is a marketing number. "Reproducible on the encoded provisions, with honest escalation everywhere else" is an engineering one. I would rather ship the second.
And that is why this does not age out. A better base model next year still cannot prove to an examiner which statutory provision backed which position. Coverage, gate precision, and a filable audit trail are properties of the verification layer. They are not a model error rate that shrinks as models improve.
The artifact I did not know I was building until an examiner asked for it
I did not set out to build a compliance document, but the more tax people I talked to, the more the conversation kept ending in the same place: "fine, it caught the error, but what do I hand the IRS?" So every verdict now writes a filable §6662 due-diligence record, a printable workpaper that documents the position was verified against the statute before filing. Source workpaper, provision, primary source, the extracted claim, the determination narrative, the full citation chain. It is the evidence that a reasonable-cause, due-care position was actually taken, which matters directly under the AICPA SSTS revisions effective January 2024.
There is one more reason I care about where this runs, and it became concrete after the Heppner ruling (SDNY, February 2026), which raised a privilege-waiver question about feeding client research into a public AI tool. StatuteGuard runs fully locally with no API key by default. No position and no client data leaves the perimeter. After Heppner, a closed, local, auditable architecture is not just a nice-to-have on a security review. It is legally material. I did not design the local-first posture for that ruling. But the ruling is why I now lead with it.
For context on the stakes, US business tax-compliance costs run past $126 billion a year (WP1 solution research, 2026), and the IRC §6662 penalty is 20% of the underpayment, with §6663 fraud exposure reaching 75%. When the drafting is automated and the penalty is personal, the verification step is the one that should keep a Head of Tax up at night.
What I actually believe now
I started this thinking I was building a better tax AI, and I want to end by saying plainly that I was wrong about what the problem was. Your tax AI does not have an accuracy problem. It has a verification problem, and a better model will not fix it, because the 20% penalty lands on your signature, not on its weights. Personalizing and automating the drafting of tax work is real progress. It is also not the same thing as proving a position is defensible, and the industry has been quietly treating them as if they were.
The demo lives at veriprajna.com/demos/tax-compliance-ai if you want to try to break the gate. I would genuinely like you to.
And if you would rather watch the gate decide than read me describe it, here is the whole thing running end to end.
So here is the question I keep asking tax leaders, and I do not have a comfortable answer to it yet. When an AI drafts a position and you sign the return, what is the artifact that proves you verified it, rather than trusted it? If the honest answer is "nothing, I trusted the model," then the model is not your assistant. It is your co-signer, and it cannot be summoned to the audit.


