Cogloom · Practical AI & coding

Never trust an LLM's output directly

The validation layer that goes between the model and the code that believes it

The failure shows up in nearly every agent codebase: the code receives a model response, trusts the JSON inside it, and reads result.items[0].id — which throws at 2 a.m. because the model returned {"result": null} on an edge case. The model didn't hallucinate the content. It hallucinated the structure.

Why structured-output mode isn't the whole fix

Constrained JSON modes are genuinely useful — use them. But they don't close the gap, for two reasons:

The pattern: parse, validate, classify

Every model call runs through three stages, and the caller is forced to handle the outcome:

  1. Parse — pull the structure out of the text. Models wrap JSON in prose or code fences; extract it before JSON.parse, and guard the empty-response case first.
  2. Validate — assert the parsed structure against a real schema (Zod, or equivalent), so a shape that merely looks right can't slip through.
  3. Classify — return a discriminated union — { ok: true, data } or { ok: false, reason, raw } — so the calling code physically cannot read .data without first checking .ok. The type system enforces the error handling.

Retry only what's worth retrying

Not every failure is permanent. A malformed-JSON attempt often succeeds on retry; an empty response usually means something else is broken, so don't retry it. The lever that actually moves the number: feed the validation error back into the next prompt — "your last response failed validation: <error>" — rather than blindly re-rolling. Telling the model what was wrong gets a valid output far more often than hoping the dice land better.

The one-line rule

Treat every model response as untrusted input from the network: parse it defensively, validate it against a schema, and make the failure path a value the caller must handle — never an exception you discover in production at 2 a.m.

Cogloom — practical AI & coding, checked before it's repeated. The full validation layer, retry logic, and the rest of the reliability patterns live in the Reliable Agent Field Guide →

Notes