多智能体协作这个话题,最近聊的人越来越多。但说实话,真正把多个LLM(大语言模型)串起来干活、让它们各自负责一块、最后拼出一个完整结果的项目,市面上成熟的参考并不多,大部分还停留在“调一个API、拼一个对话流”的阶段。今天这篇,我直接从我实际做的一个协作型多智能体系统出发,把任务怎么拆、角色怎么分、Agent之间怎么通信、怎么避免它们互相“甩锅”或者重复劳动,一一讲透。内容偏工程落地,适合已经在用LLM做应用的开发者,也适合想从单模型调用过渡到多Agent编排的产品和技术负责人。
1. 整体设计思路:为什么要“多个AI”而不是“一个更强AI”
1.1 单模型的天花板与多Agent的破局点
先聊一个最基础的问题:一个LLM已经能做很多事了,为什么还要搞出一堆Agent让它们协作?
我自己的体会是,单个模型在处理长链路、多步骤任务时,有几道明显的坎。第一是上下文长度的物理限制,你让一个模型同时当“规划者+执行者+质检者”,它很容易在写到一半的时候把最开始的约束条件给忘了,我实测下来,一个2万字的报告任务,单模型一口气写到后面,经常出现前后矛盾。第二是角色认知的混乱,一个模型同时要“严谨”又要“创造性发散”,本身就是互相打架的指令,你可能会让它先写初稿再自己审核,但模型受“自我美化”倾向影响,几乎很难找出自己生成的错误——这是目前所有LLM的通病。第三是单点故障,一次调用超时或解析失败,整个任务就卡死了。
多智能体系统解决的就是这三个问题。把大任务拆成若干子任务,每个子任务由一个专职的Agent负责,它的上下文窗口只需要关注自己这一亩三分地,token利用率大幅提升。角色分离后,可以专门用一个“批评型Agent”去挑“执行型Agent”的毛病,这比让同一个模型既当运动员又当裁判员要靠谱得多。而且每个Agent独立调用,挂了一个还可以重试或者换一个模型顶上,系统的鲁棒性明显更好。
1.2 三种主流协作模式的取舍
在我搭建系统之前,先梳理了目前业界常见的几种多Agent协作架构。不看清楚这几条路,后面很容易把自己绕进去。
- 管道式(Pipeline):A做完传给B,B做完传给C,像流水线一样。优点是逻辑清晰、好调试,缺点是下游Agent无法给上游反馈,任务一旦在中间环节出错,前面所有工作都得重来。适合步骤边界明确的任务,比如“数据采集→清洗→分析→生成报告”。
- 编排式(Orchestrator/Worker):由一个“主编排器”负责理解总任务、拆解子任务、分发给执行Agent,再汇总结果。这种模式最灵活,适合任务动态变化、无法预先确定流程的场景。代价是编排器本身可能成为瓶颈,它要处理的信息量最大。
- 对等协商式(Peer-to-Peer):所有Agent地位平等,通过消息传递互相协商、互相评审。比如三个Agent分别写方案,然后互相提意见再修改。这种模式最适合需要多轮头脑风暴、方案迭代的场景,但也是最容易失控的——Agent之间的对话可能发散,聊着聊着跑到十万八千里外。
考虑到我需要处理的任务类型以“内容创作”“数据分析”“代码开发”为主,这三种模式我都试过,最终采用的是“编排式为主、部分环节插入对等协商”的混合架构。总任务先由编排器规划,拆出若干子任务分发给对应角色的Agent,在“方案评审”阶段,再让两个执行Agent平行产出方案,由评审Agent从不同维度打分对比。这样既避免了纯管道式无法反馈的缺点,也规避了纯对等协商的失控风险。
1.3 “集中式编排+分布式执行”的架构蓝图
最终敲定的系统架构由四层构成。
- 任务解析层:接收用户原始请求,识别任务类型、提取约束条件(比如格式要求、字数限制、风格偏好),输出一份结构化的“任务规格书”。
- 规划编排层:根据任务规格书,调用一个“规划Agent”生成执行计划,包括需要哪些角色参与、每个角色的输入输出是什么、依赖关系如何。这一步是整个系统的核心大脑。
- 执行协作层:多个执行Agent并行或串行工作,通过统一的消息队列收发任务和结果。每个Agent有自己独立的系统提示词(System Prompt)和上下文管理策略。
- 评估反馈层:评审Agent检查执行结果,不符合要求则退回重做;同时所有执行过程会写入日志,供后续优化。
这几层之间通过标准化的JSON消息格式通信,每个消息都包含任务ID、发送者、接收者、内容主体和可选的附件引用。用JSON的好处是既方便解析,也方便记录和回放——出问题的时候,把整个消息链路翻出来一看,就知道是哪个环节掉链子了。
2. 角色定义与任务分工的实操要点
2.1 五类核心Agent角色的职责拆解
角色设计直接影响协作质量。我在系统里固定了五类角色,每次任务不一定都用上,但框架里都预留了位置。
规划Agent(Planner)负责把复杂任务拆成可执行的子任务。它的关键能力是“正确识别任务的依赖关系”——哪些步骤必须串行,哪些可以并行。比如生成一份行业分析报告,数据收集和框架设计可以并行,但最终的内容填充必须等这两步都完成后才能开始。我给规划Agent的指令里特别强调:“输出每个子任务的前置依赖项,如果没有依赖,标记为independent。”
执行Agent(Executor)是具体干活的。系统里同时存在多个执行Agent,按领域区分,比如“代码执行Agent”“文案撰写Agent”“数据分析Agent”。它们的系统提示词里包含领域专属知识和工作规范,上下文只保留与当前子任务相关的信息。
评审Agent(Critic)负责质量把关。它的系统提示词里有一条非常重要的要求:“必须基于客观标准而非主观偏好进行评价,必须指出具体问题而非泛泛而谈‘不够好’。”我后来给评审Agent设计了结构化的评审表单,每一项对应打分维度和改进建议,这样输出的评审意见才能被执行Agent有效利用。
检索/工具Agent(Tool Agent)负责调用外部工具——搜索引擎、知识库、代码解释器、数据库查询接口等,把外部世界的信息带进LLM的上下文。尤其在做时效性强的任务(比如行业动态分析)时,这个Agent必不可少,否则模型只能靠训练数据里的旧知识硬编。
汇总Agent(Summarizer)把多个执行Agent的结果整合成一份连贯的输出。它最容易被忽略,但实际做下来发现这一步极其关键。多个子任务的结果直接拼接经常出现风格不一致、重复内容、逻辑跳跃,汇总Agent要像主编一样做整合、润色、去重。
2.2 系统提示词设计的两个核心原则
角色定义的本质,是通过系统提示词给每个Agent划定“人设边界”。我踩过很多坑之后,总结出两条核心原则。
原则一:职责要“窄”而“深”,不要“宽”而“泛”。比如不要写“你是一个助手,协助用户完成各项任务”——这种提示词等于没有提示。正确写法是:“你负责将用户的需求拆解为不超过5个子任务,每个子任务必须包含输入、输出、依赖关系和验收标准。”这样Agent的注意力被锁定在拆分任务这件事上,输出的结果才稳定。
原则二:明确“不能做什么”比“能做什么”更重要。协作系统里最怕越界。我在每个执行Agent的提示词里都加了约束条款——“你只负责完成指定的子任务,不输出任务之外的额外建议,不评论其他模块的工作”。听起来很死板,但实测下来,加了这条之后,Agent之间的消息内容干净了很多,不再出现执行A任务时突然聊起B任务的情况。
2.3 任务拆解的粒度控制
任务拆多细,直接决定协作效率。拆得太粗,单个Agent的任务还是太重,解决不了上下文超限的问题;拆得太细,Agent之间的通信开销大得吓人,而且每一步都可能出错。
我总结了一个经验法则:子任务的规模以“输出物”来判断,而不是以“输入内容”来判断。如果一条任务要求的输出物是一个可以直接交付的完整模块(比如一个可运行的函数、一篇完整的章节),那这个粒度就合适。如果输出物还需要大量后续加工才能变成最终成果的一部分,那说明拆得太粗了。
另外一个重要经验是“任务依赖图”的维护。我让规划Agent在输出子任务列表时,同时输出一张依赖关系表。系统根据这张表决定执行顺序:无依赖的任务立即分发给空闲Agent,有依赖的任务等上游完成后自动触发。这套机制让我处理的并行效率提升了不少——原先串行要10分钟的任务,拆分并行后压到了4分钟。
3. 协作机制与通信协议的工程实现
3.1 标准化消息结构与状态机设计
多Agent系统最怕的一件事就是“消息满天飞、状态理不清”。在设计之初我就定了规矩:所有Agent之间的交互,必须通过统一的消息总线和标准化的消息结构,不搞点对点直连。
消息结构我参考了常见的任务管理系统,设计成下面这个JSON格式:
{ "message_id": "uuid", "task_id": "task-001", "msg_type": "task_assign | task_result | task_review | task_retry", "sender": "planner", "receiver": "executor_code", "payload": { "input_data": {...}, "context_ref": ["doc-001", "doc-002"] }, "timestamp": "2025-06-18T10:30:00Z" }消息类型统一定义为四种:任务分配(task_assign)、结果上报(task_result)、评审反馈(task_review)、重试要求(task_retry)。不允许出现这四种之外的“闲聊型”消息,这个限制有效地防止了Agent之间进行无关对话。
配合消息结构,我还给每个任务定义了清晰的状态机:pending(待执行)→ running(执行中)→ completed(已完成)→ reviewing(评审中)→ accepted(已验收)或 failed(失败)。任何时刻,系统的监控面板能显示每个任务当前处于哪个状态,哪一步卡住了、哪个Agent执行超时了,一目了然。
3.2 上下文隔离与共享记忆的平衡
多Agent系统里,上下文管理是我觉得难度最高的部分。每个Agent都要有“自己的上下文”,但又不能完全隔离——否则协作无从谈起。
我采用的方案是“双区上下文”结构。每个Agent的上下文中,第一部分是本地的、只属于自己的工作记忆,包括当前任务的输入、自己历史产出的中间结果;第二部分是通过消息总线获得的“共享信息”,包括其他Agent传来的结果摘要、评审意见的要点。
这里有一个极其关键的实现细节:传给Agent的消息内容不要原样全量带进上下文,必须先做截断或摘要。比如检索Agent查到10篇资料,每篇5000字,直接全塞给文案Agent的上下文,5万token直接爆掉。我加了一个“消息预处理模块”,所有跨Agent消息在进入对方上下文之前,先做一次针对性压缩——长文档截取关键段落、数据表格转成摘要、代码输出只保留最终结果和错误日志。
3.3 协调循环的实现:一个可复用的核心流程
整个系统的“心脏”是一个协调循环,我把它实现成了Python类,核心逻辑大概是下面这条链路:
class AgentCoordinator: def __init__(self, agents, message_queue): self.agents = agents # 角色名 -> Agent实例 self.queue = message_queue # 统一消息队列 self.task_status = {} # 任务状态追踪 def run(self, task_spec): plan = self.agents["planner"].execute(task_spec) for subtask in plan.subtasks: self.dispatch(subtask) # 按依赖关系分发任务 def dispatch(self, subtask): if self.dependencies_met(subtask): # 检查前置依赖 self.queue.send( receiver=subtask.assignee, msg_type="task_assign", payload=subtask ) else: self.waiting_list.append(subtask) # 等待依赖完成 def handle_result(self, message): subtask = message.payload review_msg = self.agents["critic"].execute(subtask) if review_msg.verdict == "pass": self.task_status[subtask.id] = "accepted" self.trigger_downstream(subtask) # 触发后续任务 else: self.agents[subtask.assignee].retry(subtask, review_msg)这段代码的精髓不在逻辑复杂度,而在于统一入口。所有消息都从队列进入,由协调器统一处理,这保证了系统的行为可以预测。我在实际项目里就是在这个框架上不断加功能——比如超时重试、失败降级、Agent池扩容——都不需要改动核心循环。
3.4 模型选型与成本控制经验
不同Agent用不同模型,这个思路看起来简单,但很多人在第一版就搞反了——所有Agent全用同一个最强模型,导致成本爆炸。
我的实践经验是:规划Agent和评审Agent用推理能力强的模型,执行Agent用性价比高的模型。规划需要理解复杂任务、梳理依赖,评审需要发现逻辑漏洞,这类Agent值得用更强的模型(比如带高级推理能力的);而执行Agent往往只是按规格书产出内容,中等能力的模型就能胜任,用便宜的那档能节约不少成本。我在实际项目里测算过,一档模型的成本差距可能达到3到5倍,如果系统里有5个执行Agent在跑,只把“动脑子”的环节用贵模型,“干体力活”的环节用便宜模型,整个系统成本直接下降了一半以上。
成本控制上还有一个容易被忽略的点:Token的消费大头往往不在内容本身,而在反复重试。一个子任务如果评审不通过重跑三次,成本就是原来的三倍。所以在评审Agent的设计上,我倾向于“严进宽出”——评审标准宁可苛刻一点,也不放水。表面上看重试更多了,实际上重试的原因更准确,不会出现“执行Agent改了半天、评审又不通过”的拉锯消耗。
4. 典型场景实战:让三个Agent协作完成一份行业分析报告
4.1 场景设定与任务拆解示例
空谈架构没有说服力,我拿一个实际跑通的场景来讲:生成一份关于“智能硬件市场趋势”的分析报告,要求包含市场数据、竞品动态、技术趋势和未来展望四个部分,全文8000字左右。
用户给的任务规格书大致是这样的:
- 任务类型:结构化长文生成
- 输出格式:Markdown文档,含小标题和数据引用标注
- 时间要求:总耗时不超过8分钟
- 质量要求:每个结论必须配数据或来源;不得输出编造的数据
这个任务如果丢给单Agent直接生成,大概率会出现两类问题:一是编造市场数据(模型幻觉),二是结构混乱、前后数据对不上。拆成多Agent之后就清晰了。
规划Agent生成的执行计划如下表所示:
| 子任务ID | 负责Agent | 输入 | 输出 | 依赖 |
|---|---|---|---|---|
| T1 | 检索Agent | 任务规格书 | 10条真实市场数据及来源 | 无 |
| T2 | 执行Agent(数据) | 任务规格书 | 包含数据标注的数据章节 | 无 |
| T3 | 执行Agent(竞品) | 任务规格书 | 竞品动态章节 | T1(需要数据源) |
| T4 | 执行Agent(技术) | 任务规格书 | 技术趋势章节 | 无 |
| T5 | 汇总Agent | T2/T3/T4的输出 | 整合后的完整报告 | T2、T3、T4 |
注意这里T2和T4没有依赖,系统会让它们并行执行,T3依赖T1的数据,所以检索Agent会先启动。这个依赖关系表就是前面说的“任务依赖图”的实际应用。
4.2 执行过程中的消息流转记录
我把一次真实运行的日志简化后贴出来,让大家直观感受消息是怎么流动的:
0:00:00规划Agent收到任务规格书,开始拆解。0:00:12规划Agent输出T1-T5共5个子任务及依赖表,发送给协调器。0:00:15协调器同时向检索Agent发送T1、向数据执行Agent发送T2、向技术执行Agent发送T4。核心思想:没有依赖的任务立刻并行启动,不浪费等待时间。
0:00:20检索Agent调用外部数据接口,返回了若干条市场数据,消息类型为task_result,附带了数据来源链接。同时数据执行Agent开始写“市场规模与增长”章节。
0:02:10数据执行Agent完成T2初稿,发送task_result给协调器。协调器将结果转发给评审Agent。
0:02:20评审Agent返回审查意见:“增长率的引用来源为2023年数据,时效性不足,需更新为最新年度版本。”协调器将消息类型改为task_retry,连同评审意见一起发回给数据执行Agent。
0:02:25数据执行Agent收到重试指令,修改数据来源,重新提交。这次评审通过了。
0:02:40检索Agent的T1也完成了,协调器立即触发T3(竞品执行Agent)——它的输入条件满足了。
0:04:30T3、T4完成,汇总Agent收到三份执行结果,开始整合。
0:06:05汇总Agent输出最终报告,评审Agent做全文终审,通过后发送给用户。
整个流程用时6分多钟,符合预期。期间检索失败重试了一次,数据章节评审打回了一次,都通过消息机制自动解决了,不需要人工介入。
4.3 这个案例里最值得借鉴的三个技巧
这个场景跑多了以后,我提炼出几个可以“抄作业”的点。
技巧一:检索Agent必须为下游Agent预留“数据标签”。检索Agent返回的数据如果只是堆在一起,执行Agent拿到之后容易张冠李戴。我的做法是让检索Agent对每条数据都附上“用途标签”,比如“用于市场规模段”“用于增长率段”。执行Agent拿到数据后直接对号入座,准确率高不少。
技巧二:评审意见必须结构化。我一开始让评审Agent自由输出意见,结果执行Agent经常看不明白。后来改成强制结构化输出:“问题定位在哪一段/哪个数据→问题类型是什么(事实性错误/逻辑矛盾/表达不清晰)→具体修改建议是什么”。执行Agent收到之后能直接照着改,不用再“猜”评审的心思。
技巧三:汇总Agent不能只拼接,要做“逻辑缝合”。多个执行Agent各自写章节,拼在一起经常出现两章之间重复引用同一句话、或者前后数据口径不一致。汇总Agent的提示词里我加了一条:“检查所有章节间是否存在重复描述或数据冲突,如有冲突,以评审Agent验证通过的数据为准。”
5. 避坑指南与问题排查实录
5.1 高频踩坑问题速查表
把多Agent系统从能跑到跑稳,中间要趟过不少坑。我把实际项目中遇到的高频问题整理成了一张速查表,碰到类似情况可以直接翻这张表。
| 问题现象 | 根因分析 | 解决建议 |
|---|---|---|
| 某个Agent回复超时,任务卡死 | 单次调用没有超时保护 | 为每次LLM调用设置超时时间,超时后自动重试或降级 |
| Agent之间互传消息越传越长 | 消息在传递过程中不断累积历史 | 跨Agent消息进入对方上下文前,强制做截断、摘要或只保留关键字段 |
| 评审Agent永远让重做,任务死循环 | 评审标准含糊,重试没有次数上限 | 设置最大重试次数(我常用2次),超过后上报人工或启用备用Agent |
| 两个执行Agent产出的内容相互矛盾 | 各自上下文不同,缺少共享约束 | 在任务规格书中加入“全局约束字段”,每个Agent的上下文中都注入该字段 |
| 某些Agent频繁编造数据 | 模型幻觉,尤其实时性强的数据 | 引入检索Agent提供真实数据源,并设定“无数据=不输出结论”的硬规则 |
| 并行任务多的时候,内容风格不统一 | 每个执行Agent的写作风格缺乏约束 | 在规划阶段由规划Agent生成一份“风格规范”,随任务消息附带给所有执行Agent |
5.2 三个让人头疼的深层问题
表格里是表象,我再展开讲三个让我真正头疼过的深层问题。
第一个是“上下文污染”问题。当Agent A处理任务时,它的上下文里带着任务的历史信息。任务结束以后,如果这个Agent实例被复用去处理一个完全不相关的任务,上一轮的信息就会污染下一轮。我一开始把Agent设计为长期驻留的长生命周期实例,结果第三个任务之后输出质量明显下降。解决办法是“实例池化、按需重启”——每个Agent实例在处理完一个任务后自动销毁,下一个任务从池里取新实例。虽然每次初始化有一点额外的token开销,但质量稳定性好太多。
第二个是“角色冲突”导致的评级失真。评审Agent由哪个模型担任其实很讲究。如果评审Agent由执行Agent同一个模型担任,它会对同类错误“眼熟”——同一个模型家族的逻辑缺陷很相似,彼此之间不容易发现。我做了一个对比试验:用同样一个执行Agent产出的带错误报告,分别让同一家族模型和不同家族模型评审,结果是不同家族模型发现错误的数量明显更多。所以有条件的话,评审Agent尽量选择与执行Agent不同的模型品牌,交叉验证更有效。
第三个是“协调器单点故障”。所有任务消息都通过协调器转发,协调器一旦异常,整个系统瘫痪。我的方案是在协调器侧做“降级开关”——协调器挂了自动切换到“直连模式”,各Agent之间退化为点对点通信,虽然失去了统一调度,但至少核心任务还能继续跑。这个设计让我在实际演示的时候避免过一次尴尬场面。
5.3 超时、重试与并发控制的调参经验
最后聊几个实在的参数调优经验,这些数字都是我反复试错得来的,不一定适合所有场景,但可以作为起点参考。
- 单次LLM调用超时:我设置为90秒。太短容易误杀复杂任务,太长会导致系统卡顿感知明显。
- 任务整体超时:按任务复杂度分三档——简单任务2分钟、中等任务5分钟、复杂任务15分钟。超时后强制中断并通知用户,避免无限挂起。
- 最大重试次数:单子任务最多重试2次。超过之后自动“降级处理”——调低评审标准、请求人工介入或者跳过该子任务。我的实测数据是,重试超过2次后成功率提升有限,继续耗下去性价比极低。
- 并发Agent数:我常用的并发上限是5个。并发加到8到10个的时候,整体吞吐量提升不明显,但token消耗和API限流风险大幅上升。峰值时段还会触发限流重试,白白增加延迟。
一个比较反直觉的经验是:重试间隔不要用固定等待,要用指数退避。我一开始重试失败后立刻再试,结果连续三次都被限流;改成指数退避(1秒、2秒、4秒……)之后,重试成功率提升显著,而且不会给API服务方造成压力。
6. 实操心得:多Agent系统后续可以这样扩展
做到现在这个程度,我再往后想了几步,有些已经试验过,有些还在规划,分享给你参考。
第一个扩展方向是“Agent能力配置的外部化”。目前灵活性还不够的原因是Agent的角色和提示词都硬编码在代码里。我下一步准备把提示词模板、模型选择、温度参数、上下文窗口大小等全部做成可配置的YAML配置文件——这样调整一个Agent的行为不用改代码,改配置文件就能热更新。已经在做,初步效果不错。
第二个方向是“记忆系统的持久化”。当前系统虽然避免了上下文污染,但代价是每个任务都从零开始,缺少跨任务的积累。我计划引入一个外部向量数据库,把每次任务中评审Agent通过的“高质量产出摘要”存下来,后续类似任务可以直接从记忆中调取经验,而不是每次重新生成。这个方向的挑战在于如何判断哪些内容值得进入长期记忆,避免存进去一堆噪音。我的初步想法是让评审Agent同时给产出打“可复用性”标签,只有高可复用性的内容才写入记忆库。
第三个方向是“混合人工协作”。纯自动化的Agent系统在关键节点仍然需要人的决策,比如重大方案的拍板、对外报告终审。我计划加入“人工介入节点”——在流程图中标注哪些环节需要人审批,Agent任务到这一步就挂起,等待人工确认后继续。这个机制已经在线上一个小范围灰度测试,效果不错,尤其是团队里有明确的责任人对最终输出负责的场景下,人工介入反而提升了整个链条的信任度。
以我个人的实际经验来说,多Agent系统的开发路径和传统的单模型应用开发差别很大——与其说它是“调接口”,不如说它更像“带团队”。你要定义清楚每个Agent的职责边界、沟通语言、质量标准和应对异常的策略。这个体系一旦跑顺,带来的增益是实打实的:同样的任务,从原来单模型靠运气出质量,变成了一套可控、可追踪、可迭代的工程化流程。如果你正在做类似的方向,欢迎把你在实践中遇到的坑和经验也分享出来,这一块远没到成熟期,值得一起趟。