> ## Documentation Index
> Fetch the complete documentation index at: https://langchain.idochub.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 代理（Agents）

<Warning>
  **Alpha 版本提示：** 本文档涵盖的是 **v1-alpha** 版本。内容尚不完整，且可能随时变更。

  如需查阅最新稳定版本，请参阅 v0 版本的 [LangChain Python 文档](https://python.langchain.com/docs/introduction/) 或 [LangChain JavaScript 文档](https://js.langchain.com/docs/introduction/)。
</Warning>

## 概述

代理将语言模型与工具相结合，创建能够对任务进行推理、决定使用哪些工具并迭代推进解决方案的系统。

`create_agent()` 提供了一个基于论文《ReAct: Synergizing Reasoning and Acting in Language Models》（[https://arxiv.org/abs/2210.03629](https://arxiv.org/abs/2210.03629)）的生产级 ReAct（推理 + 行动）代理实现。

<Columns cols={2}>
  <Card>
    ReAct 将代理的行为框架化为交替进行的 `思考` -> `行动` -> `观察` 步骤，其中模型会写出其推理过程，选择一个工具，查看工具的结果，然后重复此过程。ReAct 减少了幻觉现象，并使决策过程可审计：代理可以形成假设（`思考`），用工具进行测试（`行动`），并根据反馈更新其计划（`观察`）。

    ReAct 循环会一直运行，直到达到停止条件——即模型输出最终答案或达到最大迭代次数限制。
  </Card>

  <Card>
    ```mermaid theme={null}
    %%{
      init: {
        "fontFamily": "monospace",
        "flowchart": {
          "curve": "curve"
        },
        "themeVariables": {"edgeLabelBackground": "transparent"}
      }
    }%%
    graph TD
      %% 代理外部
      QUERY([查询])
      LLM{思考}
      TOOL(工具)
      ANSWER([答案])

      %% 主要流程（无内联标签）
      QUERY --> LLM
      LLM --"行动"--> TOOL
      TOOL --"观察"--> LLM
      LLM --"完成"--> ANSWER

      classDef blueHighlight fill:#0a1c25,stroke:#0a455f,color:#bae6fd;
      classDef greenHighlight fill:#0b1e1a,stroke:#0c4c39,color:#9ce4c4;
      class QUERY blueHighlight;
      class ANSWER blueHighlight;
    ```
  </Card>
</Columns>

<Info>
  在底层，`create_agent()` 使用 [LangGraph](/oss/python/langgraph/overview) 构建了一个**基于图**的代理运行时。图由节点（步骤）和边（连接）组成，定义了代理如何处理信息。代理在图中移动，执行诸如模型节点（调用模型）、工具节点（执行工具）或模型前后钩子节点等节点。了解更多关于 [图 API](/oss/python/langgraph/graph-api) 的内容。
</Info>

## 核心组件

### 模型

[模型](/oss/python/langchain/models) 是代理的推理引擎。它可以通过多种方式指定，支持静态和动态模型选择。

#### 静态模型

静态模型在创建代理时配置一次，并在执行过程中保持不变。这是最常见且最直接的方法。要从模型标识符字符串初始化静态模型：

```python wrap theme={null}
from langchain.agents import create_agent

agent = create_agent(
    "openai:gpt-5",
    tools=tools
)
```

模型标识符字符串使用 `provider:model` 格式（例如 `"openai:gpt-5"`），并支持自动推断（例如 `"gpt-5"` 将被推断为 `"openai:gpt-5"`）。您可能希望对模型配置拥有更多控制权，此时可以直接使用提供商包初始化模型实例：

```python wrap theme={null}
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)
```

模型实例让您完全控制配置。当您需要设置特定参数（如温度、最大令牌数、超时时间）或配置 API 密钥、基础 URL 和其他提供商特定设置时，请使用它们。请参阅 [API 参考](/oss/python/integrations/providers/all_providers) 以查看模型上可用的参数和方法。

#### 动态模型

<Info>
  **`runtime`**：代理的执行环境，包含在代理执行期间保持不变的配置和上下文数据（例如用户 ID、会话详细信息或应用程序特定配置）。
</Info>

<Info>
  **`state`**：在代理执行过程中流动的数据，包括消息、自定义字段以及在处理过程中需要跟踪和可能修改的任何信息（例如用户偏好或工具使用统计）。
</Info>

动态模型在运行时根据当前状态和上下文进行选择。这实现了复杂的路由逻辑和成本优化。

要使用动态模型，您需要提供一个函数，该函数接收图状态和运行时，并返回一个使用 `.bind_tools(tools)` 绑定工具的 `BaseChatModel` 实例，其中 `tools` 是 `tools` 参数的一个子集。

```python theme={null}
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent, AgentState
from langgraph.runtime import Runtime

def select_model(state: AgentState, runtime: Runtime) -> ChatOpenAI:
    """根据对话复杂性选择模型。"""
    messages = state["messages"]
    message_count = len(messages)

    if message_count < 10:
        return ChatOpenAI(model="gpt-4.1-mini").bind_tools(tools)
    else:
        return ChatOpenAI(model="gpt-5").bind_tools(tools) # 适用于更长对话的更好模型

agent = create_agent(select_model, tools=tools)
```

<Tip>
  有关模型配置的详细信息，请参阅 [模型](/oss/python/langchain/models)。
</Tip>

### 工具

工具赋予代理采取行动的能力。代理超越了简单的仅模型工具绑定，能够实现：

* 由单个提示触发的多个工具调用序列
* 在适当情况下并行调用工具
* 根据结果动态选择工具
* 工具重试逻辑和错误处理
* 工具调用之间的状态持久化

工具可以以下列形式提供给代理：

1. 工具列表（LangChain `@tool`、可调用对象或表示内置提供商工具的 `dict`）
2. 配置好的 `ToolNode`

#### 传递工具列表

将工具列表传递给代理将在底层创建一个 `ToolNode`。这是设置工具调用代理的最简单方法：

```python wrap theme={null}
from langchain_core.tools import tool
from langchain.agents import create_agent

@tool
def search(query: str) -> str:
    """搜索信息。"""
    return f"结果为：{query}"

@tool
def calculate(expression: str) -> str:
    """执行计算。"""
    return str(eval(expression))

agent = create_agent(model, tools=[search, calculate])
```

如果提供空的工具列表，代理将仅由一个没有工具调用的 LLM 节点组成。

#### 传递配置好的 ToolNode

或者，您可以直接创建一个 `ToolNode` 并将其传递给代理。这允许您自定义工具节点的行为，例如处理工具错误：

```python wrap theme={null}
tool_node = ToolNode(
    tools=[search, calculate],
    handle_tool_errors="请检查您的输入并重试。"
)
agent = create_agent(model, tools=tool_node)
result = agent.invoke({"messages": [...]})
```

如果在 `ToolNode` 中发生错误，代理将向模型返回一个带有自定义错误消息的 `ToolMessage`：

```python theme={null}
# result["messages"]
[
    ...
    ToolMessage(content="请检查您的输入并重试。", tool_call_id="..."),
    ...
]

```

<Tip>
  要了解有关 `ToolNode` 中错误处理的更多信息，请参阅 [ToolNode](/oss/python/langchain/tools#toolnode)。
</Tip>

### ReAct 循环中的工具使用

代理遵循 ReAct（*推理* + *行动*）模式，在简短的推理步骤与有针对性的工具调用之间交替进行，并将结果观察反馈到后续决策中，直到能够提供最终答案。

跟随代理应用 ReAct 回答用户问题的过程：

<Card title="提示：识别当前最受欢迎的无线耳机并验证库存。">
  ```
  ================================ 人类消息 =================================

  找出目前最受欢迎的无线耳机并检查是否有库存
  ```

  *推理*：“流行度是随时间变化的，我需要使用提供的搜索工具。”

  *行动*：调用 `search_products("wireless headphones")`

  ```
  ================================== AI 消息 ==================================
  工具调用：
    search_products (call_abc123)
   调用 ID: call_abc123
    参数：
      query: wireless headphones
  ```

  ```
  ================================= 工具消息 =================================

  找到 5 个匹配“无线耳机”的产品。前 5 个结果：WH-1000XM5, ...
  ```

  *推理*：“在回答之前，我需要确认排名第一的产品的库存情况。”

  *行动*：调用 `check_inventory("WH-1000XM5")`

  ```
  ================================== AI 消息 ==================================
  工具调用：
    check_inventory (call_def456)
   调用 ID: call_def456
    参数：
      product_id: WH-1000XM5
  ```

  ```
  ================================= 工具消息 =================================

  产品 WH-1000XM5：库存 10 件
  ```

  *推理*：“我已获得最受欢迎的型号及其库存状态。现在可以回答用户的问题了。”

  *行动*：生成最终答案

  ```
  ================================== AI 消息 ==================================

  我找到了无线耳机（型号 WH-1000XM5），库存 10 件...
  ```
</Card>

<Tip>
  要了解有关工具的更多信息，请参阅 [工具](/oss/python/langchain/tools)。
</Tip>

### 提示

您可以通过提供提示来塑造代理处理任务的方式。`prompt` 参数可以以多种形式提供。

#### 字符串

```python wrap theme={null}
agent = create_agent(
    model,
    tools,
    prompt="您是一个乐于助人的助手。请简洁准确。"
)
```

#### SystemMessage

```python wrap theme={null}
agent = create_agent(
    model,
    tools,
    prompt=SystemMessage(content="您是一个研究助理。请引用您的来源。")
)
```

#### 可调用对象

```python wrap theme={null}
def dynamic_prompt(state):
    user_type = state.get("user_type", "standard")
    system_msg = SystemMessage(
        content="提供详细的技术响应。"
        if user_type == "expert"
        else "提供简单清晰的解释。"
    )
    return [system_msg] + state["messages"]
agent = create_agent(model, tools, prompt=dynamic_prompt)
```

当未提供 `prompt` 时，代理将直接从消息中推断其任务。

<Tip>
  有关消息类型和格式的更多详细信息，请参阅 [消息](/oss/python/langchain/messages)。
</Tip>

## 高级配置

### 结构化输出

在某些情况下，您可能希望代理以特定格式返回输出。LangChain 通过 `response_format` 参数提供了一种简单通用的方法。

```python wrap theme={null}
from pydantic import BaseModel
from langchain.agents import create_agent

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

agent = create_agent(
    model,
    tools=[search_tool],
    response_format=ContactInfo
)

result = agent.invoke({
    "messages": [{"role": "user", "content": "从以下内容中提取联系信息：John Doe, john@example.com, (555) 123-4567"}]
})

result["structured_response"]
# ContactInfo(name='John Doe', email='john@example.com', phone='(555) 123-4567')
```

<Tip>
  要了解有关结构化输出的更多信息，请参阅 [结构化输出](/oss/python/langchain/structured-output)。
</Tip>

### 内存

代理通过消息状态自动维护对话历史。您还可以配置代理使用自定义状态模式在对话期间记住额外信息。

存储在状态中的信息可以被视为代理的“短期记忆”：

```python wrap theme={null}
from typing import TypedDict
from typing_extensions import Annotated
from langgraph.graph.message import add_messages
from langchain.agents import create_agent
from langchain.agents import AgentState

class CustomAgentState(AgentState):
    messages: Annotated[list, add_messages]
    user_preferences: dict

agent = create_agent(
    model,
    tools=tools,
    state_schema=CustomAgentState
)

# 代理现在可以跟踪除消息之外的额外状态。此自定义状态可以在整个对话过程中访问和更新。
result = agent.invoke({
    "messages": [{"role": "user", "content": "我更喜欢技术性解释"}],
    "user_preferences": {"style": "technical", "verbosity": "detailed"},
})
```

<Tip>
  要了解有关内存的更多信息，包括如何实现跨会话持久化的长期记忆，请参阅 [内存](/oss/python/memory)。
</Tip>

### 模型前钩子

模型前钩子是一个可选节点，可以在调用模型之前处理状态。用例包括消息修剪、摘要和上下文注入。

```mermaid theme={null}
%%{
    init: {
        "fontFamily": "monospace",
        "flowchart": {
        "curve": "curve"
        },
        "themeVariables": {"edgeLabelBackground": "transparent"}
    }
}%%
graph TD
    S(["\_\_start\_\_"])
    PRE(pre_model_hook)
    AG(model)
    POST(post_model_hook)
    END(["\_\_end\_\_"])
    TOOLS(tools)

    S --> PRE
    PRE --> AG
    AG --> POST
    TOOLS --> PRE

    POST -.-> PRE
    POST -.-> TOOLS
    POST -.-> END

    classDef blueHighlight fill:#0a1c25,stroke:#0a455f,color:#bae6fd;
    classDef greenHighlight fill:#0b1e1a,stroke:#0c4c39,color:#9ce4c4;
    class S blueHighlight;
    class END blueHighlight;
    class PRE greenHighlight;
```

它必须是一个可调用对象或可运行对象，接收当前图状态并以以下形式返回状态更新：

```python wrap theme={null}
{
    # 将更新状态中的 `messages`
    "messages": [RemoveMessage(id=REMOVE_ALL_MESSAGES), ...],
    # 需要传播的其他状态键
    ...
}
```

模型前钩子示例，用于修剪消息以适应上下文窗口：

```python wrap theme={null}
from langchain_core.messages import RemoveMessage
from langgraph.graph.message import REMOVE_ALL_MESSAGES
from langchain.agents import create_agent

def trim_messages(state):
    """仅保留最后几条消息以适应上下文窗口。"""
    messages = state["messages"]

    if len(messages) <= 3:
        return {"messages": messages}

    first_msg = messages[0]
    recent_messages = messages[-3:] if len(messages) % 2 == 0 else messages[-4:]
    new_messages = [first_msg] + recent_messages

    return {
        "messages": [
            RemoveMessage(id=REMOVE_ALL_MESSAGES),
            *new_messages
        ]
    }

agent = create_agent(
    model,
    tools=tools,
    pre_model_hook=trim_messages
)
```

<Info>
  必须提供 `messages`，并将其用作 `agent` 节点（即调用 LLM 的节点）的输入。其余键将添加到图状态中。
</Info>

<Warning>
  如果您在模型前钩子中返回 `messages`，应通过以下方式**覆盖** `messages` 键：

  ```python wrap theme={null}
  {
  "messages": [RemoveMessage(id=REMOVE_ALL_MESSAGES), *new_messages]
  ...
  }
  ```
</Warning>

### 模型后钩子

模型后钩子是一个可选节点，可以在工具执行之前处理模型的响应。用例包括验证、防护措施或其他后处理。

```mermaid theme={null}
%%{
    init: {
        "fontFamily": "monospace",
        "flowchart": {
        "curve": "curve"
        },
        "themeVariables": {"edgeLabelBackground": "transparent"}
    }
}%%
graph TD
    S(["\_\_start\_\_"])
    PRE(pre_model_hook)
    AG(model)
    POST(post_model_hook)
    END(["\_\_end\_\_"])
    TOOLS(tools)

    S --> PRE
    PRE --> AG
    AG --> POST
    TOOLS --> PRE

    POST -.-> PRE
    POST -.-> TOOLS
    POST -.-> END

    classDef blueHighlight fill:#0a1c25,stroke:#0a455f,color:#bae6fd;
    classDef greenHighlight fill:#0b1e1a,stroke:#0c4c39,color:#9ce4c4;
    class S blueHighlight;
    class END blueHighlight;
    class POST greenHighlight;
```

它必须是一个可调用对象或可运行对象，接收当前图状态并返回状态更新。

模型后钩子示例，用于过滤机密信息：

```python wrap theme={null}
from langchain_core.messages import AIMessage, RemoveMessage
from langgraph.graph.message import REMOVE_ALL_MESSAGES

def validate_response(state):
    """检查模型响应是否存在策略违规。"""
    messages = state["messages"]
    last_message = messages[-1]

    if "confidential" in last_message.content.lower():
        return {
            "messages": [
                RemoveMessage(id=REMOVE_ALL_MESSAGES),
                *messages[:-1],
                AIMessage(content="我无法分享机密信息。")
            ]
        }

    return {}

agent = create_agent(
    model,
    tools=tools,
    post_model_hook=validate_response
)
```

### 流式传输

我们已经看到如何使用 `.invoke` 调用代理以获得最终响应。如果代理执行多个步骤，这可能需要一段时间。为了显示中间进度，我们可以流式传输回发生的消息。

```python wrap theme={null}
for chunk in agent.stream({
    "messages": [{"role": "user", "content": "搜索 AI 新闻并总结发现"}]
}, stream_mode="values"):
    # 每个块包含此时的完整状态
    latest_message = chunk["messages"][-1]
    if latest_message.content:
        print(f"代理：{latest_message.content}")
    elif latest_message.tool_calls:
        print(f"调用工具：{[tc['name'] for tc in latest_message.tool_calls]}")
```

<Tip>
  有关流式传输的更多详细信息，请参阅 [流式传输](/oss/python/langchain/streaming)。
</Tip>
