Apply to my task
arXiv:2610.20809 ★ 89 Oct 14, 2026

Compute It Twice, Check the Totals: Verifying LLM Numbers Without a Gold Answer or a Judge

Key result

Out of 138 deliberately broken operations, the “code runs” and “model agrees with itself” checks missed between 101 and 129. An independent second implementation missed zero. The method lets you verify numbers an LLM computed when you don't have the right answer. The trick: don't ask the model to grade its code, ask it to write the solution again without showing the first one. Then compare results on every record and add a conservation law: per-group sums must add up to the grand total. A bug has to pass both checks at once, and that's next to impossible.

01

TL;DR

Researchers at PayPal built an agent that expands its own set of computational operations and never lets a faulty one in. The agent doesn't do math “in its head.” It writes an expression in a tiny command language (a DSL, domain-specific language), and a trusted interpreter executes it. A new operation gets admitted on two conditions: the model wrote it twice independently, and both versions produced the same result on every record. On top of that, the result has to obey a conservation law: for example, per-group sums must add up to the grand total.

The headline finding: the usual “looks good” signals can't tell correct code from incorrect code. “The code runs without errors,” “the model agrees with itself,” and “the library got shorter” let almost every bug through. Out of 138 deliberately broken operations, those checks missed 101–129. An independent second implementation missed zero, and these were defects the model wouldn't have spotted right away. Asking the model to judge whether the code is correct doesn't work either: it wrongly rejected some correct operations and produced nothing verifiable.

The method boils down to two checks. First: write the solution a second time from scratch, from the text of the question, without showing the first one, and compare results record by record. Second: check invariants that must hold for any correct solution. Per-group sum = grand total, one result per unique key, empty input gives empty output, record order doesn't change the outcome. A bug has to slip past both checks at once.

Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.

02

Method Blueprint

INNER LOOP (expand coverage without new operations)
STEP 1: The model invents new questions about the data → question + expression
STEP 2: The expression runs on every record → one number per record
STEP 3: The model answers the question TEXT again, separately → second expression
STEP 4: Accept the question only if both expressions match on ALL records
        and the quantity is new

OUTER LOOP (add a new operation)
STEP 1: Count which operation the model is missing most often → gap ranking
STEP 2: The model writes the operation (top-3 gaps, one at a time) → operation code
STEP 3: THE GATE:
        a) a second independent implementation gives the same values (tolerance 10⁻⁶)
        b) conservation laws hold on already-verified operations
        c) every question the operation unlocks passes the inner-loop check
STEP 4: Passed everything → into the library, the inner loop runs again

Each step is a separate call to the model. The second implementation is written in a separate call with no access to the first.

03

Example in Practice

The task: You sell on Amazon and have a quarterly order export: about 40,000 rows with columns customer_id, amount, city, date. You want to know which customer brought in the most revenue and how much each city contributes. These numbers are going into an investor deck, so there's zero room for error. You need a chat that can run code (ChatGPT with data analysis, Claude with file analysis, or any agent with a sandbox).

Prompt, chat #1:

Here is the file orders.csv. Columns: customer_id, amount, city, date.

Question: “Which customer brought in the most revenue, and how much was it?”

Write Python (pandas) code, run it, and return the result.
Show the code itself.

Prompt, chat #2 (a new chat, do NOT show the first solution):

Here is the file orders.csv. Columns: customer_id, amount, city, date.

Question: “Which customer brought in the most revenue, and how much was it?”

Solve it without pandas.groupby: use plain Python
(csv, dictionaries, loops). Run it and return the result.
First write how you understand the question, then the code.

Prompt, chat #3 (reconciliation and conservation law):

Here are two independent solutions to the same question and their results.
[solution 1 + result]
[solution 2 + result]

1. Compare the results. If they differ, find the cause
   (different reading of the question, handling of empty values, duplicates).
2. Check the invariants by running code on orders.csv:
   - revenue summed across all customers = sum of the entire “amount” column;
   - number of groups = number of unique customer_id values;
   - revenue summed by city = total revenue.
3. Output a table: check | expected | actual | passed/failed.

The result: In chat #3 the model compares the two answers and names the discrepancy if there is one. Then it runs the checks and outputs a “check / expected / actual / status” table. If both solutions are correct, the numbers match and every invariant passes. If one solution drops rows with an empty city or mishandles duplicates, the discrepancy surfaces before the deck goes out.

04

Why It Works

The weakness. If you just ask the model “is this right?”, it judges plausibility, not correctness. Wrong code runs too, looks just as tidy, and convinces the “judge” just as well. The model looks at its own mistake through the same lens that produced it: lock onto one solution and the bug stays invisible.

The strength. Models are good at writing code from a text description. Two solutions written independently, with different implementations, rarely fail the same way. Conservation laws are also easy to check and need no gold answer: the parts must add up to the whole, and you know that in advance.

How the method exploits this. Instead of “figure out whether it's right,” we ask “do it again and compare the numbers.” That turns a subjective judgment into a mechanical check. The conservation law catches what the pair of solutions misses: if both copies share the same bug, the per-group sums still won't reconcile with the grand total. In the experiment, double solving on its own let almost all of these shared bugs through (129 of 138), while conservation laws cut the misses to 10 of 138. The layers complement each other.

Control knobs: - Style of the second implementation (a different library, plain Python instead of pandas) → less chance of repeating the same mistake. - Second implementation in a different model → even more independence. In the study, an independent implementation from a different model family also missed zero bugs. - Set of invariants → tailor it to the task: “per-group sum = total,” “number of results = number of unique keys,” “empty input → empty output,” “order doesn't matter.” - Comparison tolerance → for money, use an exact match or down to the cent; for fractional calculations, use relative error. - Edge cases → add checks for empty values, duplicates, and a single element. In the study, edge cases are exactly what catch the sneaky bugs.

05

Prompt Template

You can bring this method into a chat. Below are two prompts: one for the independent solver, one for the reconciling judge. In the authors' system these are separate calls to a single frozen model.

<Task>
File: {file_or_data}
Columns/fields: {field_description}
Question: {data_question}
</Task>

<Mode>
SOLVER_A: solve the task, show the code and the result.
SOLVER_B (independent): new chat, do NOT show solution A.
  First describe in your own words how you understand the question.
  Then write a solution in a different style: {different_style}.
</Mode>

<Verify>
1. differential: compare the results of A and B on every record
   (tolerance {tolerance}). Discrepancy → find the cause, do not average.
2. conservation (conservation-law check), run code:
   - sum(result_by_group) == sum({sum_field})
   - number of groups == number of unique values of {group_field}
   - empty input → empty result
   - the result does not depend on row order
   - {your_invariant}
3. Every check must rest on actual computation,
   not on a claim that “this is obviously correct.”
</Verify>

<Output>
Table: check | expected | actual | status.
Verdict: ACCEPTED (everything matched) or REJECTED (what exactly failed to match).
</Output>

What to fill in: - {file_or_data}, {field_description}, {data_question} — your task. - {different_style} — for example “plain Python without pandas,” “SQL instead of pandas,” “loops instead of groupby.” - {tolerance} — “exact match” for integers and money, “1e-6 relative” for fractional values. - {sum_field}, {group_field} — the columns the conservation law holds over. - {your_invariant} — any rule you know holds, for example “the shares add up to 100%.”

🚀 Quick start — paste this into the chat:

Here is a “compute twice + conservation law” template. Adapt it to my task: [your data task]. 
Ask me questions to fill in the fields.

[paste the template above]

The LLM will ask about the data structure, the groupings, and which sums or counts should reconcile, because the method needs concrete invariants — conservation laws that hold in a way you know in advance. It will take the pattern from the template and adapt it to your table.

06

Limitations

⚠️ Code execution is required: All the reliability hinges on the interpreter computing the number, not the model. In a chat without code execution, the method turns into yet another eyeball check and loses its point.

⚠️ The full method is an engineering job: The authors' system (sandbox, restricted language, automated loop, gap ranking) requires code. In a chat you can only reproduce the core: double solving and invariant checks, without the self-growing library of operations.

⚠️ This is testing, not proof: The tolerance is checked on a finite set of records. The conservation laws are written by the model itself. The method shows that an operation passed the target tests, not that it is correct on every input.

⚠️ A shared bug in both copies: If both copies contain the same error, double solving is blind. In the authors' experiment, conservation laws covered this case, but not completely: a small fraction slipped through. Deliberately sneaky bugs designed around the checks also got past.

⚠️ You need a checkable invariant: Where there's no conservation law, the method is weaker. For example, “the most frequent value” is a non-numeric maximum with no conservation law. The authors honestly left such cases out of scope.

⚠️ Ambiguous questions: Two implementations may read the question differently. The authors ran into this with “the busiest day”: different tie-breaking rules gave different answers. A discrepancy isn't always a bug; sometimes it's a signal that the question needs clarifying.

⚠️ Correct operations sometimes get rejected: Of 14 correct operations, one was rejected because of a badly formulated law, not a wrong value. You need a human to review rejections.

⚠️ Tested on mid-size open models: Qwen, Mistral, Gemma, Llama. Weak models don't always produce usable operations. The authors didn't test on flagship models.

07

How They Studied It

The idea was simple: with no gold answers and no judge, can you still safely expand an agent's capabilities? The team took a single frozen model (Qwen3.6-35B-A3B) and a tiny computation language over a table of transactions. The agent used it to invent questions and write expressions. The data was fully synthetic: 63 test “merchants.”

The most telling experiment was a mutation test. The researchers took 14 accepted operations and broke each one with every possible single-point edit. That left 138 genuinely wrong variants. Then they ran them through different checks. Simply running the code missed 129 of 138, self-consistency also missed 129, and the “library compression” rule missed 101. An independent second implementation missed zero. When a bug was deliberately written into both copies, double solving missed 129, while conservation laws cut that to 10. Takeaway: they catch different classes of errors, so you need both layers.

Next they tested scale and transfer. In a single pass, the inner loop expanded the question set from about 10 to 36, and over several passes to 60-plus, all without new operations. On three independent starting sets, the outer loop invented the missing operations on its own, for example “sum by group.” A control run without induction produced not a single new question of that type. Agreement with independent “gold” code on 3,000 test merchants was perfect for every computable type. With no code changes, just a swapped parser, the method grew question sets on accounting data (BookSQL) and medical records (EHRSQL): tenfold and nearly twentyfold growth. On other models (Qwen3 from 4B to 32B, Mistral, Gemma, Llama) the gate stayed reliable everywhere; the only thing that changed was yield, i.e., how many operations the model managed to come up with.

The surprise was that the reliability of the check didn't depend on model strength. A weak model didn't introduce wrong operations; it simply didn't write anything admissible. The practical upshot: safety comes from mechanical verification, not from model quality.

08

Adaptations and Extrapolations

🔧 Technique: second implementation in a different model → fewer shared errors

In the study, an independent implementation from a different family (Gemma instead of Qwen) also missed zero errors. In chat, solve the task in ChatGPT and order the “second copy” from Claude or Gemini:

Here is only the question and the column description (I am NOT showing the code of the first solution).
Solve it a different way: {different_style}. Run it, return the number.

🔧 Technique: demand a report on the checks → missed cases become visible

Add to <Output>: “List the edge cases you checked (empty values, duplicates, a single row) and the result of each.” That way you'll see whether the model skipped what the researchers caught with “fuzzing.”

Extrapolation: a “compute twice” rule in an analytics agent's instructions file

The authors' idea (any number is accepted only after an independent check and a conservation law) fits naturally into a CLAUDE.md or the system prompt of an analyst agent. The paper has no such prompt; this is a transfer of the principle:

## Rules for numbers in reports
- Compute every number that goes into a report TWICE, using independent methods
  (a different library or a different coding style). Write the second method without
  looking at the first.
- Accept the numbers only if both match on every row.
- Then check the invariants: per-group sum = total; number of groups = number of
  unique keys; empty values handled explicitly.
- If a check fails, do not round and do not average: report the discrepancy
  and describe its cause.
- In the report, state which checks passed.
09

Resources

  • Paper title: A Self-Improving Agent that Grows its Own DSL: Oracle-Free Operator Induction for Exact Question Answering (preprint).
  • Authors: Yun-Shiuan Chuang, Yirou Ge, Yixi Li, Yiming Bian, Zijie Pan, Jenna L. Ballard, Uma Kona, Linsey Pang, Prakhar Mehrotra — PayPal AI.
  • References: differential testing (McKeeman, 1998; Yang et al., 2011); metamorphic testing (Chen et al., 1998; Segura et al., 2016); Program-of-Thoughts (Chen et al., 2023); skill libraries (Ellis et al., 2021; Grand et al., 2024; Wang et al., 2024b). Datasets BookSQL and EHRSQL (built on MIMIC-III).

Research digest

Key result

Out of 138 deliberately broken operations, the “code runs” and “model agrees with itself” checks missed between 101 and 129. An independent second implementation missed zero. The method lets you verify numbers an LLM computed when you don't have the right answer. The trick: don't ask the model to grade its code, ask it to write the solution again without showing the first one. Then compare results on every record and add a conservation law: per-group sums must add up to the grand total. A bug has to pass both checks at once, and that's next to impossible.

Principle

The method works like two accountants tallying the same ledger in separate offices. They compare totals, then check the balance: the sum of the line items equals the grand total. The model doesn't do math in its head. It writes code, and the interpreter produces the numbers. The two checks plug different holes: 1. Compute twice. The second solution is written in a new chat from the text of the question. The first one stays hidden. Results are compared on every record. 2. Conservation laws. These are rules that hold for any correct solution: the per-group sum equals the total, and there are as many groups as unique keys. Empty input gives an empty result. Row order makes no difference. Instead of “figure out whether it's right,” you ask “do it again and compare the numbers”. An opinion becomes a mechanical reconciliation.

Why it works

Ask a model “is this right?” and it judges plausibility, not correctness. Broken code runs too and looks tidy. The model sees its own mistake through the same lens that made it. But models write code well from a task description. Two solutions written independently and in different styles rarely fail the same way. That leaves the case where the bug lives in both copies. Here double computation is blind: it missed 129 of 138 such bugs. Conservation laws cut the misses to 10 of 138. No gold answer needed: the parts add up to the whole, and you know that in advance. The kicker: asking “is this code correct?” not only verifies nothing, it also rejects correct operations. The layers complement each other because they catch different bugs.

When to apply

Spreadsheet analytics → reports on revenue, orders, payments where the total goes to investors or accounting → especially when the data has empty values and duplicates. It also fits any grouped calculation where the parts add up to a whole. NOT suitable for a chat without code execution: the check turns into eyeballing. Weaker where there's no conservation law. Example: “the most frequent value.” Also not a fit for ambiguous questions. Two copies can read the question differently, and then a discrepancy points to bad wording, not a bug.

Mini recipe

1. Solve it once: in a chat that can run code, ask your data question. Ask it to show the code and the result. 2. Open a new chat: same task, but don't show solution #1. That's the key to independence. 3. Switch styles: in the second chat, ask for a different approach, for example plain Python without pandas or SQL. That lowers the odds of repeating the same mistake. 4. Make it restate the question: have the model first say in its own words how it understood the task. Any mismatch in understanding shows up right away. 5. Reconcile: bring both solutions into a third chat. Compare the results; for money, use an exact match or down to the cent. 6. Run the conservation laws: the per-group sum equals the grand total, and there are as many groups as unique keys. Add empty input and row order. 7. Review rejections yourself: don't average out a discrepancy. Find the cause. Sometimes the error isn't in the code but in the law itself. 8. Boost independence: if the stakes are high, have a different model write the second solution.

Examples

[BAD]: `Here is orders.csv. Which customer brought in the most revenue? Write code and verify the answer is correct.` [GOOD]: Chat 1: `Here is orders.csv (customer_id, amount, city, date). Which customer brought in the most revenue, and how much? Write pandas code, run it, show the code and the result.` Chat 2, new, without solution #1: `Same file, same question. First write in your own words how you understand the question. Then solve it without pandas.groupby, in plain Python: csv, dictionaries, loops. Run it and return the result.` Chat 3: `Here are two solutions and their results: [solution 1], [solution 2]. Compare them. If they differ, find the cause: empty values, duplicates, reading of the question. Then run checks on orders.csv: revenue summed by customer equals the sum of the “amount” column; number of groups equals the number of unique customer_id values; sum by city equals total revenue. Output a table: check | expected | actual | passed or not.`

In plain words

When a language model does arithmetic “in its head,” it's almost always a disaster. Asking it to double-check itself is just as pointless: it judges how plausible the text sounds, not the math, and confidently signs off on its own screwup. PayPal tackled the problem head-on: no calculations inside the neural net, period. Their self-improving agent writes commands in its own mini-language (a DSL), feeds them to a dumb external interpreter, and grows its own toolkit without hints from a human oracle.

Picture hiring an accountant who skips the calculator, eyeballs your taxes “by feel,” then glances at the draft and says “yep, looks legit.” Total fail. So the engineers gave this worker strict house rules: invent a new function, then write it two different ways from scratch. Only if both scripts agree to the penny across thousands of rows, and the parts add up to the whole, does the tool make it into the working arsenal.

The screening is brutal: the method rests on double independent generation plus checks via conservation laws. Asking the model “are you sure?” is useless, because pretty, wrong code runs just as smoothly as correct code. So the system demands a 100% match between two different solutions across the whole dataset. If revenue by city doesn't reconcile with the grand total, the code goes straight in the trash, no matter how convincing the logic looks.

The mechanics were stress-tested on heavy tables like quarterly marketplace exports of 40,000 rows, where an error in front of investors is fatal. But the principle is universal: plug this pipeline into any model with a code sandbox, like Claude or ChatGPT, and the agent stops making stuff up. Financial reports, inventory counts, complex logistics: the approach plugs the holes anywhere you need pharmacy-grade precision rather than a neural net's creative writing on the subject of math.

Bottom line: stop blindly trusting the “expert” calculations a language model spits out from a single prompt. Want rock-solid facts? Make the AI grow its own DSL and validate every operation through external code. Autonomous growth without hallucinations is possible, but only if you clamp the model in a vise of hard invariants and ignore its subjective “I think so.”

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on Compute It Twice, Check the Totals: Verifying LLM Numbers Without a Gold Answer or a Judge arXiv:2610.20809

Sign in to apply this study New accounts get 50 free credits.