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.
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.
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.
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.
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.
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.
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.
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.
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).