Apply to my task
arXiv:2610.29005 ★ 81 Oct 21, 2026

VeriEvolve: The Checking Program Comes First, Then the Agent

Key result

The agent says "done," and the files have quietly gone missing. That's what happens when it grades its own work. The VeriEvolve method lets you make the agent write a check of the final state (files, database, repository) first, and only then start working. The check is built before the work and frozen: you can't bend the yardstick to fit the result. It includes tests for "almost correct" cases, like a folder named "2024-1" instead of "2024-01." An honest caveat: even this check is incomplete, and in the paper it missed 3 out of 21 wrong results. That's why the method has a built-in third step that extends the check.

01

TL;DR

VeriEvolve is a setup where the check on the result is built before the agent starts working. From the task text, a model invents test situations: correct, incorrect, and "almost correct." Then it writes a program that checks the final state (files, database, repository). After that the program is frozen and serves as the yardstick for improving the agent's workflow: understanding the task, planning, execution, self-review.

The key finding: most real-world agent tasks have no ready-made check. Having a language model grade the answer ("looks fine to me") is unreliable. You need to check the state after the work: are all the files there, is there anything extra, did anything break that you didn't ask to touch. The authors also found a weak spot. The generated check is incomplete: a weak agent found loopholes, and 3 out of 21 "accepted" results turned out to be wrong (neat formatting, wrong text). The fix for the check: take a strong agent's result and the weak agent's result that slipped past the check, compare them, and add the missing criteria.

The method has three stages. Stage 1: test situations and the check. Stage 2: improving the workflow while the check stays fixed. Stage 3: comparing a strong and a weak result, a new pair of tests, and an updated check that doesn't break old verdicts. Running this pipeline directly takes code. But the principles carry over into agent instructions, as shown below.

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

STAGE 1: Task + initial state → test situations
         (correct / incorrect / "almost correct")
         → checking program → frozen once internal thresholds are met
         (≥0.90 of correct ones accepted, ≥0.80 of "almost correct" ones rejected)

STAGE 2: A workflow with 5 nodes:
         understand the task → plan → execute → inspect the result → refine
         Each node has a set of prompt variants.
         The check is frozen and only scores the variants;
         an "evolver" model writes new variants based on the errors.

STAGE 3: Strong agent's result (reference) vs the weak agent's result
         that the check let through
         → list of differences → only the ones that follow from the task text
         → a pair of tests: "with the difference" (bad) and "without it" (good)
         → fix the check + regression (all old verdicts preserved)
         → freeze → repeat stage 2

Each stage is a separate run. There are four model roles: test generator, check creator, workflow evolver, and executor.

03

Example

The pipeline itself won't run in your chat. But its principle (criteria first, "almost correct" tests, comparing two runs) works in Claude Code or Cursor.

Task: A solo seller on Amazon and Etsy has a folder of 400 statements and invoices from Chase, Stripe, and Amazon. Their accountant asks to sort them into a year/month/bank structure, rename them using the YYYY-MM-DD_bank_amount.pdf pattern, lose nothing, keep the originals, and leave no empty folders. We launch Claude Code.

Prompt:

Agent task: in the /docs/biz_2024 folder, sort the statements into a year/month/bank structure in /docs/biz_2024_sorted, and rename them using the pattern YYYY-MM-DD_bank_amount.pdf. Do not delete or modify the originals. Do not create duplicates. There must be no empty folders.

STEP 1. Before starting, don't move anything. Create a /check folder containing:
a) tests_cases.md — a list of test situations: 
   - CORRECT (what the ideal final state should look like);
   - INCORRECT (a file is lost, a file is left in the old folder);
   - "ALMOST CORRECT" (folder "2024-1" instead of "2024-01", the date in the name in DD-MM-YYYY format, the file was copied but the original was modified, an extra empty folder, the amount with a comma instead of a dot).
b) check.py — a script that looks only at the final state of the folders and outputs PASS/FAIL for each criterion, naming the file.
Verify that check.py gives PASS on the correct situations and FAIL on all the incorrect and "almost correct" ones (create them in a temporary copy). Fix the script until this holds.

STEP 2. Lock check.py as immutable: during the work it must not be edited to "fit" the result. Do the task and run check.py. If there's a FAIL, fix the result, not the check.

STEP 3. If all checks pass, reread the task and write down which requirement from the text check.py doesn't cover. Add it separately: new tests (a "with error" / "without error" pair) and a fix to the script. The fix must not change the verdicts on the old tests. Run everything again and show the outcome.

Result: the agent will first create the list of test situations and the checking script, demonstrate that the script catches the "almost correct" cases, and only then start sorting files. You'll see a PASS/FAIL report by criterion, with the names of problem files. At the end the agent will name the missed criteria and extend the check without breaking the old tests. The specifics depend on your files, so don't expect a word-for-word match.

04

Why It Works

The LLM's weakness. When an agent grades its own work, it tends to see success: the result looks tidy, while the "lose nothing" requirement has been quietly violated. An LLM judge reads the description of the result rather than checking the state, so it misses vanished files and small deviations like an extra newline at the end of a file. Those are exactly the errors the authors found in the weak executor.

The LLM's strength. The model is good at writing tests and programs from the task text, and it's also good at comparing two results and describing the difference in words. From "lose nothing, don't modify the originals" it can derive checkable conditions: "the file count matches," "the hashes of the originals haven't changed."

How the method uses this. The criteria are written before the work, meaning before the agent is tempted to game them. "Almost correct" tests force the check to catch subtle errors. Freezing keeps the agent from "adjusting the yardstick." Comparison with a reference fills in the check wherever it missed an error.

Control levers: - Test types (correct / incorrect / "almost") → add "almost correct" ones for tasks where details matter (format, case, structure). - Freezing the check → forbid the agent from editing the check file during the work. Remove the ban, and it will tailor the check to the result. - Reference → take a run from a strong model (or a manually verified result) and compare it with the weak one. Turn the difference into a new criterion. - Number of rounds → the paper uses up to 15 workflow rounds and up to 3 check refinements. For a small task, 1–2 is enough. - Stopping condition → in the paper: the result matches the reference, there are no new differences, or the budget runs out. A repeat of an already-known error is a reason to change the workflow, not the check.

05

Prompt Template

This is a reconstruction of the principle, not a verbatim prompt from the paper: the accessible text has no ready-made prompts. The structure is preserved: roles (test generator, check creator, executor), freezing, comparing the reference with the weak result, regression.

<Role>
You work in three roles in sequence: Test-Suite Generator, Verifier Evolver, Workflow Executor. Don't mix the roles.
</Role>

<Task>
{task}
Initial state: {what exists now: folder, database, repository}
What must not be touched: {constraints}
</Task>

<Stage1_Evaluator>
Test-Suite Generator: from the task text and initial state, write test situations in the form of final states:
- POSITIVE: {number_correct} correct ones;
- NEGATIVE: {number_incorrect} clear errors;
- ADVERSARIAL: {number_almost} "almost correct" ones (a small error in format, structure, content, or a side effect).
For each situation, state the expected verdict: PASS or FAIL, and why.

Verifier Evolver: write a check {format: script / checklist}. It looks only at the FINAL STATE, not at what the agent said. The check outputs PASS/FAIL for each criterion, saying exactly where the problem is.
Run it on the test situations. Accept it only if the correct ones pass (≥ 90%) and the "almost correct" and incorrect ones are rejected (≥ 80%). Otherwise fix the check (up to {number_of_attempts} attempts).
Then freeze it: FROZEN_EVALUATOR_v0.
</Stage1_Evaluator>

<Stage2_Workflow>
Workflow Executor: do the task through this chain:
1) understand the task → 2) plan → 3) execute → 4) inspect the result → 5) refine.
After execution, run FROZEN_EVALUATOR. If there's a FAIL, fix the RESULT or the WAY YOU WORK. Don't change the check. 
Maximum {number_of_rounds} rounds. Stop when all criteria are PASS.
</Stage2_Workflow>

<Stage3_Refinement>
If you have a reference result {reference: a strong model's run or a manually verified result} and the check accepted a result that is actually worse than the reference:
1) Compare the two states and describe the actual differences: what's missing, what's extra, where content or structure differs.
2) Keep only the differences that follow from the task text. Discard invented requirements.
3) For each difference, create a pair: NEGATIVE (with the difference) and POSITIVE (the same state without it, everything else unchanged).
4) Propose a targeted fix to the check. Accept it only if it (a) accepts the reference, (b) rejects the weak result, (c) doesn't change a single old verdict, (d) correctly classifies the new pairs.
5) Freeze it as FROZEN_EVALUATOR_v{n+1} and repeat Stage2.
Finish when the weak result matches the reference, there are no new differences, or the check catches an already-known error again (then the problem is in the workflow, not the check).
</Stage3_Refinement>

What to fill in: {task} — your entire task. {format} — a script if the agent can run code, or a checklist for chat. You can lower the numbers for simple tasks. {reference} — a result you're sure is correct.

🚀 Quick start — paste into the chat or Claude Code:

Here's the VeriEvolve template (the check comes before the agent). Adapt it to my task: [your task]. 
Ask me questions to fill in the fields.

[paste the template above]

The LLM will ask what counts as the final state, what must not be touched, which errors are most common, and whether you have a reference result. That way the check looks at the state rather than the agent's words, and the "almost correct" tests reflect your real risks.

06

Limitations

⚠️ Observability is required: the method works when success is visible in the final state (files, tables, database). Where the result can't be read through the interface, you can't build a check: in PostgreSQL, three tasks out of 21 were blocked for exactly this reason.

⚠️ The check is incomplete: the generated check didn't agree with the external one on every state. It let some weak results through and rejected some correct ones. It's no substitute for external checks and manual review of important results.

⚠️ An external anchor is needed: the authors admit that in their setup an external reference checker decided which results counted as falsely accepted and supplied the reference state. Without it you need another signal (e.g., disagreement between two models), but that was only validated retrospectively.

⚠️ Evolution isn't all-powerful: on PostgreSQL, the check helped close only three tasks, and another 12 out of 15 stayed unsolved by both the weak and the strong model. A good check doesn't replace model capability.

⚠️ Expensive and slow: for the weak model (GLM-5.2), a campaign on 30 tasks took about 43 hours and 33M executor tokens. The pipeline itself requires code and isolated environments.

⚠️ Small gain for the strong model: Claude's score rose from 27/30 to 30/30, but that's not statistically significant. The main benefit is for the weak model.

07

How They Tested It

The authors used the MCPMark suite, where every task has a hand-written checker (each one takes hours of expert work). The main experiment covered all 30 file-system tasks. For each task, an agent with no access to the hand-written checker generated 141 test situations, 62 of them "almost correct", and wrote a check. Then the check was compared with the hand-written one: they agreed on all 141. But the honest test is a different one: on 122 distinct states that executors created later and that the check had never seen, agreement was 113 out of 122 (about 93%).

Then the check was frozen and used to "grow" the workflow. The weak model GLM-5.2 went from 6/30 to 18/30 externally verified successes, and Claude from 27 to 30. Interestingly, the check let through three results from the weak model: with text not in uppercase, without a required code snippet, and without nested folders. Comparing them with Claude's results, the authors got test pairs and fixed the check without breaking old verdicts. After that, all three false passes disappeared.

A non-obvious takeaway: the first version of the check doesn't need to be perfect. What matters more is that it's informative enough to get started and can grow from the difference between a strong and a weak result. Another practical takeaway: when an agent repeats an error the check already knows about, the workflow or the executor is to blame, not the check.

The authors also tested the scheme on PostgreSQL, Playwright, Notion, and GitHub. There, the limits were set by what's visible through the interface, how the state is represented, and how much computation the agent needs.

08

Adaptations and Extrapolations

🔧 Technique: a ban on editing the check → protection against gaming it

Add this to the agent's instructions (CLAUDE.md, AGENTS.md):

Do not edit /check/check.py once it's frozen. If it fails, fix the result of your work. If you think the check is wrong, stop and tell me — don't fix it yourself.

Effect: the agent doesn't "fix the yardstick" to fit its result. This transfers the paper's freezing principle; the paper itself has no such wording.

🔧 Technique: two runs with different models → a ready-made reference

When there's no reference, do the task with two models (for example, Claude and a cheaper one) and let step 3 compare the final states. In the paper, executor disagreement as a trigger was only validated retrospectively, so treat it as a working hypothesis.

Extrapolation: a rule for CLAUDE.md

Before any task that changes files or data:
1. Write a list of checks on the final state, including "almost correct" errors (format, case, extra files, side effects).
2. Show it to me.
3. After the work, go through every check and provide evidence (command output), not the words "all done."

This is a simplified version of the principle for everyday work. The paper didn't test this rule.

09

Resources

  • Title: VeriEvolve: Evaluator-First Evolution for Tool-Using Agents.
  • Authors: Yueshen Li, Gokhan Tur, Dilek Hakkani-Tür (University of Illinois Urbana-Champaign), Kamer Ali Yuksel, João Pedro Maia (aiXplain).
  • Foundations: the MCPMark benchmark (Wu et al., 2026), the EvoLattice workflow representation (Yuksel, 2025).
  • Release: code, test situations, frozen checks, and 258 agent-created states are promised after publication.

Research digest

Key result

The agent says "done," and the files have quietly gone missing. That's what happens when it grades its own work. The VeriEvolve method lets you make the agent write a check of the final state (files, database, repository) first, and only then start working. The check is built before the work and frozen: you can't bend the yardstick to fit the result. It includes tests for "almost correct" cases, like a folder named "2024-1" instead of "2024-01." An honest caveat: even this check is incomplete, and in the paper it missed 3 out of 21 wrong results. That's why the method has a built-in third step that extends the check.

Principle

Three steps, like a factory with an inspector at the gate. The inspector gets the blueprint before assembly begins. 1. Tests: from the task text, the model invents final states. Correct, incorrect, and "almost correct." 2. Check: it writes a program. The program looks only at the state after the work and outputs PASS/FAIL for each criterion. It's accepted if the correct ones pass (≥90%) and the "almost correct" ones are rejected (≥80%). Then it's frozen. 3. Work and refinement: the agent works until it gets PASS everywhere. It may change the result and the way it works, but not the check. Then a strong model's result is compared with the weak result the check let through. The difference becomes a new pair of tests. The golden rule: on FAIL, the agent fixes the result, not the yardstick. A new fix to the check must not change a single old verdict.

Why it works

An LLM judge reads the description of the result rather than checking the state. Everything looks tidy, so missing files and an extra trailing newline go unnoticed. Those are exactly the errors the authors found in the weak executor. In one case the formatting was perfect but the text was wrong, and the check missed it. At the same time, the model is good at writing tests and programs from the task text. From "lose nothing, don't modify the originals" it easily derives checkable conditions: "the file count matches," "the hashes of the originals are intact." It's also good at describing the difference between two results in words. The criteria are written before the work, so the agent has no temptation to tailor them to a finished result. The numbers on the payoff: the main gain is for the weak model. Claude's score rose from 27/30 to 30/30, but that's not statistically significant. Don't expect miracles from a strong model on a simple task.

When to apply

Agent work with files, tables, databases, and repositories → tasks where success is visible in the final state, especially when details matter: format, case, folder structure, "don't touch anything else." Great for bulk document sorting, migrations, renames. NOT a fit when the result can't be read through the interface. In PostgreSQL, three tasks out of 21 were blocked for exactly this reason. It doesn't replace manual review of important results. The full automated pipeline requires code and isolated environments: in the paper, 43 hours and 33M tokens for 30 tasks with the weak model. For your own work, take only the principle — one or two rounds is enough.

Mini recipe

1. Describe the task and the constraints: what exists now, what should come out, and what must not be touched. 2. Ask for tests before the work: correct, incorrect, and 3-5 "almost correct" ones. For example, a date in DD-MM-YYYY format instead of YYYY-MM-DD. 3. Have it write the check: a script or checklist that looks only at the final state. It outputs PASS/FAIL for each criterion and names the file. 4. Run the check on the tests: it should let the correct ones through and catch all the rest. If it doesn't, fix the script. 5. Freeze it: state explicitly that the check file must not change during the work. 6. Start the work: on FAIL, fix the result, not the yardstick. 7. Hunt for gaps: have it reread the task and name a requirement the check doesn't cover. Add a "with error" / "without error" test pair and the fix. Old verdicts must stay the same. 8. If you have a reference: provide a strong model's result or one you verified by hand. Ask it to compare that with the weak result and turn the difference into criteria.

Examples

[BAD]: `Sort 400 statements into year/month/bank folders and tell me when you're done` [GOOD]: `Task: sort the statements from /docs/biz_2024 into a year/month/bank structure in /docs/biz_2024_sorted, file name YYYY-MM-DD_bank_amount.pdf. Don't modify the originals, leave no empty folders. STEP 1: don't move anything. Create /check/tests_cases.md with correct, incorrect, and almost-correct situations (folder 2024-1 instead of 2024-01, amount with a comma, original modified) and /check/check.py, which looks only at the final folders and outputs PASS/FAIL per file. Test the script on a temporary copy. STEP 2: treat check.py as immutable. Do the task and run it. On FAIL, fix the result, not the check. STEP 3: name a requirement the script doesn't cover, and add tests and a fix so the old verdicts don't change.` [BAD]: `Check whether everything was done correctly` [GOOD]: `Compare my result with the reference in /docs/ref. Describe the differences: what's missing, what's extra, where the content differs. Keep only the ones that follow from the task text. For each, make two tests: with the difference (bad) and without it (good).`

In plain words

The biggest problem with autonomous AI agents is total self-deception. When a model grades its own work, it looks at the pretty text in its report rather than the actual facts. The result: the database is falling apart, important files have quietly vanished, and the model cheerfully reports success. The VeriEvolve method breaks this nonsense with a fundamental shift: the check on the result is built strictly before the work begins.

It's like letting a student grade their own exam. Technically the handwriting is neat and the answer sounds confident, but inside it's total nonsense. Instead of trusting the student's chatter, you build an automated test rig before the exam starts: the part's weight matches to the milligram — accepted; off by even one hidden space — instant reject.

Here's what VeriEvolve actually does: the model analyzes the spec and generates test cases — correct ones, wrong ones, and the sneakiest of all, "almost correct" ones. Then it writes a separate piece of code that goes and checks the real state of the system: files, database tables, and repository commits. That code is frozen solid, turning into an impartial yardstick the agent uses to polish its plan and execution.

The research was done on tool-use benchmarks, but the principle is universal. You can use this whole setup right now with Cursor or Claude Code. Stop asking your assistant to "write the code and check it yourself" — that's a guaranteed fail. Make it write a strict edge-case check script first, lock the test against changes, and only then give the go-ahead to implement. TDD for AI models genuinely saves hours of debugging.

Bottom line: an LLM judge is blind to details when it grades a task by text alone. Stop trusting the agent's text reports and adopt the evaluator-first approach: first an automated watchdog, then development. Anyone who keeps taking models at their word will keep shipping beautifully packaged garbage to production.

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 VeriEvolve: The Checking Program Comes First, Then the Agent arXiv:2610.29005

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