Loading lesson…
Force an LLM to return JSON that matches a schema. Zod + tool-use or JSON mode makes this reliable.
Asking an LLM for JSON and parsing the string is a trap. Use the AI SDK's generateObject with a Zod schema — you get validated, typed data every time.
import { generateObject } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { z } from "zod";
const ExtractSchema = z.object({
people: z.array(
z.object({
name: z.string(),
role: z.string().optional(),
email: z.string().email().optional(),
})
),
summary: z.string().max(240),
});
export async function extract(text: string) {
const { object } = await generateObject({
model: anthropic("claude-opus-4-7"),
schema: ExtractSchema,
prompt: `Extract people mentioned and a short summary from:\n\n${text}`,
});
// object is fully typed from the schema
console.log(`${object.people.length} people found`);
return object;
}generateObject validates the response against the schema and retries on failure. You get a typed object, not a string.import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
const client = new OpenAI();
const r = await client.responses.parse({
model: "gpt-5",
input: [{ role: "user", content: "Extract a person from: Ada Lovelace, mathematician" }],
text: { format: zodResponseFormat(z.object({ name: z.string(), role: z.string() }), "person") },
});
console.log(r.output_parsed); // { name: "Ada Lovelace", role: "mathematician" }OpenAI's helpers.zod converts Zod to the JSON schema the API wants. parse() returns typed data.Understanding "Structured Output With Zod" in practice: AI-assisted coding shifts work from syntax recall to design thinking — models handle boilerplate so you focus on architecture. Force an LLM to return JSON that matches a schema. Zod + tool-use or JSON mode makes this reliable — and knowing how to apply this gives you a concrete advantage.
The big idea: never parse JSON by hand from an LLM. Zod + generateObject turns the model into a typed function.
15 questions · take it digitally for instant feedback at tendril.neural-forge.io/learn/quiz/end-progx-structured-output-zod-creators
What is the primary advantage of using generateObject with a Zod schema instead of manually parsing JSON from an LLM response?
How does adding .describe() to a Zod schema field help when working with LLMs?
Why should you add .max() to array fields in a Zod schema used with an LLM?
What does the lesson identify as the fundamental problem with manually parsing JSON from LLM output?
In the context of this lesson, what is Zod primarily used for?
The lesson describes a Zod schema as serving two purposes simultaneously. What are they?
What specific problem does generateObject solve that raw LLM API calls don't?
What does the lesson mean when it says Zod + generateObject 'turns the model into a typed function'?
If you don't limit array sizes in your Zod schema, what practical risk do you face?
Why is using .describe() on an email field specifically recommended in the lesson?
What is the key difference between manual JSON parsing and using generateObject with validation?
What happens when generateObject receives output that doesn't match your Zod schema?
What is the main benefit of having the schema serve as both documentation and prompt?
Why does the lesson call parsing JSON from prose a 'trap'?
Which AI SDK method does the lesson specifically recommend for structured output?