多智能体系统将复杂应用程序分解为多个协同工作以解决问题的专门智能体。 多智能体架构允许您将较小的、专注的智能体组合成协调的工作流程,而不是依赖单个智能体来处理每个步骤。 多智能体系统在以下情况下很有用:
  • 单个智能体有太多工具,并且在选择使用哪个工具方面做出糟糕的决策。
  • 上下文或记忆对于一个智能体来说太大而无法有效跟踪。
  • 任务需要专业化(例如,规划者、研究者、数学专家)。

多智能体模式

模式工作原理控制流示例用例
工具调用监督者智能体将其他智能体作为工具调用。“工具”智能体不直接与用户交谈 — 它们只是运行其任务并返回结果。集中式:所有路由都通过调用智能体。任务编排、结构化工作流程。
交接当前智能体决定转移控制到另一个智能体。活动智能体改变,用户可以继续直接与新智能体交互。分散式:智能体可以更改谁处于活动状态。多领域对话、专家接管。

教程:构建监督者智能体

学习如何使用监督者模式构建个人助理,其中中央监督者智能体协调专门的工作者智能体。 本教程演示:
  • 为不同领域(日历和电子邮件)创建专门的子智能体
  • 将子智能体包装为工具以实现集中编排
  • 为敏感操作添加人在回路审查

选择模式

问题工具调用交接
需要对工作流程进行集中控制?✅ 是❌ 否
希望智能体直接与用户交互?❌ 否✅ 是
专家之间的复杂的、类似人类的对话?❌ 有限✅ 强
您可以混合使用两种模式 — 使用交接进行智能体切换,并让每个智能体将子智能体作为工具调用以执行专门任务。

自定义智能体上下文

多智能体设计的核心是上下文工程 - 决定每个智能体看到什么信息。LangChain 为您提供精细控制:
  • 将对话或状态的哪些部分传递给每个智能体。
  • 为子智能体量身定制的专门提示。
  • 包含/排除中间推理。
  • 为每个智能体自定义输入/输出格式。
您的系统质量严重依赖上下文工程。目标是确保每个智能体都可以访问执行其任务所需的正确数据,无论它是作为工具还是作为活动智能体。

工具调用

工具调用中,一个智能体(“控制器”)将其他智能体视为需要时调用的工具。控制器管理编排,而工具智能体执行特定任务并返回结果。 流程:
  1. 控制器接收输入并决定调用哪个工具(子智能体)。
  2. 工具智能体根据控制器的指令运行其任务。
  3. 工具智能体将结果返回给控制器。
  4. 控制器决定下一步或完成。
Agents used as tools are generally not expected to continue conversation with the user. Their role is to perform a task and return results to the controller agent. If you need subagents to be able to converse with the user, use handoffs instead.

实现

下面是一个最小示例,其中主智能体通过工具定义获得对单个子智能体的访问权限:
from langchain.tools import tool
from langchain.agents import create_agent


subagent1 = create_agent(model="...", tools=[...])

@tool(
    "subagent1_name",
    description="subagent1_description"
)
def call_subagent1(query: str):
    result = subagent1.invoke({
        "messages": [{"role": "user", "content": query}]
    })
    return result["messages"][-1].content

agent = create_agent(model="...", tools=[call_subagent1])
In this pattern:
  1. The main agent invokes call_subagent1 when it decides the task matches the subagent’s description.
  2. The subagent runs independently and returns its result.
  3. The main agent receives the result and continues orchestration.

自定义位置

有几个点可以控制上下文在主智能体及其子智能体之间传递的方式:
  1. 子智能体名称 ("subagent1_name"):这是主智能体引用子智能体的方式。由于它影响提示,请仔细选择。
  2. 子智能体描述 ("subagent1_description"):这是主智能体对子智能体的”了解”。它直接影响主智能体决定何时调用它。
  3. 子智能体的输入:您可以自定义此输入,以更好地塑造子智能体如何解释任务。在上面的示例中,我们直接传递智能体生成的 query
  4. 子智能体的输出:这是传递回主智能体的响应。您可以调整返回的内容以控制主智能体如何解释结果。在上面的示例中,我们返回最终消息文本,但您可以返回其他状态或元数据。

控制子智能体的输入

有两个主要杠杆可以控制主智能体传递给子智能体的输入:
  • 修改提示 – 调整主智能体的提示或工具元数据(即子智能体的名称和描述),以更好地指导何时以及如何调用子智能体。
  • 上下文注入 – 通过调整工具调用从智能体状态中提取,添加在静态提示中无法实际捕获的输入(例如,完整消息历史、先前结果、任务元数据)。
from langchain.agents import AgentState
from langchain.tools import tool, ToolRuntime

class CustomState(AgentState):
    example_state_key: str

@tool(
    "subagent1_name",
    description="subagent1_description"
)
def call_subagent1(query: str, runtime: ToolRuntime[None, CustomState]):
    # Apply any logic needed to transform the messages into a suitable input
    subagent_input = some_logic(query, runtime.state["messages"])
    result = subagent1.invoke({
        "messages": subagent_input,
        # You could also pass other state keys here as needed.
        # Make sure to define these in both the main and subagent's
        # state schemas.
        "example_state_key": runtime.state["example_state_key"]
    })
    return result["messages"][-1].content

控制子智能体的输出

塑造主智能体从子智能体接收内容的两种常见策略:
  • 修改提示 – 优化子智能体的提示,以精确指定应返回的内容。
    • 当输出不完整、过于冗长或缺少关键细节时很有用。
    • 一个常见的失败模式是子智能体执行工具调用或推理,但未在其最终消息中包含结果。提醒它控制器(和用户)只能看到最终输出,因此所有相关信息必须包含在那里。
  • 自定义输出格式 – 在将子智能体的响应返回给主智能体之前,在代码中调整或丰富它。
    • 示例:除了最终文本之外,还将特定状态键传递回主智能体。
    • 这需要将结果包装在 Command(或等效结构)中,以便您可以将自定义状态与子智能体的响应合并。
from typing import Annotated
from langchain.agents import AgentState
from langchain.tools import InjectedToolCallId
from langgraph.types import Command


@tool(
    "subagent1_name",
    description="subagent1_description"
)
# We need to pass the `tool_call_id` to the sub agent so it can use it to respond with the tool call result
def call_subagent1(
    query: str,
    tool_call_id: Annotated[str, InjectedToolCallId],
# You need to return a `Command` object to include more than just a final tool call
) -> Command:
    result = subagent1.invoke({
        "messages": [{"role": "user", "content": query}]
    })
    return Command(update={
        # This is the example state key we are passing back
        "example_state_key": result["example_state_key"],
        "messages": [
            ToolMessage(
                content=result["messages"][-1].content,
                # We need to include the tool call id so it matches up with the right tool call
                tool_call_id=tool_call_id
            )
        ]
    })

交接

交接中,智能体可以直接将控制权传递给彼此。“活动”智能体会发生变化,用户与当前拥有控制权的智能体交互。 流程:
  1. 当前智能体决定需要另一个智能体的帮助。
  2. 它将控制权(和状态)传递给下一个智能体
  3. 新智能体直接与用户交互,直到它决定再次交接或完成。

实现(即将推出)


Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.