Cogloom · Practical AI & coding
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.
Constrained JSON modes are genuinely useful — use them. But they don't close the gap, for two reasons:
confidence field of 847 where the code expects a 0–1 float. The schema enforces types, not meaning.Every model call runs through three stages, and the caller is forced to handle the outcome:
JSON.parse, and guard the empty-response case first.{ 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.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.
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 →
AgentOutput<T> discriminated union are shown in full — TypeScript + Zod — in the companion dev.to post.