KUJO THE COURSE

THE KUJO COURSE · VERIFIED 1.3.1

Evaluation independent of generation

Reject plausible but wrong output with observable criteria.

STAGE 6 / Agentic systems · LESSON 37

Why this exists

A generator optimizes for producing an answer. An evaluator decides whether that answer satisfies an external criterion. If both merely repeat the same unsupported claim, the system has no independent evidence.

Deterministic checks first

Start with input validation, schema checks, arithmetic invariants, fixture expectations, and bounded tool results. Use a model-based evaluator only when a criterion requires judgment, and record its uncertainty and disagreement policy. Do not replace an exact comparison with a model opinion.

The example compares a proposed count with the length of trusted local input. Both a well-shaped correct result and a well-shaped wrong result are tested. This demonstrates why structured output validation is necessary but insufficient.

Thresholds and failure

An acceptance threshold must mean something measurable. “Confidence above 0.9” is meaningless if a model simply invented the confidence number. Prefer criteria with provenance: all required records processed, zero unauthorized tools, expected output schema, and a successful independent test.

A failed evaluation may justify revision only if the action can be repeated safely and the budget remains. Otherwise stop. Keep the previous evidence rather than overwriting it with a later success that hides the failure history.

Ecosystem boundary

The Kujo Eval project provides suite/report workflows, but evaluation remains an architectural responsibility even in a plain script. Inspect its current fixture and report contracts if you adopt it. The course's pure evaluator remains usable without an ecosystem dependency.

Professional pattern

Create negative fixtures before trusting an evaluator. Include malformed data, plausible wrong answers, missing evidence, and extra unauthorized actions. Verify that the gate rejects these fixtures before relying on it.

Common mistakes

Do not let the actor choose expected output after seeing its own answer. Do not treat “generated successfully” as acceptance. Do not hide a failed criterion inside an average score when it should be a hard stop.

Working example

func evaluate(proposed, records) { return proposed["count"] == len(records) }
let records := ["a", "b"]
assert_equal(evaluate({"count": 2}, records), true)
assert_equal(evaluate({"count": 3}, records), false)
print("correct accepted; plausible wrong rejected")

Run it

From the course repository root, use the pinned Kujo 1.3.1 runtime.

kujo check examples/37.kujo
kujo run --untrusted  examples/37.kujo

Captured output

correct accepted; plausible wrong rejected

Break it and diagnose it

The proposal has the right shape but the wrong factual count. Independent evaluation rejects it.

let proposal := {"count": 3}
assert_equal(proposal["count"], len(["a", "b"]))

kujo run --untrusted  examples/37-break.kujo

Exit status: 4. Captured diagnostic:

[KUJOVM001] [vm] Runtime Error: Assertion failed: expected Int(2), got Int(3)
  --> 0:0


Exercise

Build an evaluator with three hard criteria and five adversarial fixtures. Include a result that is valid JSON and schema-valid but incorrect. Specify which failures permit revision and which force STOP.

Checkpoint

  • I evaluate against trusted evidence.
  • I test plausible wrong answers.
  • I keep hard failures out of averaged scores.

Verified 2026-09-06 · Official Kujo 1.3.1 release · Source contract · Download example