new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

LangChain · Agents · all subjects

agents/structured-output

76 notes in this subject, read out of this brain and free to use. This is page 2 of 2.

ToolStrategy with Pydantic model example

Example creating agent with ToolStrategy and Pydantic: from pydantic import BaseModel, Field; from typing import Literal; class ProductReview(BaseModel): rating: int | None = Field(description='The rating of the product', ge=1, le=5); sentiment: Literal['positive', 'negative'] = Field(description='The sentiment of the review'); key_points: list[str] = Field(description='The key points of the review. Lowercase, 1-3 words each.'); agent = create_agent(model='gpt-5.5', tools=tools, response_format=ToolStrategy(ProductReview)); result = agent.invoke({'messages': [{'role': 'user', 'content': "Analyze this review: 'Great product: 5 out of 5 stars. Fast shipping, but expensive'"}]}); result['structured_response'] # ProductReview(rating=5, sentiment='positive', key_points=['fast shipping', 'expensive'])

Union types in ToolStrategy example

Example creating agent with ToolStrategy and Union types: from pydantic import BaseModel, Field; from typing import Literal, Union; class ProductReview(BaseModel): rating: int | None = Field(description='The rating of the product', ge=1, le=5); sentiment: Literal['positive', 'negative'] = Field(description='The sentiment of the review'); key_points: list[str] = Field(description='The key points of the review'); class CustomerComplaint(BaseModel): issue_type: Literal['product', 'service', 'shipping', 'billing'] = Field(description='The type of issue'); severity: Literal['low', 'medium', 'high'] = Field(description='The severity of the complaint'); description: str = Field(description='Brief description of the complaint'); agent = create_agent(model='gpt-5.5', tools=tools, response_format=ToolStrategy(Union[ProductReview, CustomerComplaint])); result = agent.invoke({'messages': [{'role': 'user', 'content': "Analyze this review: 'Great product: 5 out of 5 stars. Fast shipping, but expensive'"}]}); result['structured_response'] # ProductReview(rating=5, sentiment='positive', key_points=['fast shipping', 'expensive'])

ToolStrategy with custom tool_message_content example

Example creating agent with ToolStrategy and custom tool_message_content: from pydantic import BaseModel, Field; from typing import Literal; class MeetingAction(BaseModel): task: str = Field(description='The specific task to be completed'); assignee: str = Field(description='Person responsible for the task'); priority: Literal['low', 'medium', 'high'] = Field(description='Priority level'); agent = create_agent(model='gpt-5.5', tools=[], response_format=ToolStrategy(schema=MeetingAction, tool_message_content='Action item captured and added to meeting notes!')); agent.invoke({'messages': [{'role': 'user', 'content': 'From our meeting: Sarah needs to update the project timeline as soon as possible'}]}) # Tool message returns 'Action item captured and added to meeting notes!' instead of default response data message

Custom error message in ToolStrategy example

Example specifying custom error message in ToolStrategy: ToolStrategy(schema=ProductRating, handle_errors='Please provide a valid rating between 1-5 and include a comment.') - When validation fails, the tool message will contain this custom error message instead of the default validation error details.

Handle specific exception type in ToolStrategy example

Example handling specific exception in ToolStrategy: ToolStrategy(schema=ProductRating, handle_errors=ValueError) - Agent will only retry if ValueError is raised; all other exceptions will propagate.

Custom error handler function in ToolStrategy example

Example with custom error handler function: from langchain.agents.structured_output import StructuredOutputValidationError, MultipleStructuredOutputsError; def custom_error_handler(error: Exception) -> str: if isinstance(error, StructuredOutputValidationError): return 'There was an issue with the format. Try again.'; elif isinstance(error, MultipleStructuredOutputsError): return 'Multiple structured outputs were returned. Pick the most relevant one.'; else: return f'Error: {str(error)}'; agent = create_agent(model='gpt-5.5', tools=[], response_format=ToolStrategy(schema=Union[ContactInfo, EventDetails], handle_errors=custom_error_handler))

Tools and structured output simultaneous support requirement

If tools are specified in an agent with structured output, the model must support simultaneous use of tools and structured output.

Zod schema example for createAgent in JavaScript

Example creating agent with Zod schema: import * as z from 'zod'; import { createAgent, providerStrategy } from 'langchain'; const ContactInfo = z.object({name: z.string().describe('The name of the person'), email: z.string().describe('The email address of the person'), phone: z.string().describe('The phone number of the person')}); const agent = createAgent({model: 'gpt-5.5', tools: [], responseFormat: providerStrategy(ContactInfo)}); const result = await agent.invoke({messages: [{'role': 'user', 'content': 'Extract contact info from: John Doe, john@example.com, (555) 123-4567'}]}); console.log(result.structuredResponse); // { name: 'John Doe', email: 'john@example.com', phone: '(555) 123-4567' }

Standard Schema example for createAgent in JavaScript

Example creating agent with Standard Schema: import * as v from 'valibot'; import { toStandardJsonSchema } from '@valibot/to-json-schema'; import { createAgent, providerStrategy } from 'langchain'; const ContactInfo = toStandardJsonSchema(v.object({name: v.pipe(v.string(), v.description('The name of the person')), email: v.pipe(v.string(), v.description('The email address of the person')), phone: v.pipe(v.string(), v.description('The phone number of the person'))})); const agent = createAgent({model: 'gpt-5.5', tools: [], responseFormat: providerStrategy(ContactInfo)}); const result = await agent.invoke({messages: [{'role': 'user', 'content': 'Extract contact info from: John Doe, john@example.com, (555) 123-4567'}]}); console.log(result.structuredResponse); // { name: 'John Doe', email: 'john@example.com', phone: '(555) 123-4567' }

JSON Schema example for createAgent in JavaScript

Example creating agent with JSON Schema: import { createAgent, providerStrategy } from 'langchain'; const contactInfoSchema = {'type': 'object', 'description': 'Contact information for a person.', 'properties': {'name': {'type': 'string', 'description': 'The name of the person'}, 'email': {'type': 'string', 'description': 'The email address of the person'}, 'phone': {'type': 'string', 'description': 'The phone number of the person'}}, 'required': ['name', 'email', 'phone']}; const agent = createAgent({model: 'gpt-5.5', tools: [], responseFormat: providerStrategy(contactInfoSchema)}); const result = await agent.invoke({messages: [{'role': 'user', 'content': 'Extract contact info from: John Doe, john@example.com, (555) 123-4567'}]}); console.log(result.structuredResponse); // { name: 'John Doe', email: 'john@example.com', phone: '(555) 123-4567' }

toolStrategy with Zod schema example in JavaScript

Example creating agent with toolStrategy and Zod schema: import * as z from 'zod'; import { createAgent, toolStrategy } from 'langchain'; const ProductReview = z.object({rating: z.number().min(1).max(5).optional(), sentiment: z.enum(['positive', 'negative']), keyPoints: z.array(z.string()).describe('The key points of the review. Lowercase, 1-3 words each.')}); const agent = createAgent({model: 'gpt-5.5', tools: [], responseFormat: toolStrategy(ProductReview)}); const result = await agent.invoke({'messages': [{'role': 'user', 'content': "Analyze this review: 'Great product: 5 out of 5 stars. Fast shipping, but expensive'"}]}); console.log(result.structuredResponse); // { 'rating': 5, 'sentiment': 'positive', 'keyPoints': ['fast shipping', 'expensive'] }

toolStrategy with Union types example in JavaScript

Example creating agent with toolStrategy and Union types: import * as z from 'zod'; import { createAgent, toolStrategy } from 'langchain'; const ProductReview = z.object({rating: z.number().min(1).max(5).optional(), sentiment: z.enum(['positive', 'negative']), keyPoints: z.array(z.string()).describe('The key points of the review')}); const CustomerComplaint = z.object({issueType: z.enum(['product', 'service', 'shipping', 'billing']), severity: z.enum(['low', 'medium', 'high']), description: z.string().describe('Brief description of the complaint')}); const agent = createAgent({model: 'gpt-5.5', tools: [], responseFormat: toolStrategy([ProductReview, CustomerComplaint])}); const result = await agent.invoke({messages: [{'role': 'user', 'content': "Analyze this review: 'Great product: 5 out of 5 stars. Fast shipping, but expensive'"}]}); console.log(result.structuredResponse); // { 'rating': 5, 'sentiment': 'positive', 'keyPoints': ['fast shipping', 'expensive'] }

Fallback behavior when model doesn't support native structured output

If the provider natively supports structured output for the chosen model, writing response_format=ContactInfo (or responseFormat: contactInfoSchema in JavaScript) is functionally equivalent to using ProviderStrategy or providerStrategy explicitly. If structured output is not supported, the agent will automatically fall back to a tool calling strategy.

toolStrategy with custom toolMessageContent example in JavaScript

Example creating agent with toolStrategy and custom toolMessageContent: import * as z from 'zod'; import { createAgent, toolStrategy } from 'langchain'; const MeetingAction = z.object({task: z.string().describe('The specific task to be completed'), assignee: z.string().describe('Person responsible for the task'), priority: z.enum(['low', 'medium', 'high']).describe('Priority level')}); const agent = createAgent({model: 'gpt-5.5', tools: [], responseFormat: toolStrategy(MeetingAction, {toolMessageContent: 'Action item captured and added to meeting notes!'})}); const result = await agent.invoke({messages: [{'role': 'user', 'content': 'From our meeting: Sarah needs to update the project timeline as soon as possible'}]}); // Tool message contains 'Action item captured and added to meeting notes!' instead of default response data

fakeModel structuredResponse for withStructuredOutput testing

For code that uses .withStructuredOutput(), configure the fake return value with .structuredResponse(). The schema passed to .withStructuredOutput() is ignored; the model always returns the value configured with .structuredResponse(). This keeps tests focused on application logic rather than parsing.

fakeModel structuredResponse example

Example of fakeModel .structuredResponse(): import { fakeModel } from "langchain"; import { HumanMessage } from "@langchain/core/messages"; import { z } from "zod"; const model = fakeModel() .structuredResponse({ temperature: 72, unit: "fahrenheit" }); const structured = model.withStructuredOutput( z.object({ temperature: z.number(), unit: z.string(), }) ); const result = await structured.invoke([new HumanMessage("Weather?")]); console.log(result); // { temperature: 72, unit: "fahrenheit" }

Give your agent this brain