docs
This guide covers generating type-safe, validated responses using Zod schemas or JSON schemas.
import { createAgent } from "langchain";
import { z } from "zod";
const ContactSchema = z.object({
name: z.string(),
email: z.string().email(),
phone: z.string(),
});
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: ContactSchema,
});
const result = await agent.invoke({
messages: [
{
role: "user",
content: "Extract: John Doe, john@example.com, (555) 123-4567",
},
],
});
console.log(result.structuredResponse);
// { name: "John Doe", email: "john@example.com", phone: "(555) 123-4567" }import { createAgent } from "langchain";
import { z } from "zod";
const OrderSchema = z.object({
orderId: z.string(),
customer: z.object({
name: z.string(),
email: z.string().email(),
address: z.object({
street: z.string(),
city: z.string(),
state: z.string(),
zip: z.string(),
}),
}),
items: z.array(
z.object({
productId: z.string(),
name: z.string(),
quantity: z.number(),
price: z.number(),
})
),
total: z.number(),
status: z.enum(["pending", "confirmed", "shipped", "delivered"]),
});
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: OrderSchema,
});import { createAgent } from "langchain";
import { z } from "zod";
const EmailSchema = z.object({
type: z.literal("email"),
to: z.string().email(),
subject: z.string(),
body: z.string(),
});
const TaskSchema = z.object({
type: z.literal("task"),
title: z.string(),
description: z.string(),
dueDate: z.string().optional(),
});
const ReminderSchema = z.object({
type: z.literal("reminder"),
text: z.string(),
time: z.string(),
});
// Agent can return any of these schemas
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: [EmailSchema, TaskSchema, ReminderSchema],
});
const result = await agent.invoke({
messages: [{ role: "user", content: "Remind me to call John at 3pm" }],
});
// Response matches one of the schemas
if (result.structuredResponse.type === "reminder") {
console.log(result.structuredResponse.text);
console.log(result.structuredResponse.time);
}const ResponseSchema = z.discriminatedUnion("action", [
z.object({
action: z.literal("respond"),
message: z.string(),
}),
z.object({
action: z.literal("transfer"),
department: z.string(),
reason: z.string(),
}),
z.object({
action: z.literal("escalate"),
priority: z.enum(["low", "medium", "high"]),
issue: z.string(),
}),
]);
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: ResponseSchema,
});import { createAgent, toolStrategy } from "langchain";
import { z } from "zod";
const SummarySchema = z.object({
mainPoints: z.array(z.string()),
sentiment: z.enum(["positive", "neutral", "negative"]),
});
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: toolStrategy(SummarySchema, {
name: "generate_summary",
strict: true,
}),
});import { createAgent, providerStrategy } from "langchain";
import { z } from "zod";
const AnalysisSchema = z.object({
topic: z.string(),
keyFindings: z.array(z.string()),
recommendations: z.array(z.string()),
confidence: z.number().min(0).max(1),
});
// Use provider-native JSON schema support (when available)
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: providerStrategy(AnalysisSchema),
});import { createAgent } from "langchain";
const jsonSchema = {
name: "weather_info",
strict: true,
schema: {
type: "object",
properties: {
location: {
type: "string",
description: "City name",
},
temperature: {
type: "number",
description: "Temperature in Celsius",
},
conditions: {
type: "string",
enum: ["sunny", "cloudy", "rainy", "snowy"],
},
},
required: ["location", "temperature", "conditions"],
additionalProperties: false,
},
};
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: jsonSchema,
});const ExtractionSchema = z.object({
entities: z.array(
z.object({
name: z.string(),
type: z.enum(["person", "organization", "location"]),
relevance: z.number().min(0).max(1),
})
),
relationships: z.array(
z.object({
from: z.string(),
to: z.string(),
type: z.string(),
})
),
});
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: ExtractionSchema,
});const ClassificationSchema = z.object({
category: z.enum(["technical", "billing", "general", "complaint"]),
subcategory: z.string(),
priority: z.enum(["low", "medium", "high", "urgent"]),
sentiment: z.enum(["positive", "neutral", "negative"]),
confidence: z.number().min(0).max(1),
});
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: ClassificationSchema,
});const ArticleSchema = z.object({
title: z.string(),
summary: z.string(),
sections: z.array(
z.object({
heading: z.string(),
content: z.string(),
keyPoints: z.array(z.string()),
})
),
tags: z.array(z.string()),
readingTimeMinutes: z.number(),
});
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: ArticleSchema,
});const AnalysisSchema = z.object({
overview: z.string(),
strengths: z.array(z.string()),
weaknesses: z.array(z.string()),
opportunities: z.array(z.string()),
threats: z.array(z.string()),
recommendations: z.array(
z.object({
action: z.string(),
priority: z.enum(["low", "medium", "high"]),
impact: z.string(),
})
),
});
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: AnalysisSchema,
});import { createAgent, tool } from "langchain";
import { z } from "zod";
const searchTool = tool(
async ({ query }) => `Results for: ${query}`,
{
name: "search",
description: "Search for information",
schema: z.object({
query: z.string(),
}),
}
);
const ResearchSchema = z.object({
topic: z.string(),
sources: z.array(z.string()),
summary: z.string(),
citations: z.array(
z.object({
text: z.string(),
source: z.string(),
})
),
});
// Agent uses tools AND returns structured output
const agent = createAgent({
model: "openai:gpt-4o",
tools: [searchTool],
responseFormat: ResearchSchema,
});
const result = await agent.invoke({
messages: [{ role: "user", content: "Research AI history" }],
});
console.log(result.structuredResponse);import { createAgent, StructuredOutputParsingError } from "langchain";
import { z } from "zod";
const Schema = z.object({
value: z.number(),
});
const agent = createAgent({
model: "openai:gpt-4o",
tools: [],
responseFormat: Schema,
});
try {
const result = await agent.invoke({
messages: [{ role: "user", content: "Extract the number" }],
});
console.log(result.structuredResponse);
} catch (error) {
if (error instanceof StructuredOutputParsingError) {
console.error("Parsing failed:", error.message);
console.error("Raw output:", error.rawOutput);
console.error("Cause:", error.cause);
}
}import { MultipleStructuredOutputsError } from "langchain";
try {
const result = await agent.invoke({ messages: [...] });
} catch (error) {
if (error instanceof MultipleStructuredOutputsError) {
console.error("Multiple outputs returned:", error.outputs);
}
}const UserSchema = z.object({
username: z.string()
.min(3, "Username must be at least 3 characters")
.max(20, "Username must be at most 20 characters")
.regex(/^[a-zA-Z0-9_]+$/, "Username can only contain letters, numbers, and underscores"),
email: z.string().email("Invalid email format"),
age: z.number()
.min(13, "Must be at least 13 years old")
.max(120, "Invalid age"),
});const PasswordResetSchema = z.object({
password: z.string().min(8),
confirmPassword: z.string(),
}).refine(
data => data.password === data.confirmPassword,
{
message: "Passwords must match",
path: ["confirmPassword"],
}
);const ConfigSchema = z.object({
theme: z.enum(["light", "dark"]).default("light"),
language: z.string().default("en"),
notifications: z.boolean().default(true),
customSettings: z.record(z.any()).optional(),
});.describe() to help the LLM understand fieldsSee Structured Output API Reference for complete API documentation.