Execution and State Match
Use execution and state matching when correctness is best defined by what an answer does. Instead of comparing the answer text to a reference string, the verifier runs generated code, SQL, tool calls, or a formal proof and scores an observable result.
← Back to Verification PatternsQuick Mental Model
An execution-based verifier follows the same four steps across domains:
- Extract an executable artifact from the rollout, such as a code block, SQL query, or tool calls.
- Execute it with explicit limits in an isolated or task-local environment.
- Observe the output, test results, compiler status, or final state.
- Compare and score that observation against task-specific expectations.
This pattern accepts multiple valid implementations naturally. Two programs can use different algorithms, and two tool traces can take different paths, while still producing the same correct result.
Generated code and tool calls are untrusted input. A timeout or semaphore limits resource use but does not provide security isolation. Use a sandbox or container when the verifier executes code that can access the host.
Choose the Observable
Define correctness at the most semantic layer that you can evaluate deterministically:
Avoid comparing implementation details when the task only requires an outcome. For example, compare SQL result sets instead of SQL strings, and compare final application state instead of requiring the exact reference tool sequence.
Code Execution Against Tests
A code verifier extracts code, combines it with task-specific tests, executes it under a timeout, and maps the test outcome to a reward.
The bigcodebench server runs each candidate in a dedicated virtual environment subprocess. Its core flow is:
The subprocess has a hard outer timeout and decodes arbitrary output without crashing on non-UTF-8 bytes:
For distributed evaluation, put the blocking checker in a Ray task. code_gen, evalplus, and code_fim use Ray remote functions to isolate work and distribute it across workers:
Ray futures are directly awaitable. In async server code, use await future; do not call ray.get(), which blocks the event loop.
Other examples:
competitive_coding_challengeschecks competitive-programming inputs and outputs.nvarcexecutes a generated Python transformation and validates its returned grid.
SQL Execution Against a Database
Text-to-SQL verification should compare query semantics, not query text:
- Extract the predicted SQL.
- Execute the reference query against the task database.
- Execute the predicted query against the same database.
- Normalize and compare the result sets.
bird_sql runs SQLite work in a bounded worker thread so blocking database calls do not block the event loop:
Result normalization is benchmark-specific. Decide whether row order, duplicate rows, floating-point tolerance, column order, and NULL values are significant. Record execution errors separately from valid but incorrect results so infrastructure failures are diagnosable.
spider2_lite is another execution-based SQL example and uses Ray for its evaluator.
State Matching for Tool Use
Exact tool-call matching can reject a correct trajectory merely because the agent took a different valid route. State matching instead asks whether the agent produced the intended world state.
Use two independently initialized environments:
workplace_assistant applies this pattern across calendar, email, analytics, project-management, and CRM state. It executes the predicted and ground-truth actions in separate fresh tool environments, normalizes fields where comparison is case-insensitive, and requires every relevant state table to match:
Keep the live rollout state separate from both verification environments. Replaying actions from a clean baseline prevents the reference run from seeing mutations made by the agent and makes verification reproducible.
Define a canonical state projection rather than comparing every internal field. Ignore timestamps, generated IDs, caches, and other nondeterministic fields unless they are part of the task contract.
Formal Compilation
For formal mathematics, successful compilation is a deterministic correctness signal. The verifier builds a complete proof file from the task statement and generated proof, invokes the compiler in a sandbox, and checks both process status and benchmark-specific forbidden constructs.
math_formal_lean uses this flow:
Compilation success alone may not be sufficient if the language permits placeholders or unsound escape hatches. The Lean verifier also inspects output for incomplete proofs such as sorry. Apply the equivalent policy for the formal system you use.
Compiler diagnostics are useful observations, not only failures. math_formal_lean returns structured error feedback so an agent can revise the proof in a later turn.
Sandbox and Container Execution
Use a sandbox when generated artifacts need compilers, simulators, system tools, or stronger isolation than a subprocess provides.
cvdp verifies generated RTL and testbench files with task-provided harnesses. It translates Docker Compose metadata into an Apptainer sandbox specification, creates a temporary workspace per rollout, runs the harness, and always closes the sandbox:
Treat file paths, environment variables, container mounts, and harness content as untrusted. Resolve every requested path under the rollout workspace, mount only required directories, and avoid exposing host credentials or sockets.
Concurrency, Timeouts, and Cleanup
Execution verifiers can exhaust CPUs, file descriptors, processes, database connections, or sandbox capacity. Bound the expensive region, not just request admission:
Use all of the following where applicable:
- Semaphore: cap concurrent subprocesses, queries, compilers, or sandboxes.
- Timeout: enforce an outer wall-clock limit and terminate timed-out work.
- Output limit: truncate retained stdout and stderr to keep responses and logs bounded.
- Robust decoding: decode subprocess bytes with
errors="replace". - Per-task isolation: create fresh databases, state containers, or workspaces when mutations are possible.
- Guaranteed cleanup: reap subprocesses and close sandboxes in
finally; use temporary-directory context managers for files. - Structured outcomes: distinguish
incorrect,timeout,execution_error, andverifier_error.
A failed execution normally earns the task’s failure reward. A verifier infrastructure failure is different: preserve enough structured detail to diagnose or retry it instead of silently treating every failure as an incorrect model answer.
Checklist
- Define the executable artifact and how it is extracted.
- Choose an observable that captures task semantics.
- Specify normalization and comparison rules.
- Isolate untrusted execution and set resource limits.
- Bound concurrency and enforce timeouts.
- Clean up processes, workspaces, sessions, and sandboxes on every path.
- Return structured diagnostics alongside the reward.
- Test correct, incorrect, malformed, timed-out, and crashing candidates.
Related Topics
- Build Verifiers — resources server interfaces and verification overview
- Verification Patterns — other scoring approaches
- Environment Components — where resources servers fit in a rollout
- Deployment Topology — scaling servers and execution workers