← All guides

Knowledge & actions · Explore this field ↗ · Implementation · 4 min read

Structured output validation: a schema is not a decision

Use typed output as a boundary between a model and a service, then apply the business checks that a well-formed object cannot know.

A model to inspect

Output acceptance boundary

  1. 01Parse proposal
  2. 02Check contract
  3. 03Check live rules
  4. 04Confirm or reject

Conceptual flow; live rule checks remain outside the model.

Original conceptual diagram · not a live trace or measured result.
01

Put a boundary around the model

Structured output is valuable because it replaces a prose guess with a declared handoff. Define an operation object with a version, a narrow action name, values, confidence only where it has a real use, and a reference to the user turn that produced it. Parse it once at the service boundary. A downstream worker should receive typed data, not a paragraph that it must reinterpret. JSON Schema describes constraints on a JSON instance; it does not know whether an account is active or a requested appointment still exists.

Start with the smallest contract that makes an action inspectable. An address-change proposal might require customerRef, newAddress, confirmationToken, and intentVersion. It should not carry an unbounded note field just because a model can write one. Give every field an owner: user-supplied, system-derived, or tool-derived. That simple distinction stops a generated value from impersonating an authoritative lookup.

02

Separate three kinds of validity

First check transport and parsing: the object is present, within size limits, and decodes once. Next check schema: required fields, allowed enum values, types, and rejected extra properties. Finally check business validity: the referenced customer is the authenticated customer, the confirmation is current, the serviceable area accepts the address, and a pending shipment has not locked the change. These are different failures and deserve different logs.

Worked example, hypothetical: {action:"refund", amount:0, currency:"USD", orderId:"o-19"} can be structurally valid if zero is allowed by a loose schema. The business validator should reject it with a non-executing result such as amount_must_be_positive, rather than silently converting it or asking a model to repair it. The user-facing reply can ask for the missing choice; the audit record should retain the machine-readable reason.

03

Make rejection a designed outcome

A rejection is not an exception path to hide. Return an outcome object with accepted, reasonCode, field errors where safe, and an allowed next action. Avoid exposing internal authorization rules or raw database errors. For a stale price quote, say it needs a refresh, preserve the user draft, and require a new confirmation. For an unauthorized order reference, do not reveal whether that order exists.

Do not let a model retry unchanged invalid output in a loop. The validator should identify whether the system needs a fresh lookup, a user clarification, a human review, or an outright refusal. Schema validation output can locate a failing instance value, which is useful for an operator; it is not a license to show an implementation trace to a customer.

04

Bind values to their source and time

A typed object can still contain a value copied from old conversation context. Store provenance beside consequential fields: where the value came from, when it was checked, which policy or tool version validated it, and whether the user explicitly confirmed it. If the product permits corrections, invalidate dependent fields rather than retaining a green check forever. A new delivery country can invalidate tax, inventory, and delivery estimates.

This also makes a useful review record. An operator should be able to distinguish “the user entered this account number” from “the model inferred it from a previous message.” The latter may be acceptable for a suggested draft but should not be accepted as an authenticated identity claim.

05

Test rejection as carefully as success

Build cases for malformed JSON, valid-but-unknown identifiers, extra properties, stale confirmation, changed authorization, conflicting currencies, and a tool response that disagrees with the proposal. Include a counterexample where the model chooses a valid enum that is inappropriate for the user’s country. The test asserts that no mutation occurs and that the visible result is truthful.

Success criteria are concrete: every action input has a current contract version; all schema failures produce a bounded code; all business failures avoid mutation; and replaying a rejected request does not turn it into an action. These are service properties, not a claim that the model understands the business.

06

Keep contracts versioned and small

Publish a compatibility policy for each operation. A worker receiving version 2 should know whether it can reject version 1, translate it, or require a new conversation turn. Review enum expansion, optional-field defaults, and deprecated fields as behavior changes, not harmless serialization edits. A permissive parser may ease migration while making it impossible to spot a model using an obsolete action.

The practical limit is that schemas express structure and some local constraints, not ethics, authorization, inventory truth, or user intent. OWASP identifies insecure output handling as an application risk; JSON Schema supplies a vocabulary for structural assertions. The business rules in between remain your product’s responsibility.

Take it into the review

Action validation ledger

OperationSchema ruleBusiness checkSafe rejection
change_addresscountry enum; postal textcustomer owns order; shipment unlockedrefresh required
refundpositive money objectamount available; agent authorizedreview required
book_slotISO time; service codeslot still free; location eligiblechoose another slot
upload_noteknown document referencetenant access; retention allowednot available

A starting artifact to adapt to your service—not a ready-made policy, compliance certificate or test result.

Primary reading

Sources and limits

These links support the architecture, policy, or product behavior discussed above. Vendor documentation describes vendor features; it is not independent proof of performance. Current details should be rechecked before a production decision.

  1. JSON Schema Core, 2020-12
  2. OWASP Top 10 for Large Language Model Applications

What the sources establish

JSON Schema: A Media Type for Describing JSON Documents

JSON Schema defines structural assertions and annotations for JSON instances, including validation output concepts; it does not define an application’s authorization or business policy.

Limits: This source is a schema specification, not guidance on model behavior or domain validation.

Checked 2026-09-19 · JSON Schema / IETF draft publication · source publication date not established.

Open original source ↗
OWASP Top 10 for Large Language Model Applications

OWASP identifies application-layer risks around model inputs and outputs that need application controls.

Limits: The project is risk guidance, not a prescribed output-contract design.

Checked 2026-09-19 · OWASP · source publication date not established.

Open original source ↗

Procedures and worked examples are editorial synthesis. Preparation/review dates are not claimed historical publication dates.

Find your next good decision.

Start typing to explore the guides.

76 sourced guides · Escape to close