Deterministic Checks First
Before any model grades anything, most of what matters is checkable in ordinary code. Was a lookup the first tool called? Was the refund amount inside the $150 ceiling? Did the reply cite a clause that exists, and was that clause in the passages this run actually retrieved? These are questions about a record, they answer in milliseconds, they cost nothing beyond the run that produced the record, and they give the same answer next year.
Teams reach for the judge first because judging is the interesting problem. That ordering is expensive. Of the eighteen regressions Sundry's suite caught in its first quarter, twelve were caught by assertions — two thirds of the value, for a rounding error of the cost, from checks that never drifted and never needed re-validating against a human. Build this tier first and the judge gets to spend its budget on the third that needs judgement.
Assertions on the Trace
The run record from Chapter 6 is what makes this ordinary testing rather than natural-language processing. It holds the messages as sent, every tool call with its arguments and result, the task state, the passages retrieved, and the outcome with its token counts. Assertions read that structure. Nothing here parses prose, so nothing here breaks when somebody improves a sentence.
def check_run(run, case): # every line is a fact about the record, not about the wording assert run.tools_called[0] in ("search_orders", "get_order") assert set(case.forbidden).isdisjoint(run.tools_called) assert len(run.calls("issue_refund")) <= 1 for call in run.calls("issue_refund"): assert call.args["amount_cents"] <= 15000 or run.approval_id assert call.args["order_id"] in run.ids_seen # provenance, Ch8 for clause in cited_clauses(run.reply): assert clause in run.passages_returned
Read what those six assertions cover. The run opened with a lookup rather than acting on the ticket text alone. It never called a tool the case forbids — on the canonical ticket, offer_replacement, because the buyer refused one. It moved money at most once. Any refund was inside the ceiling or carried a recorded approval, and its order id had appeared somewhere in this run rather than being produced from nothing. And every clause the reply names was in the passages the retriever actually returned this run.
They are pure functions of a record, which pays off three times over. The same function runs against a stored eval run in CI, against a sampled production run in a nightly sweep, and against a replayed incident when somebody asks "would we catch this now". One implementation, three places, and no argument about whether the CI version and the production version check the same thing.
Invariants That Must Never Break
A subset of those assertions is different in kind. Invariants measure nothing about quality; they state the properties of a system that is behaving at all, and one violation across 120 runs blocks the deploy. Sundry's list is deliberately short, because a long list of blocking rules is a list somebody will start overriding.
| Invariant | What it stops | Where it came from |
|---|---|---|
| No refund above $150 without a recorded approval | An unreviewable payment out of a seller's balance | The ceiling in Chapter 12 |
| At most one refund per order per run | The double refund, in its second form | Chapter 3, and finance's reconciliation |
| Every policy claim names a clause returned this run | A confident rule the library does not contain | Chapter 8, uncited claims at 18% of replies |
| No other party's data in the reply | Another buyer's address, a card number, a seller balance | The exfiltration surface in Chapter 12 |
| No action the case marks forbidden | A replacement offered to a buyer who refused one | The eval set's own forbidden list |
The first row has caught nothing in production, and that is what a working invariant looks like. It fires in CI on the day somebody edits the system prompt in a way that makes the model generous, which happened once at Sundry and was a four-line diff to a paragraph about tone. Nobody had predicted that connection; the invariant did not need anybody to.
An invariant that can be overridden is a metric with a stern name. If one produces a false failure — and they do, usually because the invariant was written more narrowly than the business rule — fix the check that day rather than waving the build through. The alternative is a team that learns overriding is normal, and by the time the invariant matters it is furniture.
Citation Verification
The citation requirement from Chapter 6 exists so that a machine can check policy answers, and the check is three mechanical questions. Does the cited clause exist in the policy library at the pinned version? Was it among the passages this run retrieved, rather than remembered from training? Does its scope fit this order — a seller supplement for this seller, or a Sundry-wide rule on Sundry's own stock? All three are lookups against records the run already produced.
It is the cheapest high-value check in the suite. Making it blocking took Sundry's uncited policy replies from 18% to 4%, and the residual 4% are mostly replies that mention a rule in passing without deciding anything on it. Run it on every case in the set on every run, not on a sample — it costs nothing, and a sampled check on a rare failure is a check that reports zero for a month and then an incident.
Cheap Text Checks
A small amount of the reply itself is worth checking crudely. Required elements: an amount whenever money moved, a next step whenever the ticket is not closed, an order reference whenever one was discussed. Forbidden phrases: Sundry's list has six entries and every one came from an incident, including a promised delivery date the agent never obtained from the carrier and the word "guarantee" attached to a marketplace seller's behaviour.
Keep these non-blocking and treat them as leads rather than verdicts. They produce most of the suite's false failures, because prose has more legitimate shapes than a rule can enumerate, and a noisy blocking check trains the team to ignore the whole tier. Length bounds belong in the same category: a 900-word reply to "where is my parcel" is worth looking at, and it is not by itself wrong.
Where Deterministic Checks End
Every mechanical check can pass on a run that is wrong. The agent retrieved the seller's supplement, cited it by identifier, stayed under the ceiling, called the right tools in a defensible order — and chose a remedy the clause does not allow, or summarized the clause in a sentence the clause does not support. Chapter 8 measured that last shape at 3% of policy replies and called it the most convincing failure in the book, because the citation is real and the check is green.
That is the judgement class, 44% of Sundry's classified failures, and no assertion reaches it. Deterministic checks are not the small half of an eval suite — they are the cheap two thirds of it. But the third they cannot see contains almost every failure that costs money quietly, which is what the next topic is for.
- Skipping straight to a model judge because it is the interesting problem — the judge costs money on every pass, drifts on every upgrade, and misses things a two-line assertion catches every single time.
- Asserting on an exact tool sequence when the order does not matter — checking the policy before the order record is a legitimate path, the suite fails on correct runs, and within a month somebody deletes the assertion instead of fixing it.
- Checking only the final message — the reply is a summary written by the component under test, and most of the evidence is in the tool calls, the arguments and the passages that never reached the customer.
- Letting an invariant be advisory — a ceiling that can be overridden by whoever is on the release is not a ceiling, and the override becomes routine long before the day it matters.
- Assert on the structured run record rather than on prose, so the checks survive every rewrite of the customer-facing wording.
- Keep a short list of hard invariants, make them block unconditionally, and fix a false failure in the check the same day it appears.
- Verify every citation automatically on every case: the clause exists, it was retrieved this run, and its scope fits this order.
- Add an assertion for every incident that had a checkable signature, and keep the text checks non-blocking so the blocking tier stays trusted.
Knowledge Check
Why build the deterministic tier before the model judge, rather than the other way round?
- A judge takes weeks of engineering, while assertions can be written in an afternoon by one person
- It catches two thirds of real regressions at almost no cost, and never drifts or needs re-validating
- Assertions cover everything a judge covers, so the judge is only needed once the set exceeds 120 cases
- The judge cannot run until the trace format is stable, and assertions are what force that format
The refund-ceiling invariant has never fired in production. What does that tell you?
- It is dead weight and should be dropped, since a check with no findings is costing runtime for nothing
- It is working: the deploy gate is where it fires, on changes nobody expected to touch refunds
- The ceiling is already enforced by the dispatcher, so the invariant duplicates a control that cannot fail
- The threshold is set too low to be reached, and a realistic ceiling would produce occasional findings
Citation verification asks three questions about a cited clause. Which failure does it still let through?
- A clause identifier the model invented, which does not appear anywhere in the policy library
- A real clause the model recalled from training rather than retrieving it during this run
- A real, retrieved, correctly scoped clause attached to a sentence the clause does not support
- A supplement belonging to a different seller than the one who shipped this particular order
Why are the forbidden-phrase and length checks kept non-blocking?
- They produce most of the false failures, and a noisy gate discredits the checks that must block
- They are too slow to run on every case, so they only run against the weekly human sample
- They catch nothing that matters, and are kept only because removing them would need a review
- The judge already covers them, so blocking on both would fail the same run for the same reason twice
You got correct