Structured output allows agents to return data in a specific, predictable format. Instead of parsing natural language responses, you get structured data in the form of JSON objects, Pydantic models, or dataclasses that your application can directly use.LangChain’s prebuilt ReAct agent create_agent() handles structured output automatically. The user sets their desired structured output schema, and when the model generates the structured data, it’s captured, validated, and returned in the 'structured_response' key of the agent’s state.
Some model providers support structured output natively through their APIs (currently only OpenAI and Grok). This is the most reliable method when available.To use this strategy, configure a ProviderStrategy:
Copy
Ask AI
class ProviderStrategy(Generic[SchemaT]): schema: type[SchemaT]
The schema defining the structured output format. Supports:
Pydantic models: BaseModel subclasses with field validation
Dataclasses: Python dataclasses with type annotations
TypedDict: Typed dictionary classes
JSON Schema: Dictionary with JSON schema specification
LangChain automatically uses ProviderStrategy when you pass a schema type directly to create_agent.response_format and the model supports native structured output:
Copy
Ask AI
from pydantic import BaseModelfrom langchain.agents import create_agentclass ContactInfo(BaseModel): """Contact information for a person.""" name: str = Field(description="The name of the person") email: str = Field(description="The email address of the person") phone: str = Field(description="The phone number of the person")agent = create_agent( model="openai:gpt-5", tools=tools, response_format=ContactInfo # Auto-selects ProviderStrategy)result = agent.invoke({ "messages": [{"role": "user", "content": "Extract contact info from: John Doe, john@example.com, (555) 123-4567"}]})result["structured_response"]# ContactInfo(name='John Doe', email='john@example.com', phone='(555) 123-4567')
Provider-native structured output provides high reliability and strict validation because the model provider enforces the schema. Use it when available.
If the provider natively supports structured output for your model choice, it is functionally equivalent to write response_format=ProductReview instead of response_format=ToolStrategy(ProductReview). In either case, if structured output is not supported, the agent will fall back to a tool calling strategy.
For models that don’t support native structured output, LangChain uses tool calling to achieve the same result. This works with all models that support tool calling, which is most modern models.To use this strategy, configure a ToolStrategy:
Custom content for the tool message returned when structured output is generated.
If not provided, defaults to a message showing the structured response data.
The tool_message_content parameter allows you to customize the message that appears in the conversation history when structured output is generated:
Copy
Ask AI
from pydantic import BaseModel, Fieldfrom typing import Literalfrom langchain.agents import create_agentfrom langchain.agents.structured_output import ToolStrategyclass MeetingAction(BaseModel): """Action items extracted from a meeting transcript.""" 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="openai:gpt-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"}]})
Copy
Ask AI
================================ Human Message =================================From our meeting: Sarah needs to update the project timeline as soon as possible================================== Ai Message ==================================Tool Calls: MeetingAction (call_1) Call ID: call_1 Args: task: Update the project timeline assignee: Sarah priority: high================================= Tool Message =================================Name: MeetingActionAction item captured and added to meeting notes!
Without tool_message_content, our final ToolMessage would be:
Models can make mistakes when generating structured output via tool calling. LangChain provides intelligent retry mechanisms to handle these errors automatically.
When a model incorrectly calls multiple structured output tools, the agent provides error feedback in a ToolMessage and prompts the model to retry:
Copy
Ask AI
from pydantic import BaseModel, Fieldfrom typing import Unionfrom langchain.agents import create_agentfrom langchain.agents.structured_output import ToolStrategyclass ContactInfo(BaseModel): name: str = Field(description="Person's name") email: str = Field(description="Email address")class EventDetails(BaseModel): event_name: str = Field(description="Name of the event") date: str = Field(description="Event date")agent = create_agent( model="openai:gpt-5", tools=[], response_format=ToolStrategy(Union[ContactInfo, EventDetails]) # Default: handle_errors=True)agent.invoke({ "messages": [{"role": "user", "content": "Extract info: John Doe (john@email.com) is organizing Tech Conference on March 15th"}]})
Copy
Ask AI
================================ Human Message =================================Extract info: John Doe (john@email.com) is organizing Tech Conference on March 15thNone================================== Ai Message ==================================Tool Calls: ContactInfo (call_1) Call ID: call_1 Args: name: John Doe email: john@email.com EventDetails (call_2) Call ID: call_2 Args: event_name: Tech Conference date: March 15th================================= Tool Message =================================Name: ContactInfoError: Model incorrectly returned multiple structured responses (ContactInfo, EventDetails) when only one is expected. Please fix your mistakes.================================= Tool Message =================================Name: EventDetailsError: Model incorrectly returned multiple structured responses (ContactInfo, EventDetails) when only one is expected. Please fix your mistakes.================================== Ai Message ==================================Tool Calls: ContactInfo (call_3) Call ID: call_3 Args: name: John Doe email: john@email.com================================= Tool Message =================================Name: ContactInfoReturning structured response: {'name': 'John Doe', 'email': 'john@email.com'}
You can customize how errors are handled using the handle_errors parameter:Custom error message:
Copy
Ask AI
ToolStrategy( schema=ProductRating, handle_errors="Please provide a valid rating between 1-5 and include a comment.")
If handle_errors is a string, the agent will always prompt the model to re-try with a fixed tool message:
Copy
Ask AI
================================= Tool Message =================================Name: ProductRatingPlease provide a valid rating between 1-5 and include a comment.
Handle specific exceptions only:
Copy
Ask AI
ToolStrategy( schema=ProductRating, handle_errors=ValueError # Only retry on ValueError, raise others)
If handle_errors is an exception type, the agent will only retry (using the default error message) if the exception raised is the specified type. In all other cases, the exception will be raised.Handle multiple exception types:
Copy
Ask AI
ToolStrategy( schema=ProductRating, handle_errors=(ValueError, TypeError) # Retry on ValueError and TypeError)
If handle_errors is a tuple of exceptions, the agent will only retry (using the default error message) if the exception raised is one of the specified types. In all other cases, the exception will be raised.Custom error handler function:
Copy
Ask AI
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)}"ToolStrategy( schema=ToolStrategy(Union[ContactInfo, EventDetails]), handle_errors=custom_error_handler)
On StructuredOutputValidationError:
Copy
Ask AI
================================= Tool Message =================================Name: ToolStrategyThere was an issue with the format. Try again.
On MultipleStructuredOutputsError:
Copy
Ask AI
================================= Tool Message =================================Name: ToolStrategyMultiple structured outputs were returned. Pick the most relevant one.