A schema-constrained JSON output looks solved the moment a model stops emitting stray commentary and starts producing clean, parseable objects. That feeling is dangerous, because syntactic validity and safety are two different properties, and a guardrail pipeline that stops checking after `json.loads()` succeeds has not validated anything a downstream system actually depends on. An LLM that has been coached into emitting `{"action": "issue_refund", "order_id": "ORD-88213", "amount_usd": 4500.00}` has produced perfectly well-formed JSON whether the order exists, whether $4,500 is a plausible refund for that order, or whether the model hallucinated the order ID entirely from a similar-looking one earlier in the conversation.
Output validation is the guardrail layer that sits between what a model says it wants to do and what your system actually lets happen. Input validation, covered in the previous lesson, protects the model from a hostile prompt; output validation protects your infrastructure from a model that is unreliable, not malicious — one that drops a required field under load, invents an ID that resembles a real one, or emits a negative quantity because nothing in its training ever told it quantities can't be negative in your domain. Both failure modes produce the same downstream damage: a tool call that executes with bad data.
This lesson builds the two layers that output validation actually requires — schema enforcement, which checks shape and type, and semantic validation, which checks whether a shape-correct payload is actually true and safe — plus the retry-and-repair loop that turns a validation failure into a second, bounded attempt instead of either a silent pass-through or an unrecoverable crash. Skip either layer and a guardrail pipeline has a hole exactly where the previous two lessons on classifiers and rules established that defense must be layered, not single-point.