Zod declares the structure and constraints data must satisfy. In AI-powered applications, a schema gives generated responses an expected shape and lets the application catch outputs that do not match it. The same approach validates incoming requests before server-side processing. section 4.3.2 section 9.1.1
Use a schema at the boundary where data enters an application:
- For structured generation, pass a Zod schema to the Vercel AI SDK’s generateObject. It validates the model response and returns a typed object when validation succeeds; failed validation can trigger retries up to a specified limit. section 4.3.3
- For streamed structured data, use streamObject, which attempts to parse and validate responses as they arrive. section 4.3.3
- For a custom AI tool, define its parameters with a Zod schema, then register the tool and render its response. section 4.4.2
- For an API request, parse the body against a schema on the server before processing it. Browser-side limits can improve feedback but cannot replace server validation. section 9.1.1
Listing 4.10 Generating structured responses with Zod
import { z } from 'zod';
import { google } from '@ai-sdk/google';
import { generateObject } from 'ai';
const ProductSchema = z.object({. #1
name: z.string(),
description: z.string(),
price: z.number(),
category: z.string()
});
const ProductListSchema = z.array(ProductSchema); #2
async function generateProductList(prompt) {
'use server';
const {
object: { products },
} = await generateObject({. #3
model: google("models/gemini-2.0-flash"),
schema: z.object({
products: ProductListSchema. #4
}),
prompt: `Generate a list of 5 products
related to: ${prompt}. Provide name, description, price,
and category for each product.`, #5
});
return products;
}
generateProductList('A list of cereal types').then(console.table);
A product-generation example builds an object schema from string and number fields, wraps it in an array schema, and passes it to generateObject. section 4.3.3
A weather tool parameter
A weather assistant declares a city parameter as z.object({ city: z.string().describe('The name of the city') }). Its tool generator uses that city to fetch data and render a weather component. section 4.4.2
Listing 9.1 Validating incoming requests using Zod
import { z } from 'zod'; #1
const promptSchema = z.object({ #2
prompt: z.string().min(1).max(1000),
});
export default async function POST(req, res) {
try {
const validatedData =
promptSchema.parse(req.body); #3
const response =
await process(validatedData.prompt); #4
res.status(200).json({ response });
} catch (error) {
return res.status(400).json({ error: error.errors });
}
}
A Next.js API handler parses req.body with a schema requiring a prompt string of 1–1,000 characters, processes valid input, and returns a 400 response on validation failure. section 9.1.1
Install Zod with npm install zod when using it for structured generation. Keep validation on every server request: client code can be bypassed, and input validation is only one layer of application security. section 4.3.3 section 9.1.1
