为什么需要多智能体


文档摘要

为什么需要多智能体 本节摘要:一个 Agent 撞墙时,最聪明的做法不是把它做得更大,而是把它拆成多个。本节从单 Agent 的三道天花板——上下文饱和、角色混乱、串行瓶颈——讲起,说明何时该从「一个全能 Agent」转向「一群专职 Agent」。我们将给出多智能体的四种基本拓扑(流水线、扇出/扇入、编排者-工人、对等集群),并在一个连续光谱上把它们定位清楚。最后用 TypeScript 从零实现一个过载单 Agent 与一个消息驱动的多 Agent 流水线做对比,让你亲眼看到「分而治之」带来的上下文洁净度收益,以及它必然带来的延迟与调试代价。读完本节,你能判断一个任务该不该上多智能体,以及该用哪种拓扑。

为什么需要多智能体

本节摘要:一个 Agent 撞墙时,最聪明的做法不是把它做得更大,而是把它拆成多个。本节从单 Agent 的三道天花板——上下文饱和、角色混乱、串行瓶颈——讲起,说明何时该从「一个全能 Agent」转向「一群专职 Agent」。我们将给出多智能体的四种基本拓扑(流水线、扇出/扇入、编排者-工人、对等集群),并在一个连续光谱上把它们定位清楚。最后用 TypeScript 从零实现一个过载单 Agent 与一个消息驱动的多 Agent 流水线做对比,让你亲眼看到「分而治之」带来的上下文洁净度收益,以及它必然带来的延迟与调试代价。读完本节,你能判断一个任务该不该上多智能体,以及该用哪种拓扑。

学习目标

阅读完本节,你应当能够:

  1. 识别单 Agent 的三道天花板(上下文饱和、角色混乱、串行瓶颈),并说明何时拆分为多 Agent 才是正解。
  2. 对比四种编排模式(流水线、扇出/扇入、编排者-工人、对等集群),针对给定任务结构选出合适的一种。
  3. 设计一个带清晰角色边界、共享状态、通信契约的多智能体系统。
  4. 量化多智能体复杂性(延迟、成本、调试难度)与单 Agent 简单性之间的权衡。

一、问题与直觉

你在第 14 章造出了一个单 Agent,它能读文件、跑命令、调 API、对结果做推理。然后你把它指向一个真实代码库:200 个文件、三种语言、依赖基础设施的测试,以及「先调研外部 API 才能写代码」的要求。

Agent 卡住了。不是因为 LLM 笨,而是任务超出了单个 Agent 循环能消化的范围。上下文窗口被文件内容塞满,它忘了 40 次工具调用前读过什么;它试图同时当研究员、程序员、评审员,三样都干不好。

这就是单 Agent 天花板。每当任务要求以下任一项,你都会撞上它:

  • 上下文超出单窗口容量——读 50 个文件就突破 20 万 token。
  • 不同阶段需要不同专长——研究所需的提示与代码生成不同。
  • 工作可以并行——既然三个文件能同时读,何必串行?

多智能体的解法

把工作拆开,给每个 Agent 一份工作、一个上下文窗口、一条为该工作调好的系统提示:

每个 Agent 拥有:聚焦的系统提示、独立的上下文窗口(不被他人工作污染)、清晰的输入输出契约。

真实系统

  • Claude Code 子 Agent:用 Task 派生子 Agent,父 Agent 保持上下文洁净,子 Agent 做聚焦工作后只回传摘要。
  • Devin:运行规划者、程序员、浏览器三个 Agent,各持独立上下文。
  • SWE-bench 多 Agent 团队:榜单前列的系统普遍采用「研究员读代码库 + 规划者设计修复 + 程序员实现」的组合,单 Agent 系统得分更低。
  • ChatGPT 深度研究:并行派出多个搜索 Agent,各探一个角度,再综合。

四种基本模式

反直觉点:多智能体是光谱而非开关——从「单 Agent」到「子 Agent」「流水线」「团队」「集群」,复杂性逐级上升。不要一上来就上集群,先确认你的任务真的需要那么大的协调开销。

何时不要用多智能体

每条 Agent 间消息都是一个潜在故障点,调试从「读一段对话」变成「在五个 Agent 间追踪消息」。

  • 保持单 Agent 的条件:任务塞得进一个上下文窗口(工作数据 < 10 万 token);不同阶段不需要不同系统提示;串行执行已足够快;任务简单到拆分得不偿失。
  • 复杂性代价:每个 Agent 边界都是一次有损压缩——A 的完整上下文被压成给 B 的消息;协调逻辑(谁、何时、以何顺序)本身就是 bug 源;延迟上升(最少 N 个串行 LLM 调用,有来回则更多);成本成倍(每个 Agent 独立烧 token)。

经验法则:若一个任务少于 20 次工具调用、塞得进 10 万 token,就保持单 Agent

二、从零实现

第一步:过载的单 Agent

一个试图包揽一切的单 Agent,系统提示臃肿,上下文里堆着研究、代码、评审:

type AgentResult = { content: string; tokensUsed: number; toolCalls: number }; async function singleAgentApproach(task: string): Promise<AgentResult> { const systemPrompt = `你是全栈开发者。你必须:1. 调研需求 2. 写代码 3. 评审 bug 4. 写测试。在一段对话里全做完。`; const contextWindow: string[] = []; let totalTokens = 0, totalToolCalls = 0; const research = await fakeLLMCall(systemPrompt, `调研: ${task}`); contextWindow.push(research.output); totalTokens += research.tokens; totalToolCalls += research.calls; const code = await fakeLLMCall(systemPrompt, `依据研究:\n${contextWindow.join("\n")}\n\n现在为以下写代码: ${task}`); contextWindow.push(code.output); // ... 评审同理,contextWindow 一路膨胀 return { content: contextWindow.join("\n---\n"), tokensUsed: totalTokens, toolCalls: totalToolCalls }; }

问题:上下文随阶段膨胀;系统提示通用,无法为每阶段调优;没有并行。

第二步:专职 Agent

拆分,每个 Agent 一份工作:

type SpecialistAgent = { name: string; systemPrompt: string; run: (input: string) => Promise<AgentResult> }; function createSpecialist(name: string, systemPrompt: string): SpecialistAgent { return { name, systemPrompt, run: async (input: string) => { const r = await fakeLLMCall(systemPrompt, input); return { content: r.output, tokensUsed: r.tokens, toolCalls: r.calls }; }, }; } const researcher = createSpecialist("researcher", "你是技术研究员。读文档、找模式、总结发现,只输出实现所需的事实。"); const coder = createSpecialist("coder", "你是资深 TypeScript 开发者。给定需求与研究,写干净、有测试的代码。仅此而已。"); const reviewer = createSpecialist("reviewer", "你是代码评审。找 bug、安全问题、逻辑错误。要具体,引用行号。");

第三步:用消息协调

type AgentMessage = { from: string; to: string; content: string; timestamp: number }; async function multiAgentApproach(task: string): Promise<AgentResult> { const messages: AgentMessage[] = []; let totalTokens = 0, totalToolCalls = 0; const researchResult = await researcher.run(task); messages.push({ from: "researcher", to: "coder", content: researchResult.content, timestamp: Date.now() }); totalTokens += researchResult.tokensUsed; totalToolCalls += researchResult.toolCalls; const coderInput = messages.filter(m => m.to === "coder") .map(m => `[来自 ${m.from}]: ${m.content}`).join("\n"); const codeResult = await coder.run(coderInput); // ... 评审同理 return { content: messages.map(m => `[${m.from} -> ${m.to}]: ${m.content}`).join("\n\n"), tokensUsed: totalTokens, toolCalls: totalToolCalls }; }

每个 Agent 只收到发给它的消息,没有上下文污染——研究员读的 5 万 token 文档永远不会进入评审员的上下文。

设计要点:多智能体的总 token 更多(三 Agent 三次独立调用),但每段上下文更干净、系统提示更专精,单阶段质量因此提升。这就是「多智能体难点在协调而非多」的根源——多出来的开销都花在协调上。

三、框架对比

框架 编排范式 适合 注意
Claude Code / Cursor 子 Agent 父子派发,父保规划、子做聚焦 通用开发任务,主上下文需保持洁净 子 Agent 只回传摘要,细节易丢
CrewAI 角色驱动(team、role、goal) 业务流程式任务,角色清晰 抽象偏「拟人化」,debug 时需穿透
AutoGen 对话式多 Agent,GroupChat 需要 Agent 间讨论/辩论 轮次难控,易陷入循环
LangGraph 显式状态图,节点=Agent、边=控制流 需要确定性、可恢复、可审计 学习曲线陡,需先建模状态机
OpenAI Swarm 轻量交接(handoff),无中心状态 无状态编排、快速原型 无内置持久化与容错

💡 选型心法:需要可审计性与恢复就选 LangGraph;需要快速角色化原型就选 CrewAI/Swarm;需要讨论与辩论就选 AutoGen。 别为一个 3 步流水线引入状态图框架——复杂度回报不成比例。

四、可复用产物

本节产出一份决策提示(原课程 outputs/prompt-multi-agent-decision.md):输入任务描述(预期上下文规模、阶段数、是否需并行、可靠度要求),输出「是否该上多智能体」以及推荐的拓扑与框架。把它接到你的任务评估流程里,可在动工前避免「一上来就集群」的过度工程。

五、练习

  1. 加测试员:新增第四个专职 Agent「tester」,接收来自 coder 的代码与 reviewer 的反馈,编写测试。
  2. 修订回路:改造流水线,使评审员能向程序员回送反馈形成修订循环(最多 2 轮),记录总轮次与最终质量。
  3. 扇出改造:把串行流水线改成扇出——研究员与「需求分析师」并行运行,合并输出后再交给程序员,对比延迟。
  4. 代价量化:对同一任务分别跑单 Agent 与多 Agent,记录总 token、总延迟、墙钟时间,计算「质量提升 ÷ 成本倍数」的性价比。
  5. 拓扑选择器:写一个函数,依据任务参数(预计工具调用数、阶段数、并行性)自动推荐四种拓扑之一,并用 5 个真实任务验证其推荐合理性。

本节要点回顾

  1. 单 Agent 有三道天花板:上下文饱和(细节丢失)、角色混乱(系统提示泛而平庸)、串行瓶颈(无吞吐)。
  2. 多智能体的解法是分工:每个 Agent 一份工作、一个干净上下文窗口、一条专精系统提示、一份输入输出契约。
  3. 多智能体是光谱:单 Agent → 子 Agent → 流水线 → 团队 → 集群,复杂性逐级上升,按需选取。
  4. 四种基本拓扑:流水线(串联)、扇出/扇入(并行分解再合并)、编排者-工人(中心派发)、对等集群(点对点、涌现行为)。
  5. 何时不要用:任务 < 20 次工具调用且 < 10 万 token 就保持单 Agent——多智能体的协调开销得不偿失。
  6. 代价:每条 Agent 边界都是有损压缩;协调逻辑本身是 bug 源;延迟随串行调用上升;成本随 Agent 数成倍增长。
  7. 真实系统印证:Claude Code 子 Agent、Devin、SWE-bench 多 Agent 团队、ChatGPT 深度研究,都在用分工换取质量。
  8. 核心心法:多智能体的难点不在「多」,而在「协调而不失控」——后面 24 节都是围绕这个「协调」展开。

下一节,我们将回到多智能体研究的源头——FIPA-ACL 与言语行为(Speech Acts)的理论遗产,理解「Agent 之间到底在说什么、怎么说」这一最古老却仍未过时的问题。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U