◀ Knowledge hub

03, AI & intelligence

Getting reliable structured output from a model

codeAmani Labs Engineering
Cinematic still for Getting reliable structured output from a model

If you parse a model's prose, you will eventually parse it wrong

Asking a model for JSON in the prompt and then running the reply through a parser works until the day the model adds a friendly sentence before the JSON, or wraps it in a code fence, or returns a number where you expected a string. The robust approach is to constrain the output to a schema at the call, so the model returns data, not prose you hope is data.

Generate against a schema

Define the shape you want with a schema and let the SDK enforce it. The result comes back already typed and already validated, so the code that consumes it never has to guess.

import { generateObject } from "ai";
import { z } from "zod";

const { object } = await generateObject({
  model: "openai/gpt",
  schema: z.object({
    intent: z.enum(["bug", "feature", "question"]),
    priority: z.number().int().min(1).max(5),
    summary: z.string().max(200),
  }),
  prompt: ticketText,
});

// object.intent is a known enum, object.priority is a number, guaranteed

If the model produces something off shape, the SDK retries against the schema rather than handing you broken data. The validation lives at the boundary, which is the only place it can actually protect the rest of the system.

Keep the schema tight

A loose schema invites loose output. Prefer enums over free strings, set bounds on numbers, and cap string lengths. Every constraint you express is a constraint the model must satisfy and a class of malformed result you will never see. A field typed as one of four values cannot come back as a paragraph.

Validate again if it crosses a trust boundary

Schema constrained generation guarantees the shape, not the meaning. If the values drive a payment, a permission change, or anything irreversible, treat them as untrusted input and check them against your business rules before acting. The model gave you well formed data; whether that data is sensible is still your decision.

The payoff

Structured output is what turns a language model from a text toy into a dependable component you can wire into a pipeline. Once the output is typed and validated, the model is just another function that returns a known shape, and the rest of your code can rely on it.

Qualified conversation

Have a build to de-risk? Let's talk.

Tell us what you are building. We respond within two business days.