Skip to main content

What are Workflow Evals?

Workflow evals are saved, block-level regression checks. Each eval freezes the inputs for one workflow block, replays that block against the current workflow draft, and evaluates one assertion against the block output. Use evals when you want to answer questions like:
  • Does this Extract block still return the expected invoice total?
  • Does this Function block still compute the validation flag correctly?
  • Does this Split block still assign pages to the right subdocuments?
  • Does this Classifier block still route a file to the expected category?
Evals are intentionally block-scoped. Running an eval executes the selected block with saved inputs instead of replaying the entire workflow, which keeps the feedback loop short while you adjust schemas, prompts, function code, categories, or split definitions.

Supported Blocks

Workflow evals are currently supported for: Other block types, such as input blocks, notes, API calls, conditionals, review gates, and loops, do not currently produce workflow eval runs directly.

Eval Shape

A workflow eval stores:
  1. Target - the block to run, currently { "type": "block", "block_id": "..." }.
  2. Source - the handle inputs to replay.
  3. Assertion - one expected condition for one declared output handle.
source.type can be: For blocks executed inside a loop, provide step_id so Retab knows which iteration’s inputs to capture. File inputs are materialized as durable Retab file references so the eval does not depend on the original browser upload session.

Assertions

An assertion targets a declared output handle and, optionally, a dotted path inside that handle’s JSON payload. The current condition kinds are:

Condition payloads

Each condition is a { "kind": ..., ... } object. The fields alongside kind depend on the kind — most value checks use expected, but the comparison, pattern, metric, and nested kinds use their own fields: Examples:
In the CLI, the inline --path/--equals flags build an equals assertion only. To use any other condition kind, pass the full assertion JSON with --assertion-file (or --assertion-file - to read from stdin).

Running Evals

You can run one eval, every eval for one block, or every eval in a workflow. In the API, create a parent eval run with:
The request body always includes workflow_id. scope is optional: When an eval run starts, Retab:
  1. Loads the current workflow draft and current block configuration.
  2. Rebuilds the saved handle inputs into normal runtime inputs.
  3. Executes only the selected block.
  4. Stores the block artifact, handle outputs, routing decisions, warnings, and timing.
  5. Resolves the assertion target from the handle outputs.
  6. Records the assertion outcome and the result verdict.
Eval runs are asynchronous. Poll GET /v1/workflows/evals/runs/{run_id} until the parent run reaches a terminal lifecycle, then read child rows from GET /v1/workflows/evals/results?run_id={run_id}.

Results

A parent WorkflowEvalRun has a lifecycle: Parent counts separates lifecycle from assertion outcomes:
Each WorkflowEvalResult row has its own lifecycle and, once completed, a verdict of passed, failed, or blocked. The nested assertion_result.outcome uses the same three outcome values and includes actual_value, expected_value, optional score/threshold fields, and failure details when the assertion cannot pass. Result rows also include the saved handle_inputs, produced handle_outputs, workflow/block fingerprints, the execution artifact, routing decisions, warnings, and timing.

Freshness and Drift

Workflow evals are tied to the block inputs and output schema that existed when the eval was created or last updated. When the workflow draft changes, Retab reports several freshness signals: The eval also stores latest_run_summary, latest_passing_run_summary, and latest_failing_run_summary. Each summary separates run lifecycle (status) from assertion outcome (outcome). Staleness does not automatically mean the workflow is broken. It means the eval should be rerun or recaptured before you rely on its latest result.
  1. Run the workflow on representative documents.
  2. Open the Evals page and create an eval from a completed run, or create one with explicit manual inputs.
  3. Pick the block output field or handle you want to protect.
  4. Define one assertion for the expected behavior.
  5. Run the eval after changing schemas, prompts, code, categories, or split definitions.
  6. Use stale evals as a review queue before publishing workflow changes.
Evals work best when each one protects one behavior. Prefer multiple focused evals over one broad assertion so failures point directly to the changed output.

API Reference