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