Structured output is still untrusted input. Parsing, schema validation, business rules, and authorization are separate gates.
Validated LLM Decision Boundary
Structured model output remains untrusted until deterministic gates accept it.
const Decision = z.object({
action: z.enum(['approve', 'review', 'reject']),
confidence: z.number().min(0).max(1),
evidenceIds: z.array(z.string()).max(10),
})
const decision = Decision.parse(JSON.parse(modelOutput))
if (decision.action === 'approve' && decision.confidence < 0.95) decision.action = 'review'
assertEvidenceExists(decision.evidenceIds)
authorize({ actor, action: decision.action, resource })
await applyDecision(decision) // deterministic, audited, idempotent boundaryInvariant: Invalid or unauthorized model output never reaches a side effect.
Use when: Model output will trigger deterministic application logic.
Why this boundary matters
JSON shape does not prove truth, permission, or business validity. Each deterministic gate rejects a different class of unsafe transition.
Failure policy
| Boundary | Action |
|---|---|
| JSON parse fails | Reject or retry generation within budget |
| Schema validation fails | Do not coerce silently; return structured errors |
| Business invariant fails | Route to review or deterministic rejection |
| Authorization fails | Deny regardless of model confidence |
| Valid and authorized output | Execute through a deterministic application boundary |
Trade-offs
Schema validation removes structural ambiguity, not hallucination or unsafe intent. Strict schemas can increase model retries; permissive coercion can hide errors. Business rules, authorization, and evals remain separate gates.
Decision rule: Treat model output as untrusted input and allow side effects only after parsing, validation, business rules, and authorization all pass.
Further reference
Model output → parse → schema validation → business rules → authorization → deterministic action
Browse all engineering snippets · Read about production AI risk gates