从单 Agent 到多 Agent
要点
- 先把「单 Agent」想成一个总负责人
- 新手最容易犯的一个错误,是还没把需求做清楚,就先把系统拆得很复杂
- 单 Agent 不是不能做复杂事,而是事情一多,它会越来越像一个什么都要管的全能员工
- 很多人第一次听到「多 Agent」时,会误以为它的重点是「让系统更聪明」
- 这里不讲抽象判断,直接看工程里的几个信号
内容
1. 先看一个真实场景
假设我们正在做一个「AI 电子伴侣」应用。
用户晚上回家后发来一条消息:
NOTE
我明天上午十点开会,你提醒我一下。还有,我前几天提到的那家餐厅叫什么来着?
这条消息看起来很短,实际上里面混了两件事:
- 一件是「提醒我开会」:需要写入日程
- 一件是「那家餐厅叫什么」:需要去历史记录里找答案
如果系统还比较简单,我们完全可以只用一个 Agent 来处理。这个 Agent 身上挂几个工具:
- 一个查记忆的工具
- 一个写日程的工具
- 一个普通对话模型
收到消息后,它自己判断要不要查工具、先查哪个、最后怎么组织回复。这就是「单 Agent」方案。
很多入门项目到这一步就已经能工作了,而且效果并不差。
2. 单 Agent 是怎么工作的
先把「单 Agent」想成一个总负责人。
用户说的话先交给这一个 Agent,它来做全部判断:
- 先看用户在问什么
- 判断需不需要调用工具
- 如果需要,就自己去调工具
- 拿到工具结果后,再决定下一步
- 最后生成回复
代码层面,它通常长这样:
// index.ts
import { createAgent, tool } from 'langchain'
import * as z from 'zod'
const searchMemory = tool(
async ({ query }) => `用户上周提到的餐厅是「山野食堂」`,
{
name: 'search_memory',
description: '从历史记忆中搜索信息',
schema: z.object({
query: z.string(),
}),
}
)
const createReminder = tool(
async ({ title, time }) => `已创建提醒:${time} ${title}`,
{
name: 'create_reminder',
description: '创建提醒事项',
schema: z.object({
title: z.string(),
time: z.string(),
}),
}
)
const agent = createAgent({
model: 'openai:gpt-4.1-mini',
tools: [searchMemory, createReminder],
systemPrompt: '你是一个陪伴型助手,回答要自然、简洁。',
})
const result = await agent.invoke({
messages: [
{
role: 'user',
content: '提醒我明天上午十点开会,再告诉我上周那家餐厅叫什么。',
},
],
})
console.log(result.messages.at(-1)?.content)这套结构很好理解。所有事情都交给一个 Agent,它像一个「总控台」:
- 既负责理解用户意图
- 也负责决定是否调用工具
- 还负责把最终结果说出来
刚开始做项目时,这种方式最省事。因为你只要把工具准备好,再把 Agent 的角色设定好,就能很快跑起来。
3. 为什么很多项目一开始都应该先用单 Agent
新手最容易犯的一个错误,是还没把需求做清楚,就先把系统拆得很复杂。
但在真实开发里,很多需求其实并没有复杂到要上多 Agent。
还是用刚才那个 AI 伴侣的例子。如果系统目前只做下面几件事:
- 陪用户聊天
- 查一查历史记忆
- 写一下提醒事项
- 偶尔查天气
那单 Agent 已经够用了。
原因很简单。
第一,链路短。
用户发消息后,通常只需要一两次工具调用就能结束,不需要长流程编排。
第二,状态少。
大部分信息都可以放在当前对话上下文里,不需要跨很多步骤保存中间状态。
第三,开发成本低。
你只要维护一个 Agent 的角色、Prompt 和工具列表,不需要额外设计角色分工。
第四,问题更容易排查。
如果输出不对,你只需要检查这一个 Agent 的 Prompt、输入、工具结果和模型回复。
这个阶段的系统结构,大致像这样:
Drawing canvas 上面第一张图就是单 Agent 的典型结构:用户请求先进入一个总 Agent,再由它决定要不要去调记忆、日程、天气这些工具。
4. 单 Agent 从什么时候开始吃力
单 Agent 不是不能做复杂事,而是事情一多,它会越来越像一个什么都要管的全能员工。
还是沿着 AI 伴侣这个场景继续往下加需求:
- 用户发来的消息先要做安全检查
- 然后要判断这条消息是聊天、记忆写入,还是日程类请求
- 如果提到了旧话题,要先查长期记忆
- 如果涉及提醒,要再走日程写入
- 如果是敏感话题,还要切换特殊回复策略
这时问题就出来了。
问题 1:一个 Agent 身上的职责开始变得太多。
原来它只负责聊天和简单工具调用。现在它还要同时承担:
- 分类
- 路由
- 安全判断
- 工具调度
- 最终回复生成
职责一多,Prompt 就会越来越长,工具也会越来越多。
问题 2:它知道的东西越来越杂。
这个 Agent 既要知道怎么安抚情绪,又要知道怎么查记忆,还要知道什么时候去写日程。每一类任务的规则都堆在一起,模型更容易判断失误。
问题 3:排查问题越来越难。
一旦结果不对,你很难立刻判断是:
- 分类错了
- 工具选错了
- 记忆没取对
- 还是最后生成回复时把信息说乱了
问题 4:流程开始变长。
有些请求不再是一问一答,而是一个多步骤流程。比如:
- 先做安全检查
- 再做意图判断
- 再决定是否查记忆
- 再决定是否写入外部系统
- 最后才生成回复
到了这个阶段,继续让一个 Agent 全包,代码还能写,但系统会越来越别扭。
这里要分清两件事。
第一件事是:流程本身变复杂了。
这时候最先出现的,往往是编排和状态管理问题。比如步骤怎么排序,中间结果怎么保存,某一步失败后从哪里继续。
第二件事是:职责是否真的需要拆开。
如果只是流程长了一点,但仍然可以由一个 Agent 清楚地处理,那未必需要立刻上多 Agent。很多时候,先把工作流和状态管理理顺,问题就已经解决了一大半。
5. 多 Agent 不是更高级,而是开始分工
很多人第一次听到「多 Agent」时,会误以为它的重点是「让系统更聪明」。其实更准确的说法是:
多 Agent 的重点是分工。
Canvas actions99%Exit zen mode
Drawing canvas 还是刚才那套 AI 伴侣需求,如果改成多 Agent,可以拆成这样:
- 一个
router agent:先判断这条消息属于哪一类任务 - 一个
memory agent:专门处理记忆检索和记忆写入 - 一个
schedule agent:专门处理日程和提醒 - 一个
companion agent:负责最后的对话输出
这时每个 Agent 只管自己最擅长的一部分。
这样拆开后,最大的变化不是「每个 Agent 都更强」,而是系统结构变清楚了:
- 谁负责分类
- 谁负责查历史
- 谁负责写外部系统
- 谁负责面向用户说话
上面第二张图就是这种结构。用户请求先进入路由节点,再被分发给不同的专职 Agent。处理完以后,再把结果汇总回来。
这时候你会发现,多 Agent 更像是把一个大而全的总负责人,拆成几个职责明确的小角色。
不过这里也不要理解得太绝对。
当单 Agent 开始变重时,常见的演进方向之一确实是多 Agent。但不是所有复杂问题都必须拆成多个独立 Agent。有些项目只是工具变多了,或者流程变长了,这时先做更清晰的工作流编排、工具分组、上下文裁剪,也可能已经够用。
所以这一节真正想说明的是:
- 当职责明显混在一起时,可以考虑多 Agent
- 当问题主要是流程长、状态多时,先把编排问题解决清楚
6. 怎么判断当前项目该停在单 Agent,还是该进入多 Agent
这里不讲抽象判断,直接看工程里的几个信号。
如果你现在的项目有下面这些特点,先用单 Agent 更合适:
- 工具数量不多,通常在 3 到 5 个以内
- 大多数请求都能在一轮内处理完
- 没有特别复杂的状态流转
- 你现在最重要的目标是先把产品跑起来
如果你开始频繁遇到下面这些情况,就要考虑多 Agent 了:
- 一个 Agent 的 Prompt 已经越来越长
- 工具越来越多,模型经常选错工具
- 一条请求经常要经过多个阶段
- 不同类型任务混在一起,代码越来越难维护
- 你需要单独观察某一个角色或某一类任务的表现
这不是二选一的价值判断,而是系统规模变化后的自然结果。
单 Agent 更像一个「全能助手」。
多 Agent 更像一个「分工明确的小团队」。
项目早期,先把全能助手做好,通常更稳。
项目长到一定阶段,再把它拆成团队,才有意义。
7. 总结
本文只解决一个问题:
为什么系统会从单 Agent 逐渐走向多 Agent。
下一步我们会继续把边界讲清楚:
LangChain主要负责把「单个 Agent + 多工具」这条主线搭起来LangGraph更适合承接「多 Agent + 状态流转 + 多步骤流程」这类系统问题