Assertions
An assertion grades a model output. Every assertion the user can write
in YAML is a variant of the AssertionSpec enum in the frozen
kanros-core trait layer — run kanros schema for the full
machine-readable catalogue. The runner turns each spec into a concrete
Assertion and records the outcome (Pass, Fail, Error, Skipped)
per cell.
YAML always uses type: as the discriminator and kebab-case for the
variant name:
assert:
- type: contains
value: "key findings"
Outcome states
| State | Meaning |
|---|---|
pass | The assertion ran cleanly and the output is correct. |
fail | The assertion ran cleanly and decided the output is wrong. |
error | The assertion could not run (plugin crashed, network failure during grading, …). Distinct from fail so CI can surface infra issues separately. |
skipped | Intentionally not run (filter, missing capability, …). |
A run exit code is 0 only when every cell's every assertion is pass
or skipped.
Catalogue
The full list of AssertionSpec variants below is grouped by family.
Every name is the exact YAML type: value.
Deterministic
equals— exact string equality. Takesvalue: String.not-equals— inverse.contains— case-sensitive substring match.icontains— case-insensitive substring match.not-contains— substring must not appear.starts-with— required prefix.ends-with— required suffix.regex— Rustregexsyntax. Takespattern: String.not-regex— inverse.contains-all— every needle invalues: [String]must appear.contains-any— at least one needle must appear.contains-none— none of the needles may appear.contains-json— output must contain a JSON object/array somewhere.is-json— output is itself valid JSON.json-schema— output is valid JSON matching the supplied draft 2020-12schema:value.is-sql— output parses as SQL in one of the supported dialects.is-xml— output is well-formed XML.length— character length in[min, max](either bound optional).word-count— word count in[min, max].
Performance
cost— USD cost must not exceedmax_usd: f64.latency— wall-clock latency must not exceedmax_ms: u64.perplexity— output perplexity must not exceedmax: f64.
Custom code
javascript— runscode: Stringvia the embeddedboa_engine. The source must definefunction evaluate(ctx)returning truthy/falsy.python— runs a Pythonscript:via subprocess.webhook— POSTs the context tourl: String; the response decides pass/fail.wasm— calls a WASM (Component Model) plugin. Takesplugin: PluginRefand an optionalconfig:JSON value.
Similarity
similarity— cosine similarity of output and reference embeddings. Requiresreference: String,threshold: f32, andembedder: ProviderRef.levenshtein— edit distance against areference: String, bounded bymax_distance: u64.
Model-graded
llm-rubric— LLM-as-judge with a free-text rubric. Takesvalue: String(the rubric) andprovider: ProviderRef(the grader model).factuality— factuality check against areference:answer.model-graded-closedqa— closed-QA model-graded check.answer-relevance— answer-relevance check.
RAG metrics
See RAG metrics for the full semantics.
context-recall— recall over areference:answer withthreshold: f32and graderprovider:.context-precision— precision over the retrieved context.context-relevance— relevance of the retrieved context to the question.faithfulness— every claim in the answer is supported by the suppliedcontext:.
NLP metrics
bleu— BLEU score against areference:, bounded bythreshold:.rouge-n— ROUGE-N score; takesn: u8(typically 1 or 2).meteor— METEOR score against areference:.
Safety
moderation— runs a moderation API; pass if no categories are flagged. Optionalcategories:whitelist restricts which flags matter.classifier— runs a HuggingFace classifier; pass iflabel:is belowthreshold:.
Composite
assert-set— combine N childassertions:withop: and | or | weightedand optionalthreshold:.select-best— rank N model outputs byrubric:and pass only the best.
Plugin
custom— call a user-provided WASM assertion plugin via aplugin: PluginRef.
Worked examples
A composite: pass only if every child passes.
assert:
- type: assert-set
op: and
assertions:
- type: contains
value: "summary"
- type: latency
max_ms: 1000
- type: word-count
min: 50
max: 250
A weighted composite with a score threshold:
assert:
- type: assert-set
op: weighted
threshold: 0.7
assertions:
- type: similarity
reference: "Apollo 11 landed in 1969."
threshold: 0.6
embedder: { id: openai:text-embedding-3-small }
- type: contains
value: "1969"
A model-graded rubric (one grader call per cell):
assert:
- type: llm-rubric
value: |
The summary must mention the launch date, the mission lead, and
the planned next step. Style must be neutral.
provider:
id: openai:gpt-4o
A JSON-schema check:
assert:
- type: json-schema
schema:
type: object
required: [summary, key_findings]
properties:
summary: { type: string, minLength: 10 }
key_findings:
type: array
items: { type: string }
minItems: 1
Notes
- Custom code assertions (
javascript,python,webhook,wasm) run inside the runner process by default; for stronger isolation prefer thewasmassertion which uses the capability-sandboxed WASM plugin host described in WASM plugins. - Each assertion records both its outcome and (where applicable) a
numeric
scorein[0.0, 1.0]. Composite assertions read these scores to compute their own verdict.