> ## 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.

# 多智能体系统

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

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

**多智能体系统** 将复杂应用拆分为多个专业化的智能体，这些智能体协同工作以解决问题。\
相比于依赖单一智能体处理所有步骤，**多智能体架构** 允许你将多个小型、专注的智能体组合成一个协调的工作流程。

多智能体系统在以下情况下尤为有用：

* 单一智能体拥有过多工具，难以做出合理选择；
* 上下文或记忆内容过于庞大，单一智能体无法有效跟踪；
* 任务需要**专业化分工**（例如：规划者、研究员、数学专家）。

## 多智能体模式

| 模式                        | 工作原理                                                 | 控制流                  | 示例应用场景       |
| ------------------------- | ---------------------------------------------------- | -------------------- | ------------ |
| [**工具调用**](#tool-calling) | 中央智能体将其他智能体作为“*工具*”调用。“工具”智能体不直接与用户交互——它们仅执行任务并返回结果。 | 集中式：所有路由均通过调用智能体。    | 任务编排、结构化工作流。 |
| [**交接控制**](#handoffs)     | 当前智能体决定**将控制权转移**给另一个智能体。活跃智能体随之切换，用户可直接与新智能体继续交互。   | 去中心化：智能体可自主决定切换活跃对象。 | 多领域对话、专家接管。  |

## 模式选择指南

| 问题                 | 工具调用 | 交接控制   |
| ------------------ | ---- | ------ |
| 是否需要集中控制工作流？       | ✅ 是  | ❌ 否    |
| 是否希望智能体直接与用户交互？    | ❌ 否  | ✅ 是    |
| 是否需要专家间进行复杂、类人的对话？ | ❌ 有限 | ✅ 强烈推荐 |

<Tip>
  你可以混合使用两种模式——使用**交接控制**实现智能体切换，同时让每个智能体**调用子智能体作为工具**来处理特定任务。
</Tip>

## 自定义智能体上下文

多智能体设计的核心是**上下文工程**——决定每个智能体可见的信息。LangChain 提供细粒度控制，包括：

* 传递给每个智能体的对话或状态的哪些部分；
* 为子智能体定制的专用提示词；
* 包含或排除中间推理过程；
* 按智能体定制输入/输出格式。

系统的质量**高度依赖**于上下文工程。目标是确保每个智能体（无论是作为工具还是活跃智能体）都能获得完成其任务所需的正确数据。

## 工具调用

在**工具调用**模式中，一个智能体（“**控制器**”）将其他智能体视为*工具*，在需要时调用。控制器负责编排，工具智能体执行特定任务并返回结果。

流程：

1. **控制器**接收输入，决定调用哪个工具（子智能体）。
2. **工具智能体**根据控制器的指令执行任务。
3. **工具智能体**将结果返回给控制器。
4. **控制器**决定下一步操作或结束流程。

```mermaid theme={null}
graph LR
    A[用户] --> B[控制器智能体]
    B --> C[工具智能体1]
    B --> D[工具智能体2]
    C --> B
    D --> B
    B --> E[用户响应]
```

<Tip>
  作为工具使用的智能体通常**不应**与用户直接对话。
  它们的作用是执行任务并将结果返回给控制器智能体。
  如果需要子智能体能与用户对话，请改用**交接控制**模式。
</Tip>

### 实现方式

以下是最小示例，主智能体通过工具定义访问单个子智能体：

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

subagent1 = create_agent(..)

@tool(
    name="subagent1_name",
    description="subagent1_description"
)
def call_subagent1(query: str):
    result = subagent1.invoke({
        "messages": [{"role": "user", "content": query}]
    })
    return result["messages"].text
    
agent = create_agent(..., tools=[call_subagent1])
```

在此模式中：

1. 主智能体在判断任务匹配子智能体描述时，调用 `call_subagent1`。
2. 子智能体独立运行并返回结果。
3. 主智能体接收结果并继续编排。

### 可定制点

你可以在多个环节控制主智能体与子智能体之间的上下文传递：

1. **子智能体名称** (`"subagent1_name"`)：主智能体引用子智能体的方式。名称影响提示词，需谨慎选择。
2. **子智能体描述** (`"subagent1_description"`)：主智能体对子智能体的“认知”。直接影响主智能体何时调用它。
3. **子智能体输入**：可自定义输入，以更好引导子智能体理解任务。上例中我们直接传递智能体生成的 `query`。
4. **子智能体输出**：这是返回给主智能体的**响应**。可调整返回内容，以控制主智能体如何解读结果。上例中我们返回最终消息文本，但也可返回额外状态或元数据。

### 控制子智能体输入

控制主智能体传递给子智能体输入的两个主要方法：

* **修改提示词** – 调整主智能体提示词或工具元数据（即子智能体名称和描述），以更好引导调用时机和方式。
* **上下文注入** – 通过调整工具调用从智能体状态中提取信息，添加静态提示词难以捕捉的输入（如完整对话历史、先前结果、任务元数据）。

```python theme={null}
from typing import Annotated
from langchain.agents import AgentState
from langchain.agents.tool_node import InjectedState

@tool(
    name="subagent1_name",
    description="subagent1_description"
)
def call_subagent1(query: str, state: Annotated[CustomState, InjectedState]):
    # 应用任何必要的逻辑，将消息转换为合适的输入
    subagent_input = some_logic(query, state.messages)
    result = subagent1.invoke({
        "messages": subagent_input,
        # 如有需要，也可传递其他状态键。
        # 请确保在主智能体和子智能体的状态模式中均定义这些键。
        "example_state_key": state.example_state_key
    })
    return result["messages"][-1].text
```

### 控制子智能体输出

塑造主智能体从子智能体接收内容的两种常见策略：

* **修改提示词** – 优化子智能体提示词，明确指定应返回的内容。
  * 适用于输出不完整、过于冗长或缺少关键细节的情况。
  * 常见失败模式：子智能体执行工具调用或推理，但**未在最终消息中包含结果**。需提醒子智能体：控制器（和用户）仅看到最终输出，因此所有相关信息必须包含在内。
* **自定义输出格式** – 在将子智能体响应交还主智能体前，通过代码调整或丰富响应。
  * 示例：除最终文本外，向主智能体传递特定状态键。
  * 这需要将结果包装在 `Command`（或等效结构）中，以便将自定义状态与子智能体响应合并。

```python theme={null}
from typing import Annotated
from langchain.agents import AgentState
from langchain_core.tools import InjectedToolCallId
from langgraph.types import Command


@tool(
    name="subagent1_name",
    description="subagent1_description"
)
# 需要将 `tool_call_id` 传递给子智能体，以便其使用该 ID 响应工具调用结果
def call_subagent1(
    query: str, 
    tool_call_id: Annotated[str, InjectedToolCallId],
# 若要返回的不仅是最终工具调用，需返回 `Command` 对象
) -> Command:
    result = subagent1.invoke({
        "messages": [{"role": "user", "content": query}]
    })
    return Command(update={
        # 这是我们传回的示例状态键
        "example_state_key": result["example_state_key"],
        "messages": [
            ToolMessage(
                # 需包含工具调用 ID，以便与正确的工具调用匹配
                result["messages"][-1].text, tool_call_id=tool_call_id
            )
        ]
    })
```

## 交接控制

在**交接控制**模式中，智能体可直接将控制权传递给彼此。“活跃”智能体发生切换，用户与当前拥有控制权的智能体交互。

流程：

1. **当前智能体**判断需要另一智能体协助。
2. 它将控制权（及状态）传递给**下一智能体**。
3. **新智能体**直接与用户交互，直至决定再次交接或完成任务。

```mermaid theme={null}
graph LR
    A[用户] --> B[智能体 A]
    B --> C[智能体 B]
    C --> A
```

### 实现方式（即将推出）
