Skip to main content

verify: the verdict belongs to the Runtime

The verify expression takes verification back from the model: checks gather evidence, pass when is evaluated by the Runtime, and the conclusion cannot be forged by an agent.

Basic form

let result = verify {
check highlights = agent(assistant) {
task "Extract the week's key achievements"
expect HighlightList
}
check risks = agent(assistant) {
task "Aggregate every blocker into the risk list"
expect RiskList
}
pass when highlights.items.any and risks.items.any
}

require result.passed else fail "report must surface highlights and risks"

The result type is the builtin Verification<{highlights, risks}>:

{ passed: bool, failed: bool, checks: { highlights: HighlightList, risks: RiskList } }

Exactly three members: .passed / .failed (bool) and .checks (the object of all check results).

Two scope rules

  1. A check's initializer evaluates in the outer scope — it cannot see check names, but it can read stage dependencies, let bindings, input
  2. pass when evaluates in the verify scope — all check names visible

Check names are unique within the verify (duplicate-check).

A check can be any expression

Checks need not be agent calls — deterministic expressions work as checks too:

let audit = verify {
check one_per_day = unique(posts[*].day) // purely deterministic
check brand_voice = agent(strategist) { /*...*/ expect VoiceCheck }
pass when one_per_day and brand_voice.ok
}

Mixing both kinds is a common pattern: deterministic assertions (uniqueness, counts, disjointness) computed by the language; qualitative checks delegated to agents — but the final conjunction always lives in pass when.

Parallel check groups

A verify may contain one parallel group whose checks run concurrently; top-level items run in order. The checks object is the flat merge of all groups:

let gate = verify {
parallel {
check coverage = agent(moderator) { task "..." expect CoverageCheck timeout 2m }
check edge = agent(moderator) { task "..." expect EdgeCheck timeout 3m }
}
pass when coverage.ok and edge.ok
}

Why expect-ing Verification is forbidden

expect types must be Schemas an agent can produce; Verification is explicitly excluded (expect-invalid-type). This closes a cheating lane: having an agent return "verification passed". In Agent Flow an agent can at most return evidence (e.g. TestReport{passed: bool}), while the workflow-level "passed" conclusion (verification.passed) can only be computed from pass when.

Note the distinction: an agent's TestReport.passed is an evidence field (the model claims tests ran); the verify result's .passed is the runtime verdict (computed by pass when). Feeding the former into the latter is exactly the intended use:

let result = verify {
check tests = agent(tester) { task "Run the test suite" expect TestReport }
pass when tests.passed // Runtime applies the evidence field
}

Typical patterns

The gate

require quality.passed else fail "screening gate failed"

verify itself never throws; require turns it into a hard gate that raises WorkflowAssertionError and emits a require.failed event.

The fork (no gate, only influence)

if gate.passed {
emit progress { doc: input.doc_path, gate: "passed" }
} else {
emit progress { doc: input.doc_path, gate: "blocked" }
}
let verdict = agent(styler) {
input { evidence: evidence, passed: gate.passed } // verdict feeds onward
expect text
}

Verification values cross boundaries

gate.passed and gate.checks.blockers.items are ordinary values: they can flow into agent input, emit progress payloads and return objects — the runtime-rendered conclusion moves freely; only its origin is fixed.

Next steps