An output is a claim until something checks it
The single highest-value component in a production automation is usually not the prompt, the model or the framework. It is a hundred lines of dull checking code that sits between the agent and the world.
Build the checks in this order, because they get more expensive and less reliable as you go down.
1. Schema
Does it parse? Are the required fields present? Are the types right? Are enums within their sets?
Free, instant, catches a surprising amount. Structured output modes make malformed JSON rare, but “valid JSON with total as the string unknown” is still very much on the menu.
2. Arithmetic and invariants
The checks a competent clerk would do:
- line items sum to the stated total, within one unit of rounding
- the discount is not larger than the subtotal
- the delivery date is not before the order date
- quantities are non-negative integers
- the currency on the invoice matches the currency on the account
Each is two lines. Together they catch most extraction errors, and unlike anything model-based they never have an off day.
3. Trace every value back to a tool result
Here is the rule that catches the most fabrication, and it is cruder than you would expect:
Every identifier, figure and quotation in the output must appear in some tool result from the same run.
Collect the text of every tool result into one string. For each claimed value in the output, check that it is present. Exact substring for ids and quotations; normalised comparison for numbers, since 2499 may appear as ₹2,499.00.
It is blunt. It has false alarms: a legitimately computed sum will not appear anywhere. So exempt derived fields explicitly, by name, and check them with rule 2 instead. What remains catches invented order numbers, invented citations and invented quotations at a rate that will surprise you.
4. Business rules
Refund never exceeds amount paid. No discount above 30% without approval. Never email an address not on the account. These are the rules that exist in somebody’s head; the validator is where they get written down for the first time, which is often the most valuable side effect of building one.
5. A model as judge, last
Useful for “is this reply polite and on-topic”, which no rule expresses. Expensive, slower, and it has its own failure modes, including agreeing with fluent nonsense. Put it last, never let it be the only check, and see the evaluation course for how to check the judge.
What to do when a check fails
Three options, in order:
- Return the validator’s message to the model as an observation and let it try once.
The line items sum to 2,340 but you reported 2,490. Recheck the items.This works well. - Route to a human queue, with the failed check named. This is what queues are for.
- Fail closed, no output at all, for anything money-related.
Never drop a failure silently, and never fall back to a default.
Retry once, then stop
Second retries rarely help, and the mechanism is worth knowing: the failed attempt is now in the context, and models tend to produce variations on the shape they just produced. Two failed validations means something structural: a bad tool result, an ambiguous instruction, or a task the model cannot do. That is a human’s problem, not a third attempt’s.
The honest limit
A validator catches what you thought of. It cannot catch a well-formed, plausible, internally consistent, wrong answer that satisfies every rule you wrote.
That is not a reason to skip it. It is the reason the human queue and the golden set exist, and why the last question in every design review is: what would a wrong answer look like that all of this passes?
Every lesson here is open. Your progress is recorded once you pass the Context Engineering exam.
Check your understanding
An extraction agent reads invoices and outputs supplier name, invoice number, line items and total. Which single check catches the largest share of real errors for the least code?
Pick the one you would defend. Your answer stays private.
Stuck on something?Ask Mai, your AI tutor