Building with AILesson 54 of 80

Contents

Building with AI

Lesson 54 of 80. Sign in to keep your place.

Module 6 · Evaluating and iterating

Assertions before judges: the checks that cost nothing

8 min read

Where one quarter’s regressions were actually caughtDeterministic assertions61Model judge24Retrieval recall check9Found in production6% of regressions caught, one quarterThe free layer catches most of them, and each failure names its own cause: cited chunk 7, which wasnot retrieved. The judge is not redundant (it exists for the answer that is well-formed, citescorrectly, is the right length and is wrong) but running it first would cost money to learn less.
The free layer catches most of them, and each failure names its own cause: cited chunk 7, which was not retrieved. The judge is not redundant (it exists for the answer that is well-formed, cites correctly, is the right length and is wrong) but running it first would cost money to learn less.

Figure

The cheap layer

Before you ask a model whether an answer is good, ask code whether it is even acceptable. A surprisingly large share of the ways an AI feature breaks are mechanical: the JSON stopped validating, a citation points nowhere, the answer came back in the wrong language, the refusal phrase appeared on a question that should have been answered, the reply is three times longer than last week. None of these needs judgement. All of them can be checked in microseconds, for free, and each failure names its own cause.

The evaluation course builds this layer as part of a full framework. This lesson is the working list for a feature you are shipping.

The catalogue

Shape. Valid JSON. Conforms to the schema. Required fields present. Enumerated fields hold allowed values. Numbers within range. Dates parse.

Content. Must-contain strings from the case file. Must-not-contain strings: competitor names, a placeholder like “[insert name]”, the phrase “as an AI” where the product’s voice forbids it, a raw URL where the product renders links.

Citations. Every cited id exists in the set that was retrieved for this request. The permissions lesson made the point: a model given five chunks will sometimes cite a sixth.

Language. A language detector on the output, compared with the language of the input. Models drift into English when a prompt is in English and the user is not, and nothing else catches it.

Length. A lower bound, because an empty or one-line answer is usually a failure, and an upper bound, because verbosity creeps in with every prompt tweak and nobody notices until the interface overflows.

Refusals. The refusal phrase must appear on the cases tagged should-refuse and must not appear on any other. Both directions; over-refusal is the more common regression.

Code. If the feature writes code, it must parse. If there are tests, they must pass in a sandbox: the running-code lesson from the agents module showed how to run them safely. A syntax error is a failure with a line number.

Personal data. A pattern check for emails, phone numbers and card-like digit runs in the output, when the feature should never emit them.

Cost and latency. Token usage per case against a budget, and wall-clock time against a limit. A prompt change that doubles output length passes every quality check and doubles the bill.

Writing them

Any test runner does this. In Python:

Python
import json, pytest
from feature import answer

cases = [json.loads(l) for l in open("cases.jsonl")]

@pytest.mark.parametrize("case", cases, ids=lambda c: c["id"])
def test_case(case):
    out = answer(**case["input"])
    for s in case["expect"].get("must_contain", []):
        assert s in out.text, f"missing {s!r}"
    for s in case["expect"].get("must_not_contain", []):
        assert s not in out.text, f"found {s!r}"
    for cid in case["expect"].get("cites", []):
        assert cid in out.cited_ids
    assert set(out.cited_ids) <= set(out.retrieved_ids), "cited an unretrieved chunk"
    assert out.usage.output_tokens < 600

promptfoo is a free tool that does the same from a YAML file with built-in assertion types, and it is a good choice when several people who are not all engineers maintain the cases.

Why this layer comes first

Three reasons, in order of importance. It is free: no model call, no cost per run, so it runs on every commit. It is precise: a failure says “cited chunk 7, which was not retrieved”, not “score 6/10”. And it is stable: the same output always gets the same verdict, which the next two lessons will show a model judge cannot promise.

In practice, on a mature feature, a majority of regressions caught in CI are caught here. The judge layer above it exists for the failures this layer cannot see: an answer that is well-formed, cites correctly, is the right length and is wrong.

What assertions cannot do

They cannot tell you an answer is good. A response can pass every check above and be confidently incorrect, subtly off-topic, or technically accurate and useless. Assertions rule out the mechanically broken; they do not rule in the correct. That is the judge’s job, and the reason the next lesson exists. The mistake to avoid is the one that follows from a green assertion suite: treating “nothing mechanical failed” as “it works”.

The habit that keeps the list growing

Every production failure that could have been caught by a string check becomes a string check. A user reports that the assistant answered in English; a language assertion is added. A citation was fabricated; the citation check is tightened. The list in this lesson is a starting point, and the version a team has after a year is longer, specific to the product, and the cheapest quality instrument they own.

Every lesson here is open. Your progress is recorded once you pass the Python, from Zero, for AI exam.

Check your understanding

A team’s CI runs only a model judge, at some cost per run, and it occasionally passes an answer that cites a chunk which was never retrieved. What is the most direct fix?

Pick the one you would defend. Your answer stays private.

Next lesson · 9 minA model judge you have checked against people

Stuck on something?Ask Sayali, your AI tutor

How to cite: Addaly (2026) ‘Assertions before judges: the checks that cost nothing’, in Building with AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/building-with-ai/assertions-before-judges (Accessed: 13 October 2026).