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?
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:- Target - the block to run, currently
{ "type": "block", "block_id": "..." }. - Source - the handle inputs to replay.
- 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:workflow_id. scope is optional:
When an eval run starts, Retab:
- Loads the current workflow draft and current block configuration.
- Rebuilds the saved handle inputs into normal runtime inputs.
- Executes only the selected block.
- Stores the block artifact, handle outputs, routing decisions, warnings, and timing.
- Resolves the assertion target from the handle outputs.
- Records the assertion outcome and the result verdict.
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 parentWorkflowEvalRun has a lifecycle:
Parent
counts separates lifecycle from assertion outcomes:
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.
Recommended Workflow
- Run the workflow on representative documents.
- Open the Evals page and create an eval from a completed run, or create one with explicit manual inputs.
- Pick the block output field or handle you want to protect.
- Define one assertion for the expected behavior.
- Run the eval after changing schemas, prompts, code, categories, or split definitions.
- Use stale evals as a review queue before publishing workflow changes.