LangChain Output Strategies

LangChain provides three structured output strategies. Understanding their differences and how they work can help you make the best choice in different scenarios.


Overview of Three Strategies

StrategyPrincipleModel SupportResponse Speed
ToolStrategyDisguises the Schema as a tool; the model "calls" this tool to output structured dataAll models that support function callingSlower (one extra tool call)
ProviderStrategyUses the model's native structured output capability (e.g., OpenAI's response_format)Some models (GPT-4o+, Claude 3+, etc.)Faster (direct output)
AutoStrategyAutomatically detects model capabilities and selects the best strategyAutomatic adaptationAutomatically selects the optimal

ToolStrategy — Tool Calling Mode

ToolStrategy is the most compatible approach. It converts your Schema into a "fake tool," and the model outputs structured data by calling this tool.

Example

from pydantic import BaseModel, Field
from langchain.agents import create_agent
from langchain.agents.structured_output import ToolStrategy
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage


class WeatherReport(BaseModel):
    """Weather Report"""
    city: str = Field(description="City name")
    temperature: float = Field(description="Temperature (Celsius)")
    condition: str = Field(description="Weather condition")
    humidity: int = Field(description="Humidity percentage")


model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)

# Explicitly specify using ToolStrategy
agent = create_agent(
    model=model,
    response_format=ToolStrategy(schema=WeatherReport),
    system_prompt="You are a weather assistant. Generate a structured weather report based on the user's description.",
)

result = agent.invoke({
    "messages": [HumanMessage(content="Hangzhou is sunny today, 25 degrees, humidity 60%")]
})

report = result["structured_response"]
print(f"City: {report.city}")
print(f"Temperature: {report.temperature}°C")
print(f"Condition: {report.condition}")
print(f"Humidity: {report.humidity}%")

# View the execution process — you can see an extra tool call message
print(f"\n"Total messages: {len(result['messages'])}")
for msg in result["messages"]:
    print(f"  [{msg.type}]", end="")
    if hasattr(msg, 'tool_calls') and msg.tool_calls:
        print(f" Calls: {[tc['name'] for tc in msg.tool_calls]}")
    elif msg.type == "tool":
        print(f" {msg.content[:60]}")
    else:
        print(f" {str(msg.content)[:60]}")

Output:

City: 杭州
Temperature: 25.0°C
Condition: 晴天
Humidity: 60%

Total messages: 4
  [human] 杭州今天晴天,温度25度,湿度60%
  [ai] 调用: ['WeatherReport']
  [tool] Returning structured response: ...
  [ai]

You can see that ToolStrategy adds an extra tool calling step (calling a "fake tool" named WeatherReport) before producing the structured output.

handle_errors — Error Retry

ToolStrategy supports automatic retry when structured output fails:

Example

from langchain.agents.structured_output import ToolStrategy

# handle_errors=True: when the output format is wrong, feed the error message back to the model to retry
strategy_with_retry = ToolStrategy(
    schema=WeatherReport,
    handle_errors=True,  # Default is False
)

# handle_errors can also be a custom error message template
strategy_custom_error = ToolStrategy(
    schema=WeatherReport,
    handle_errors="The format is incorrect. Please correct it according to {error} and output again.",
)

ProviderStrategy — Native Structured Output

ProviderStrategy uses the model provider's native capabilities (such as OpenAI's response_format parameter). Not all models support it.

Example

from pydantic import BaseModel, Field
from langchain.agents import create_agent
from langchain.agents.structured_output import ProviderStrategy
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage


class CourseInfo(BaseModel):
    """Course Information"""
    name: str = Field(description="Course name")
    level: str = Field(description="Difficulty: Beginner/Intermediate/Advanced")
    price: str = Field(description="Price information")


model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)

# Explicitly specify ProviderStrategy
agent = create_agent(
    model=model,
    response_format=ProviderStrategy(schema=CourseInfo),
    system_prompt="You are the course assistant for EXAMPLE.",
)

result = agent.invoke({
    "messages": [HumanMessage(content="The Python 3 basics tutorial is a free beginner-level course")]
})

course = result["structured_response"]
print(f"Course: {course.name}")
print(f"Difficulty: {course.level}")
print(f"Price: {course.price}")
print(f"\n"Number of messages: {len(result['messages'])}")  # Fewer than ToolStrategy

Output:

Course: Python3 基础教程
Difficulty: 入门
Price: 免费

Message count: 2

Compared with ToolStrategy, ProviderStrategy has fewer messages (2 vs 4) because it does not require an extra tool calling step.

ProviderStrategy is currently mainly supported by OpenAI's GPT-4o and above, and Claude 3 and above. If the model does not support it, LangChain will automatically fall back to ToolStrategy. You can check whether the model supports it via model.profile.


AutoStrategy — Automatic Selection

This is the most recommended approach. Pass in a Pydantic model (instead of a strategy object), and LangChain will automatically select the best strategy:

Example

from pydantic import BaseModel, Field
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage


class Analysis(BaseModel):
    """Analysis Result"""
    summary: str = Field(description="One-sentence summary")
    score: int = Field(description="Score 1~10")
    pros: list[str] = Field(description="List of pros")
    cons: list[str] = Field(description="List of cons")


# Directly pass in a Pydantic model — LangChain automatically selects the strategy
model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)
agent = create_agent(
    model=model,
    response_format=Analysis,  # Directly pass the model; the strategy is selected automatically
    system_prompt="You are a course evaluation expert. Evaluate the course described by the user.",
)

result = agent.invoke({
    "messages": [HumanMessage(
        content="EXAMPLE's Python course: comprehensive and systematic content,"
                "rich in examples, and completely free. However, video tutorials are limited,"
                "and advanced content coverage is insufficient."
    )]
})

analysis = result["structured_response"]
print(f"Summary: {analysis.summary}")
print(f"Score: {analysis.score}/10")
print(f"Pros: {', '.join(analysis.pros)}")
print(f"Cons: {', '.join(analysis.cons)}")

Output:

Summary: Example Python 课程内容系统且免费,但缺乏视频教学和高级内容
Rating: 7/10
Pros: 内容系统全面, 实例丰富, 完全免费
Cons: 视频教程较少, 高级内容覆盖不够

Guide to Choosing Among Three Strategies

ScenarioRecommended StrategyReason
Not sure whether the model supports native outputAutoStrategy (directly pass Pydantic)Automatically selects the best strategy
Need to be compatible with various modelsToolStrategyWorks with all models that support function calling
Pursuing maximum performanceProviderStrategySkips the tool calling step, faster
Need error retryToolStrategy(handle_errors=True)Only ToolStrategy supports handle_errors

In most cases, directly passing a Pydantic model (i.e., using AutoStrategy) is sufficient. Only when you need error retry or explicit control over strategy behavior do you need to explicitly specify ToolStrategy or ProviderStrategy.

Other Extensions