智能体是将大语言模型与工具结合起来构建的系统,该系统能够对任务进行推理、决定调用哪些工具并逐步迭代执行直到最后解决问题。 create_agent 可以新建一个生产级别的智能体。 LLM智能体不断循环调用工具直到实现最终目标。 如图,智能体一直循环运行直到满足停止条件 —— 即当模型能够输出最终结果或达到迭代次数限制。
create_agent 使用 LangGraph 构建基于图形的智能体运行时环境。图形由节点(步骤)和边(连接)组成,这些内容决定智能体如何处理信息。智能体按照图的结构进行流转,不断执行一个个的执行节点,执行节点可以是模型节点(调用模型)、工具节点(执行工具)或中间件。了解 Graph API 的更多信息。

核心组件

模型

模型 是智能体的引擎。它可以通过多种方式指定,支持静态指定和动态选择。

静态指定模型

静态模型在创建智能体时配置一次,在整个执行过程中保持不变。这是最常见和最直接的方法。 可以使用 来初始化静态模型:
from langchain.agents import create_agent

agent = create_agent("openai:gpt-5", tools=tools)
模型标识符字符串支持自动推断(例如 "gpt-5" 将被推断为 "openai:gpt-5")。请参阅参考文档查看完整的模型标识符字符串映射列表。
要想更好地控制模型配置,请直接使用供应商发行包进行模型实例化。在下面示例中,我们使用 ChatOpenAI。有关其他可用的聊天模型类,请参阅聊天模型
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model="gpt-5",
    temperature=0.1,
    max_tokens=1000,
    timeout=30
    # ... (其他参数)
)
agent = create_agent(model, tools=tools)
模型实体化方式让您能够完全掌控具体参数配置,当你需要配置特定的参数temperaturemax_tokenstimeoutsbase_url 和其他供应商特定参数时,请使用模型实例化方式。请参阅参考文档查看模型上可用的参数和方法。

动态选择模型

基于 的当前 和上下文可以进行模型的动态选择,这有助于实现复杂的路由逻辑和成本优化。 要实现动态选择模型,使用 @wrap_model_call 装饰器来创建一个中间件,并在中间件中修改请求使用的模型:
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse


basic_model = ChatOpenAI(model="gpt-4.1-mini")
advanced_model = ChatOpenAI(model="gpt-4.1")

@wrap_model_call
def dynamic_model_selection(request: ModelRequest, handler) -> ModelResponse:
    """Choose model based on conversation complexity."""
    message_count = len(request.state["messages"])

    if message_count > 10:
        # 对更长的对话使用高级模型
        model = advanced_model
    else:
        model = basic_model

    return handler(request.override(model=model))

agent = create_agent(
    model=basic_model,    # 默认模型
    tools=tools,
    middleware=[dynamic_model_selection]
)
使用结构化输出时,预绑定模型(已调用 bind_tools 的模型)不支持动态选择模型。如果您需要使用结构化输出的动态模型选择,请确保传递给中间件的模型不是预绑定的。
有关模型配置详情,请参阅模型。有关动态模型选择模式,请参阅中间件中的动态模型

工具

工具赋予智能体执行操作的能力。模型也可以调用工具,但智能体对工具的掌控能力超越了模型,主要体现在:
  • 按顺序调用多个工具(由单个提示触发)
  • 在适当时并行调用工具
  • 基于先前结果动态选择工具
  • 工具重试逻辑和错误处理
  • 跨工具调用的状态持久化
有关更多信息,请参阅工具

静态工具

静态工具是在创建智能体时指定,在整个执行过程中保持不变。这是最常见和最直接的方法。 要定义一个可以调用工具的智能体,将工具列表传递给智能体参数tools。
工具可以是普通 Python 函数或 工具装饰器@tool可用于指定工具名称、描述、参数模式和其他属性。
from langchain.tools import tool
from langchain.agents import create_agent


@tool
def search(query: str) -> str:
    """Search for information."""
    return f"Results for: {query}"

@tool
def get_weather(location: str) -> str:
    """Get weather information for a location."""
    return f"Weather in {location}: Sunny, 72°F"

agent = create_agent(model, tools=[search, get_weather])
如果传入空的工具列表,智能体将仅包含LLM节点,但没有工具调用能力。

动态工具

使用动态工具,智能体可用的工具集在运行时是动态变化的,而不是预先全部定义好。并非每个工具都适合所有情况,另外太多工具可能会压垮模型(上下文过载)并增加错误;太少又会限制能力。动态工具使得基于认证状态、用户权限、功能标志或对话阶段而调整可用工具集得以实现。 根据是否提前获知工具,有两种方法:
当所有可能的工具在智能体创建时都可获得时,您可以先注册它们,并基于状态、权限或上下文动态过滤哪些工具暴露给模型。
在达到某些对话里程碑后启用高级工具:
from langchain.agents import create_agent
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
from typing import Callable

@wrap_model_call
def state_based_tools(
    request: ModelRequest,
    handler: Callable[[ModelRequest], ModelResponse]
) -> ModelResponse:
    """Filter tools based on conversation State."""
    # 从状态读取:检查用户是否已认证
    state = request.state
    is_authenticated = state.get("authenticated", False)
    message_count = len(state["messages"])

    # 仅在认证后启用敏感工具
    if not is_authenticated:
        tools = [t for t in request.tools if t.name.startswith("public_")]
        request = request.override(tools=tools)
    elif message_count < 5:
        # 在对话早期限制工具
        tools = [t for t in request.tools if t.name != "advanced_search"]
        request = request.override(tools=tools)

    return handler(request)

agent = create_agent(
    model="gpt-4.1",
    tools=[public_search, private_search, advanced_search],
    middleware=[state_based_tools]
)
此方法最适合:
  • 所有可能的工具在编译/启动时都知道
  • 您想基于权限、功能标志或对话状态进行过滤
  • 工具是静态的,但其可用性是动态的
有关更多示例,请参阅动态选择工具
要了解更多关于工具的信息,请参阅工具

工具的错误处理

要自定义工具错误的处理方式,请使用 @wrap_tool_call 装饰器创建中间件:
from langchain.agents import create_agent
from langchain.agents.middleware import wrap_tool_call
from langchain.messages import ToolMessage


@wrap_tool_call
def handle_tool_errors(request, handler):
    """Handle tool execution errors with custom messages."""
    try:
        return handler(request)
    except Exception as e:
        # 返回自定义错误消息给模型
        return ToolMessage(
            content=f"Tool error: Please check your input and try again. ({str(e)})",
            tool_call_id=request.tool_call["id"]
        )

agent = create_agent(
    model="gpt-4.1",
    tools=[search, get_weather],
    middleware=[handle_tool_errors]
)
当工具失败时,智能体将返回带有自定义错误消息的 ToolMessage
[
    ...
    ToolMessage(
        content="Tool error: Please check your input and try again. (division by zero)",
        tool_call_id="..."
    ),
    ...
]

工具在 ReAct 循环中的使用

智能体遵循 ReAct(“推理 + 行动”)模式,在执行简要推理并有针对性执行工具调用和将结果反馈给后续决策之间交替进行,直到它们能够提供最终答案。
提示: 识别当前最流行的无线耳机并验证可购买性。
================================ Human Message =================================

Find the most popular wireless headphones right now and check if they're in stock
  • 推理:“是否流行是时间敏感的,我需要使用搜索工具。”
  • 行动:调用 search_products("wireless headphones")
================================== Ai Message ==================================
Tool Calls:
  search_products (call_abc123)
 Call ID: call_abc123
  Args:
    query: wireless headphones
================================= Tool Message =================================

Found 5 products matching "wireless headphones". Top 5 results: WH-1000XM5, ...
  • 推理:“我需要确认排名靠前商品的库存状态后再回答。”
  • 行动:调用 check_inventory("WH-1000XM5")
================================== Ai Message ==================================
Tool Calls:
  check_inventory (call_def456)
 Call ID: call_def456
  Args:
    product_id: WH-1000XM5
================================= Tool Message =================================

Product WH-1000XM5: 10 units in stock
  • 推理:“我有了最流行的型号及其库存状态。现在可以回答用户的问题了。”
  • 行动:生成最终答案
================================== Ai Message ==================================

I found wireless headphones (model WH-1000XM5) with 10 units in stock...

系统提示词

您可以通过提供系统提示词来塑造智能体处理任务的方式。可以直接把字符串赋值给system_prompt
agent = create_agent(
    model,
    tools,
    system_prompt="You are a helpful assistant. Be concise and accurate."
)
当未提供 system_prompt 时,智能体将直接从对话消息中推断其提示词。 system_prompt 参数接受 strSystemMessage类型。使用 SystemMessage 可以更好地控制提示词结构,这对于某些供应商的特定功能(如 Anthropic 的提示缓存)很有用:
from langchain.agents import create_agent
from langchain.messages import SystemMessage, HumanMessage

literary_agent = create_agent(
    model="anthropic:claude-sonnet-4-5",
    system_prompt=SystemMessage(
        content=[
            {
                "type": "text",
                "text": "You are an AI assistant tasked with analyzing literary works.",
            },
            {
                "type": "text",
                "text": "<the entire contents of 'Pride and Prejudice'>",
                "cache_control": {"type": "ephemeral"}
            }
        ]
    )
)

result = literary_agent.invoke(
    {"messages": [HumanMessage("Analyze the major themes in 'Pride and Prejudice'.")]}
)
带有 {"type": "ephemeral"}cache_control 字段告诉 Anthropic 缓存该内容块,减少使用相同系统提示词时重复请求的延迟和成本。

动态系统提示词

对于一些更高级的用法,比如需要基于运行时上下文或智能体状态来改变系统提示词的情况,您可以使用中间件达到目的。 @dynamic_prompt 装饰器可创建一个中间件,能够实现根据不同模型请求而生成不同的系统提示词的功能:
from typing import TypedDict

from langchain.agents import create_agent
from langchain.agents.middleware import dynamic_prompt, ModelRequest


class Context(TypedDict):
    user_role: str

@dynamic_prompt
def user_role_prompt(request: ModelRequest) -> str:
    """Generate system prompt based on user role."""
    user_role = request.runtime.context.get("user_role", "user")
    base_prompt = "You are a helpful assistant."

    if user_role == "expert":
        return f"{base_prompt} Provide detailed technical responses."
    elif user_role == "beginner":
        return f"{base_prompt} Explain concepts simply and avoid jargon."

    return base_prompt

agent = create_agent(
    model="gpt-4.1",
    tools=[web_search],
    middleware=[user_role_prompt],
    context_schema=Context
)

# 系统提示将基于上下文动态设置
result = agent.invoke(
    {"messages": [{"role": "user", "content": "Explain machine learning"}]},
    context={"user_role": "expert"}
)
有关消息类型和格式的更多详情,请参阅消息。有关全面的中间件文档,请参阅中间件

智能体名称

可以为智能体设置一个名称 name。当把某个智能体作为子图subgraph添加到多智能体系统时,这个名字会被用作节点Node的标识符:
agent = create_agent(
    model,
    tools,
    name="research_assistant"
)
智能体名称优先使用 snake_case(例如 research_assistant 而不是 ResearchAssistant)。某些模型供应商对包含空格或特殊字符的名称有问题或拒绝。坚持仅使用字母数字字符、下划线和连字符可确保跨所有供应商的兼容性。这同样适用于工具名称

调用

所有智能体都在其状态内包含一个消息序列,您可以通过向其 State 传递一个更新来调用智能体。也就是,要调用代理,请传递一个新消息:
result = agent.invoke(
    {"messages": [{"role": "user", "content": "What's the weather in San Francisco?"}]}
)
有关从智能体流式传输步骤和流式Token的信息,请参阅流式输出指南。 智能体遵循 LangGraph Graph API,并支持所有相关方法,如 streaminvoke
使用 LangSmith 来跟踪、调试和评估您的智能体。

高级概念

结构化输出

在某些情况下,您可能希望智能体以特定格式返回输出。LangChain 通过 response_format 参数提供结构化输出策略。

ToolStrategy

ToolStrategy 调用人工工具来生成结构化输出。这适用于任何支持工具调用的模型。当供应商原生的结构化输出(通过 ProviderStrategy)不可用或不可靠时,应使用 ToolStrategy
from pydantic import BaseModel
from langchain.agents import create_agent
from langchain.agents.structured_output import ToolStrategy


class ContactInfo(BaseModel):
    name: str
    email: str
    phone: str

agent = create_agent(
    model="gpt-4.1-mini",
    tools=[search_tool],
    response_format=ToolStrategy(ContactInfo)
)

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')

ProviderStrategy

ProviderStrategy 使用模型供应商的原生功能生成结构化输出。这更可靠,但仅适用于支持原生结构化输出的供应商模型:
from langchain.agents.structured_output import ProviderStrategy

agent = create_agent(
    model="gpt-4.1",
    response_format=ProviderStrategy(ContactInfo)
)
langchain 1.0 开始,在模型支持原生结构化输出时,简单地赋值模式(例如 response_format=ContactInfo)将默认为 ProviderStrategy,否则将回退到 ToolStrategy
要了解结构化输出,请参阅结构化输出

记忆

智能体通过消息状态自动保存对话历史,当然,您还可以让智能体使用自定义状态模式结构在对话期间保存其他附加信息。 存储在消息状态中的信息可以看作是智能体的短期记忆 自定义状态模式必须从 AgentState 继承,并且类型为 TypedDict 有两种方式进行自定义状态的定义:
  1. 通过中间件(首选)
  2. 通过 create_agent 时的 state_schema

通过中间件定义状态

当您定义的自定义状态需要被特定中间件钩子和被绑定到中间的工具访问时,使用中间件来对自定义状态进行定义。
from langchain.agents import AgentState
from langchain.agents.middleware import AgentMiddleware
from typing import Any


class CustomState(AgentState):
    user_preferences: dict

class CustomMiddleware(AgentMiddleware):
    state_schema = CustomState
    tools = [tool1, tool2]

    def before_model(self, state: CustomState, runtime) -> dict[str, Any] | None:
        ...

agent = create_agent(
    model,
    tools=tools,
    middleware=[CustomMiddleware()]
)

# 代理现在可以跟踪消息之外的额外状态
result = agent.invoke({
    "messages": [{"role": "user", "content": "I prefer technical explanations"}],
    "user_preferences": {"style": "technical", "verbosity": "detailed"},
})

通过 state_schema 定义状态

使用 state_schema 参数可快捷地来定义仅在工具中使用的自定义状态。
from langchain.agents import AgentState


class CustomState(AgentState):
    user_preferences: dict

agent = create_agent(
    model,
    tools=[tool1, tool2],
    state_schema=CustomState
)
# 代理现在可以跟踪消息之外的额外状态
result = agent.invoke({
    "messages": [{"role": "user", "content": "I prefer technical explanations"}],
    "user_preferences": {"style": "technical", "verbosity": "detailed"},
})
langchain 1.0 开始,自定义状态模式必须是 TypedDict 类型。不再支持 Pydantic 模型和 dataclass。请参阅 v1 迁移指南了解更多详情。
通过中间件定义自定义状态优于通过 create_agent 上的 state_schema 定义它,因为它允许您将状态扩展概念性地保持在相关中间件和工具的范围内。为保持向后兼容性,create_agent 上的state_schema 仍然可用。
要了解更多关于记忆的信息,请参阅记忆。有关实现跨会话持久化的长期记忆的信息,请参阅长期记忆

流式传输

我们已经看到如何用 invoke 调用智能体来获取最终响应。如果智能体需要执行多个步骤,这可能需要一些时间。为了显示中间进度,我们可以流式传输发生的消息。
from langchain.messages import AIMessage, HumanMessage

for chunk in agent.stream({
    "messages": [{"role": "user", "content": "Search for AI news and summarize the findings"}]
}, stream_mode="values"):
    # 每个块包含该点的完整状态
    latest_message = chunk["messages"][-1]
    if latest_message.content:
        if isinstance(latest_message, HumanMessage):
            print(f"User: {latest_message.content}")
        elif isinstance(latest_message, AIMessage):
            print(f"Agent: {latest_message.content}")
    elif latest_message.tool_calls:
        print(f"Calling tools: {[tc['name'] for tc in latest_message.tool_calls]}")
有关流式传输的更多详情,请参阅流式传输

中间件

中间件 为不同执行阶段定制智能体行为提供了强大的扩展性,您可以使用中间件来:
  • 在调用模型之前处理状态(例如消息修剪、上下文注入)
  • 修改或验证模型的响应(例如防护栏、内容过滤)
  • 使用自定义逻辑处理工具执行的错误
  • 基于状态或上下文实现动态模型选择
  • 添加自定义日志记录、监控或分析
中间件可无缝集成到智能体的执行中,允许您在关键点拦截和修改数据流,而无需更改智能体的核心逻辑。
有关全面的中间件文档,包括 @before_model@after_model@wrap_tool_call 等装饰器,请参阅中间件