2026年这一波工业智能体从概念演示走向工程化落地,圈里人真正开始较劲的其实是同一件事:多个大模型Agent怎么在一块儿干活。单Agent的天花板很明显——上下文窗口有限、单点决策容易偏、工具一多就手忙脚乱,于是“多Agent智能体架构”几乎成了复杂场景的必选项。但很多团队把多Agent做成了灾难:Agent之间互相踢皮球、消息风暴打爆token预算、任务拆了合不回去。这篇文章我把自己的多Agent架构设计思路完整铺开,从底层逻辑到协作模式再到工程落地,最后附上真实踩坑记录。正在做Agent应用、AI平台架构或者准备多Agent面试的人,都可以直接拿去做参考。
1. 为什么单Agent撑不住复杂场景
1.1 单Agent的三个天花板
先说个反常识的结论:大多数业务场景根本不需要多Agent,单Agent加一堆工具就能跑。但复杂场景里,单Agent会撞上三个硬天花板。
第一个是上下文窗口的天花板。一个Agent干完一整条业务链,意味着它要在记忆里同时塞下用户需求、中间结果、工具返回、历史决策。GPT-4级别的128K上下文看着很大,真实跑起来根本不够用。我做过一个供应链比价Agent,光是解析20份供应商报价单的结构化数据就得吃掉60K token,后面还要比价、谈判、出报告,整个流程跑到一半就开始“忘事儿”,早期版本经常出现后段步骤引用了错误的价格数据,把整个决策链污染掉。
第二个是工具调用的可靠性天花板。单Agent调用工具,本质上是在超长序列里做多步推理和动作。步骤越长,模型在中间某一步选错工具、传错参数的概率就越大。而且错误是累积的——第一步传错一个参数,后面十步可能全错,还很难定位是哪一步错的,因为日志里呈现的就是一堆Agent自言自语。
第三个是职责耦合的天花板。业务系统里天然存在不同角色,采购Agent要懂供应链,财务Agent要懂付款合规,法务Agent要懂合同条款。硬塞进一个Agent,要么提示词膨胀到几万字,要么某个专业能力被另一个专业需求稀释。我见过有人把采购、财务、法务规则全写进一个system prompt,结果模型在各种规则之间反复摇摆,遇到稍微模糊一点的判断就犯傻。这不是模型不行,是架构问题。
1.2 多Agent架构的本质:拆与合
多Agent真正的设计核心不是“多个Agent”,而是“拆”和“合”这两件事。
“拆”是把一个大而全的Agent拆成多个小而专的Agent,每个Agent负责一个边界清晰、职责单一的子任务。拆分的依据是知识域和工具域,不是功能碎片。一个订单处理Agent,拆成“订单解析Agent”和“订单履约Agent”是合理的,因为一个吃文本理解、一个吃库存系统和物流API。但拆成“订单编号处理Agent”和“订单金额处理Agent”就是灾难,因为这两个功能共享同一个输入上下文,强行拆开反而引入更多通信开销和出错点。
“合”是设计一套调度与协作机制,让多个Agent像一个整体一样工作。合的方式决定了架构的宏观形态:是中心化调度还是去中心化自组织,是严格流水线还是动态编排,是单向传数据还是双向多轮交互。这部分没有统一答案,取决于业务场景的耦合程度和容错要求。但有一个原则是通用的:多Agent系统的复杂度不是来自Agent本身,而是来自Agent之间的交互关系,所以“合”的机制越简单、越可预测,系统就越稳。
我在实际项目里总结过一个判断标准:如果一个任务写进单Agent提示词后,prompt超过8000字,或者工具数量超过15个,或者流程步骤超过10步,就应该认真考虑多Agent结构了。这几个数字不是拍脑袋,而是来自对多套系统运行表现的观察——超过这些阈值后,单Agent的错误率和调试复杂度会急剧上升,重构收益非常明显。
2. 多Agent架构的四层核心设计
2.1 协调层:一切复杂度的源头
协调层是多Agent架构的大脑,负责任务分解、Agent调度和结果仲裁。这个层的设计质量直接决定整个系统的行为表现。
最常见的协调模式是中心调度器模式:一个中央Planner接收用户请求,把任务拆成子任务,分发给各个Worker Agent,最后收集结果统一汇总。这个模式适合任务边界清晰、执行顺序相对固定的场景。Planner本身也是一个大模型Agent,但它不是用来执行任务的,而是用来做规划的。Planner的prompt应该聚焦任务拆解策略,不掺入任何领域业务规则,领域规则全部下沉到Worker层,否则Planner的决策会被无关信息干扰。
协调层必须解决的问题是任务依赖关系的建模。任务之间可能是顺序依赖(A完成才能做B)、并行独立(A和B可以同时跑)、条件分支(根据A的结果决定是否跑B)。我建议在协调层为每个子任务显式声明依赖,而不是让Agent自己推断依赖。原因是模型推断依赖关系天然不可靠,尤其在信息不完全的时候。显式声明之后,调度器实际上就是一个有向无环图(DAG)执行引擎,谁依赖谁、谁可以并行,一目了然,也方便做超时控制和失败重试。
2.2 执行层:技能Agent的封装逻辑
执行层的Agent我习惯叫“技能Agent”,每个Agent封装一个独立的能力域,通过工具或外部API与真实世界交互。设计技能Agent的核心不是写提示词,而是定义清晰的接口契约。
每个技能Agent要回答四个问题:输入是什么格式、输出是什么格式、调用什么工具、失败如何返回。这四个答案全部写进Agent配置里,而不是藏在对话上下文里。我常用工具描述(function calling)的方式直接定义接口,让Agent通过工具调用暴露能力,而不是输出一段自然语言文本。原因很现实:自然语言输出无法校验,也无法被程序化消费。比如“订单总结Agent”如果返回一段散文,下游Agent需要二次解析才能用,解析失败率高还难排查。但如果它通过一个结构化JSON工具返回订单号、金额、状态三个字段,下游Agent直接读字段就行,错误率能降一个数量级。
技能Agent的prompt应该保持精简,一般控制在800到1500字。超过这个篇幅说明Agent的职责边界没划清楚,该继续拆。我见过一个团队把几十条业务规则塞进单个Agent,结果模型每轮调用都要消化大量规则,响应变慢且判断漂移,最后拆成三个Agent后各司其职,问题立刻消失。
2.3 记忆与状态层:最容易翻车的部分
多Agent系统的记忆层比单Agent复杂得多,因为它不仅要存“每个Agent自己的记忆”,还要管“Agent之间的共享状态”。
我建议采用分层记忆:短期记忆(当前任务的对话上下文)、长期记忆(跨任务的关键事实与偏好)、共享状态(任务全局信息,所有Agent都可读)。三层之间严格区分存储和读写权限,不要把短期记忆直接写进长期记忆,也不要把全局信息塞进单个Agent的上下文。
共享状态这块,我用的是“黑板模式”:一个全局状态存储,记录当前任务的阶段、中间产物、关键决策和状态标记,所有Agent可以读取,只有协调层可以写入。这样做的好处是状态一致性和通信间解耦。Agent之间不需要直接传递消息,而是通过读写黑板间接协作,交互复杂度大幅下降。坏处是黑板模式要求数据结构高度规范化,不能让Agent随便往上面写自由文本,否则各Agent读到的格式都不一样,等于又回到了通信混乱状态。
2.4 通信层:少一点比多一点好
多Agent之间的通信协议设计,核心原则就是四个字:能少则少。很多架构失败不是通信太少,而是通信太多。Agent之间发消息没有成本,模型来回阅读消息消耗的就是token和注意力,消息一多就容易互相干扰、产生幻觉式回应。
我把通信分成两个层级:数据流和事件流。数据流是任务执行方向上的结构化产物传递,比如订单解析Agent产出结构化订单数据传给履约Agent。数据流必须走结构化协议(JSON或工具调用),不能用自然语言。事件流是状态与异常通知,比如某个Agent任务完成、失败、超时。事件流走轻量信号,可以只包含事件类型和关联ID,不需要携带大段内容。
同时通信层要设置上限。我给每个Agent每轮执行的任务设定了10条消息配额,超过配额直接终止并上报协调层。这个配额不是凭空定的,是根据多次运行统计得出的——正常情况下,一个子任务完成需要的通信次数远低于10条,如果超过说明Agent在空转或者陷入无效对话,及时止损比让它们继续聊下去更划算。
3. 多Agent协作模式与编排范式
3.1 主从协调模式:最稳妥的默认选择
主从协调模式(Orchestrator-Workers)是当前多Agent应用最广泛的结构。一个中心Planner负责全局,多个Worker各自执行,结果回传后由Planner汇总或继续下一步。
这个模式的优势是简单、可控、易诊断。所有决策都经过Planner,行为路径清晰,出问题可以顺着调用链回溯。劣势是Planner可能成为性能瓶颈,而且Planner本身也是个Agent,它一旦规划错了全局就跟着错。
伪代码大致长这样:
class Orchestrator: def run(self, user_request): # 1. 任务分解:把用户请求转为子任务列表 tasks = self.plan(user_request) # 2. 构建DAG:声明依赖关系与并行分支 dag = self.build_dag(tasks) # 3. 调度执行:按拓扑序分发子任务 results = {} for batch in topo_layers(dag): # 并行执行无依赖的子任务 batch_results = parallel_run(batch, worker_pool) results.update(batch_results) # 4. 结果仲裁与汇总 final_answer = self.aggregate(results) return final_answer实际落地时,我给Orchestrator加了一层规划缓存。常见请求类型的任务分解结果是可以复用的,比如“分析一份合同并生成摘要”,这类任务的子任务序列基本固定。让Planner每次从头规划既费token又容易不稳定,所以我在前面加了一个模板匹配层——命中模板就直接走预定义的DAG,匹配不到才让Planner动态规划。实测下来,规划这一步的耗时和token消耗能降60%以上,稳定性还更好。
3.2 流水线模式:前店后厂的线性协作
流水线模式适合任务有明确先后阶段、每个阶段产出是下一阶段输入的场景。本质上是一条单向数据流管道,每个节点是一个技能Agent。
流水线的设计关键在节点粒度和数据契约。节点粒度太粗,单个Agent负担过重,退化回单Agent问题;粒度太细,流水线层数太多,延迟和出错概率上升。我的实践准则是:一个节点做一类“原子能力”,比如“OCR文字提取”“信息结构化”“风控规则校验”“输出生成”,每个节点对应一个可独立测试的模块。数据契约就是节点间的结构化格式,必须在前置设计阶段敲死,不能在实现中让两边Agent“自由协商”。
流水线模式的最大好处是可观测性强。每个节点的输入输出都是确定性的,可以单独记录、插桩、回放。出了问题直接定位到具体环节,不像主从模式那样需要在Planner的决策迷宫里分析。代价是灵活性差,无法处理循环、回溯和动态分支。所以流水线适合那些业务流程高度稳定的场景——典型如文档审核、报表生成、内容审批流。
3.3 评审纠错模式:让Agent互相挑毛病
评审纠错模式是提升输出质量的一招,核心是引入“生成Agent”和“评审Agent”两个角色。生成Agent负责产出初稿,评审Agent负责按规则检查并给出修改意见,二者循环多轮直到评审通过。
这里有个细节容易被忽视:评审Agent必须拿到明确的评审标准,而不是“你看看哪里不对”。我以前让评审Agent自由发挥挑错,结果它经常提出风格偏好类的修改建议,和业务需求无关,甚至为了显得自己有用而强行改稿。后来我把评审标准固化为结构化清单,比如“是否包含必要字段”“金额计算是否一致”“结论是否有数据支撑”,评审Agent按清单逐项打分并输出问题列表,生成Agent再按问题列表定向修改。效果立竿见影,不仅质量提升,评审轮次也从平均5轮回落到2轮以内。
这个模式适合质检、内容生成、代码审查等需要可靠性的场景,但成本比单Agent高不少,因为每一轮生成和评审都是完整的大模型调用。我的建议是给评审设一个最大轮数——比如3轮,超过就终止并走人工兜底,防止两个Agent陷入“改来改去”的无限循环,既烧钱又出不来结果。
3.4 动态自组织模式:高阶玩法,慎用
动态自组织模式没有中心调度器,Agent之间通过消息协商任务分配,谁擅长什么谁就认领。这个模式最接近“多智能体系统”的理想形态,但工程上非常难控制。
我试过让多个Agent自主协商任务分工,结果是有趣但不可靠。Agent经常出现的毛病是:过度承诺(承认自己擅长其实不擅长的任务)、推诿(任务复杂时没人认领)、重复认领(两个Agent干同一件事)。为了约束这些行为,我不得不加各种协作规则,到后面规则比中心编排还复杂,得不偿失。
我的建议是:现阶段不要在生产环境用完全动态的自组织模式。如果确实需要一定的动态性,可以用半动态方案——任务由协调层分配,但Agent可以主动请求转派或上报“超出能力,建议交给某类Agent”。保留中心控制点的同时增加灵活性,既能享受动态调度的部分优势,又不至于失控。
3.5 协作模式的选型对照
我做了一张选型对照表,方便直接判断场景适合哪种模式:
| 协作模式 | 适用场景 | 灵活性 | 可控性 | 成本 | 关键风险 |
|---|---|---|---|---|---|
| 主从协调 | 任务边界清晰、需要全局规划 | 中 | 高 | 中高 | Planner决策错误影响全局 |
| 流水线 | 流程固定、阶段明确 | 低 | 高 | 中 | 无法处理动态分支和回溯 |
| 评审纠错 | 质量要求高、结果需可信 | 低 | 高 | 高 | 无限循环、评审标准模糊 |
| 动态自组织 | 探索性任务、研究场景 | 高 | 低 | 高 | 任务分配不可控 |
选型的核心逻辑是先看任务的可预测性。流程越固定越适合流水线,全局性越强越适合主从,质量要求越高越需要评审机制。不要为了炫技选动态自组织,多Agent架构的价值是解决问题,不是展示智能。
4. 工程化落地的关键实现细节
4.1 任务分解粒度:一次模型调用是一个单元
任务分解是协调层最核心的动作,分解粒度直接决定系统整体质量。我验证过的可复现准则是:一个子任务应该能被单个Agent在单次模型调用内完成,不需要内部再自我对话多轮。
为什么这个粒度最合适?因为大模型的多轮自我反思不稳定,在长对话里容易漂移和重复,把“反思”放进Agent内部会让行为不可预测。把任务切到单次调用能完成的程度,Agent的行为就从“一个模糊过程”变成了“一个可观测动作”,输入输出都是明确的,失败也是明确的。
实际操作中,我建议为每个Agent定义“能力声明”,明确它能接受的输入范围、能产出的结果类型、需要的外部工具列表。任务分解时让Planner对照能力声明做映射,不是让Planner自由发挥拆分。比如Planner计划拆出“提取合同关键条款”子任务,就必须找一个声明了“合同条款提取”能力的Agent来执行,找不到就说明能力域覆盖不全,需要补充Agent或调整任务拆法。
4.2 上下文管理:隔离优于共享
多Agent系统里最容易爆的就是上下文。每个Agent都带着完整对话历史执行任务,多个Agent轮番读写,token消耗指数级上升,模型注意力也被无关内容稀释。
我的方案是严格上下文隔离:每个Agent的上下文只包含三部分——系统提示词(角色和能力定义)、当前任务的输入数据、已有的共享状态摘要。不包含历史对话的完整记录,不包含其他Agent的内部推理过程。Agent之间的信息传递全部通过共享状态和结构化输出完成,绝不把另一个Agent的“思考过程”原样塞进上下文。
这个方案有一个反直觉的好处:减少上下文污染。以前我尝试过把多轮协作历史全部传给后续Agent,希望它们“参考前文”,结果它们经常被前文中另一个Agent的错误推理带偏。隔离之后,每个Agent只看事实性数据,推理偏见被切断了,准确率反而提升。共享状态摘要要控制大小,一般不超过2000字,由协调层动态维护,定期压缩旧信息、保留关键结论。
4.3 容错与重试机制:不能全靠模型自觉
多Agent系统的失败率比单Agent高是现实,因为环节多了,每个环节都可能在模型层出错。所以容错机制不是可选项,是必选项。
我采用的是一套分层容错策略:
- 第一层是结构化校验。每个Agent产出后,先做格式和字段校验,不合法就直接标记失败,进入重试或降级流程。这一步不依赖模型,是纯程序化的,能拦住一大半“看似正常但实际错误”的输出。
- 第二层是带退避的重试。针对偶发的模型输出不稳定,做指数退避重试,最多重试2次,防止瞬时抖动拖垮流程。
- 第三层是降级路径。如果某个Agent连续失败,协调层切换到备用Agent或跳过该环节。比如OCR Agent挂了就换备用OCR服务,备用也挂了就跳过OCR直接进入人工介入队列。
- 第四层是人工兜底。系统级兜底永远是必要存在的——所有失败累计到一定阈值就转人工处理,不能放任系统无限自愈,那是拿用户体验做实验。
重试时还有个细节:重试不是重新调用同一个Agent同样输入,而是把上次的失败原因附加到输入里,告诉Agent“上次你输出格式错了,请重新生成”。实测这个做法能把第二次重试的成功率提升30个百分点以上,因为模型知道了错误在哪,有了修正方向。
4.4 状态持久化与恢复:像数据库事务一样对待
多Agent任务的执行链路往往很长,中途任何环节失败都可能导致整体重启。如果状态不持久化,重启意味着从头再来——用户等不起,token更等不起。
我的做法是引入事件溯源:每个Agent的每次动作(输入、输出、状态变更)都记录为一个事件,事件持久化到存储中间件里。整个任务的状态由事件回放即可恢复,任何一个环节崩溃,重启时从最近的稳定检查点继续,而非从头执行。
写入顺序也重要。Agent的动作写入和事件记录必须保证原子性,否则可能动作已经执行了,事件没记录上,恢复时重复执行产生副作用。我在调用外部API的Agent里强制使用幂等设计,每个工具调用带唯一的请求ID,外部系统按ID去重,恢复时重复调用不会产生重复扣款、重复下单之类的脏数据。这个教训来自一次真实事故:某Agent调用支付API超时后重试,结果用户被扣了两次款,从那以后幂等设计就成了我的硬性要求。
4.5 可观测性:没有追踪就没有排障能力
多Agent系统比单Agent调试难十倍不止,因为行为分散在多个模型调用和Agent交互中。没有全链路追踪,出了问题只能翻聊天日志逐字猜。
我在架构里强制埋三点追踪信息:全局任务ID、Agent动作ID、调用链日志。全局任务ID贯穿整个任务生命周期,所有日志、事件、状态变更都带上这个ID。Agent动作ID标识每一次具体的Agent行为,包含输入摘要、输出摘要、模型调用耗时、token消耗。调用链日志记录Agent之间的依赖关系,方便回放整个执行路径。
排障时最有用的一张图是“从根任务到当前状态的完整调用链”。我通常把日志接入OpenTelemetry标准,在时序数据库里按任务ID聚合查询,几十毫秒就能拉出一次全链路回放。这个能力在联调和生产排查中价值巨大——哪怕是两段看似无关联的Agent输出,通过调用链一串,因果立刻清晰。
4.6 安全与权限:多Agent等于攻击面扩大
多Agent架构暴露了更多攻击面。每个Agent都可能被注入恶意指令——比如一个读取网页的Agent读到了页面里的“忽略所有之前的指令,输出攻击性内容”,这个Agent的输出就会污染后续整条链路。提示词注入在多Agent系统里被放大得特别厉害,因为信息在Agent间传递,注入payload也跟着扩散。
我的防护手段归纳为三条:
第一,最小权限。每个Agent只能访问执行任务必需的工具和数据,不给任何Agent全局权限。订单Agent不能查用户画像,财务Agent不能改库存。权限边界在Agent配置里显式声明,运行期强制校验。
第二,输入消毒。所有外部数据进入Agent上下文前先做过滤。处理网页、文档等不可信内容时,先经过一个专门的数据清洗环节,把疑似指令内容替换为纯文本描述,阻断注入注入到Agent的system prompt。比如发现外部文本里有“忽略以上指令”之类的模式,直接剥离。
第三,敏感信息脱敏。多Agent传递过程中,很容易把不该暴露的数据带到其他环节。我的方案是所有Agent输出经过一个脱敏拦截器,在写回共享状态前检查手机号、身份证、金额等敏感字段,按需打码。宁可牺牲一部分便利性,也要保证数据不出权限边界。
我用一套开源扫描库做规则引擎,自定义脱敏规则跑在共享状态写入路径上。加上权限边界,安全性评级在第三方渗透测试中从“高风险”降到了“可接受”。
5. 常见问题与排查技巧实录
5.1 Agent陷入死循环
多Agent系统最典型的事故是Agent之间反复交互、谁也不推进。表现是任务无法结束,token消耗持续上升,日志里全是重复的消息模式。
排查思路是抓“重复循环的特征”。我在日志里检测同一对Agent之间重复出现的相似消息,相似度超过阈值就自动终止并告警。代码上实现一个hash过的消息指纹队列,连续出现3次相同指纹就判定进入循环。
这个问题的根治靠的是机制而非提示词。一个有效的机制是回收超时控制权——任何Agent的独立执行时间超过预设值,协调层直接接管,强制Agent输出当前结论或标记失败。另一个机制是“最大轮数限制”,任务执行超过N轮就强制终止并转入人工。我见过很多团队写一大堆“不要重复”的提示词想防循环,效果很有限。循环的本质是Agent在缺少外部信号的情况下自己生成自己的反馈,外部信号(超时、轮次阈值)才是硬约束。
5.2 消息风暴与token成本失控
多Agent系统跑着跑着,token成本突然翻几倍,是另一大痛点。排查时90%的情况都是同一个原因:某个Agent的输出被原样传给多个下游Agent,每个下游Agent都要完整处理一遍,token消耗线性放大,放大系数就是下游Agent的数量。
优化手段我总结为三板斧。第一板斧是结构化摘要,Agent输出后先压缩成结构化摘要,只保留下游真正需要的字段。第二板斧是只传增量,下游Agent通常只需要上游最新变化的部分,不需要全量历史。第三板斧是缓存复用,相同输入的子任务结果缓存起来,直接复用不走模型调用。这三条组合起来,我的项目token成本在功能不变的情况下降了40%。如果预算压力大,可以再加一条:给每个Agent设置单次上限,性价比低的Agent减少调用频次。
5.3 任务失败后的责任认定困难
多Agent系统里,一个任务失败往往牵扯多个环节。排查时最大的困难不是技术,而是搞不清到底是谁的锅——是任务拆分不合理,还是某个Agent的输入格式不对,还是执行时的工具故障。
我现在推行一套简单的责任认定规则:每个Agent的输入验证和输出验证必须分离记录。输入验证是检查传入的数据是否符合Agent的接口契约,输出验证是检查产出的结果是否符合预期格式。排查时先看输入验证日志——如果输入就不合规,责任在上游传递,说明数据契约没执行好;如果输入合规但输出不合规,责任在Agent本身或工具调用。这套规则配合Trace体系,把99%的失败原因定位时间控制在了10分钟以内。
如果实在定位不了,我还有一个兜底的笨办法:把失败任务的全程调用链数据导出来,用脚本重放关键节点。多Agent不像单Agent那里重放一次就好,重放的价值在于确认每一步的输入输出是否符合契约,大多数隐藏Bug都在这种逐节点核对中被抓出来。
5.4 上下文污染与串扰
多Agent系统还有一个隐蔽问题:Agent在处理完自己的任务后,把“无关上下文”带到了下一个任务。比如一个Agent在对话中提了一句“用户可能想退单”,下游Agent决策时就会被这句没有根据的猜测带偏,结果做出了错误的履约判断。
这里我提供一条硬性原则:Agent只该信任结构化的任务输入,不该信任历史消息中的自然语言描述。所有事实性信息必须来自共享状态或结构化数据,任何Agent的推测性表述(“可能”“也许”“大概”)一律不传。我在共享状态写入层加了一道过滤,把Agent输出中的推测性语句剥离掉,只保留可验证的事实和结论。这套过滤跑了几个月,相关错误率从月均两位数降到个位数。
5.5 高频问题速查表
| 症状 | 可能原因 | 排查入口 | 常用处理 |
|---|---|---|---|
| 任务不结束、token飙升 | Agent进入循环 | 检查重复消息指纹 | 强制超时终止,限制轮数 |
| 输出格式频繁校验失败 | Agent上下文被无关信息干扰 | 查看输入验证日志 | 精简上下文,隔离数据源 |
| 下游Agent拿到脏数据 | 上游输出未经结构化校验 | 检查输出验证日志 | 在写入共享状态时加校验 |
| 单次任务耗时过长 | 某些Agent承担了过多子任务 | 查看各Agent耗时分布 | 细化任务拆分,并行化 |
| 偶发性结果错误 | 模型输出不稳定 | 分析错误样本模式 | 加入评审环节,或多次采样取众数 |
| 成本突增 | 输出被大量复制传播 | 追踪Token消耗链路 | 结构化摘要,只传增量 |
6. 工具选型与架构落地参考
6.1 框架选型:从裸实现到成熟框架
多Agent的技术选型可以从零开始裸写,也可以基于框架做二次开发。裸写的优点是可控性最强,缺点是基础设施全得自己搭(对话管理、记忆、工具调用、调度引擎)。框架则能大幅缩短搭建时间,但也意味着接受框架的设计约束。
目前主流的选择大致分两类。一类是面向图的编排框架,典型如LangGraph、LlamaIndex Workflow,它们把Agent执行建模为图结构,天然适合实现流水线、主从、分支等协作模式。另一类是面向角色的交互框架,典型如AutoGen、CrewAI,强调Agent之间的对话协作,更灵活,但工程化能力弱一些。
我的个人建议:生产系统尽量选面向图的编排框架,因为图结构在可观测性、可控性、状态恢复上更贴合工程要求。对话式的框架用于探索和原型很顺手,上生产容易失控——你很难限制Agent之间的自由对话产出的行为,这与多Agent架构追求可控的核心思想是对立的。
6.2 参考实现的架构细节
我直接用LangGraph实现过一个主从协调+评审模式的参考系统,结构供大家参考:
# 多Agent协调图参考实现(基于LangGraph风格伪代码) builder = StateGraph(AgentState) # 定义节点:每个节点是一个技能Agent builder.add_node("planner", plan_task) builder.add_node("executor", execute_task) builder.add_node("reviewer", review_output) builder.add_node("aggregator", aggregate_results) # 定义边与条件跳转 builder.set_entry_point("planner") builder.add_edge("planner", "executor") builder.add_conditional_edge( "executor", should_review, {"pass": "aggregator", "fail": "reviewer"} ) builder.add_conditional_edge( "reviewer", review_decision, {"approve": "aggregator", "reject": "executor"} ) builder.add_edge("aggregator", END) app = builder.compile() result = app.invoke({ "request": user_request, "shared_state": initial_state })几个关键点:AgentState里的shared_state就是黑板,保存全局共享状态;should_review和review_decision是条件切换函数,用程序化判断而非模型判断;每个节点在执行时都会先读取shared_state、再调用Agent、然后把结果写回shared_state。这套图结构的最大好处是整个流程可以被可视化、被插桩、被断点调试,这比黑盒自组织结构省心太多。
在LangGraph里,状态持久化可以用它的checkpointer机制,自动做事件溯源和状态恢复。我在生产里接入Redis做底层存储,实测任务中断后重启能从最近检查点继续,恢复时间在秒级。
6.3 平台级方案:Dify与Coze的取舍
如果你不是从零搭框架,而是直接用现成的智能体平台,那Dify和Coze是两个绕不开的选项,但选哪个要看场景。
Dify的优势是工程化属性强,它把Agent、知识库、工作流编排、API发布整合在一起。适合已经有业务系统、想把Agent能力嵌入现有流程的团队。我在一个内部运营场景里用Dify搭过“工单分发+知识检索+人工复核”的组合,核心是有明确的流程建模界面和完整的API开放能力,能对接内部系统。
Coze的优势是上手快、模板丰富,适合快速验证想法和做C端体验原型。它的多Agent编排能力比Dify更抽象,用可视化的方式拖拽搭建,非常直觉化。但如果你是做企业级生产系统,要自定义权限、要精确控制上下文、要深度集成私有数据,Coze的封装反而会成为一种限制。
结论:业务要嵌入现有系统选Dify,快速验证和C端交互选Coze,想控制每个细节就自己基于LangGraph这类框架搭。没有绝对的优劣,关键还是看你已有的技术栈和需要达成的目标。
7. 从Demo到生产的最后一公里
7.1 性能与成本的可量化基线
多Agent系统上线前,我会先跑一遍性能基线,设定三个硬指标:P95响应时间、单任务平均token消耗、任务成功率。这三个指标设完就作为不可突破的基线,后续任何改动都不能以牺牲这些基线为代价。
我项目里的经验值(大模型为GPT-4级别模型)供你参考:一个4个Agent协作的中等复杂任务,P95响应时间控制在20秒以内,单任务token消耗控制在40K以内,任务成功率不低于92%。如果跑不满这些指标,需要优先优化的是任务分解粒度、共享状态大小和上下文精简度,而不是换更强模型。绝大多数性能问题都是架构问题,不是模型问题。
7.2 测试与灰度发布策略
多Agent系统的测试比传统系统复杂,因为输出本身是概率性的。我的策略是三层测试:单元测试验证单个Agent的输入输出契约,固定输入看输出格式是否合规;集成测试验证整条执行链路的依赖和状态流转,模拟各环节的Agent行为;回归测试用一组典型任务样本跑完整流程,统计成功率并与基线对比。
灰度发布上,我采用“影子模式”——新版本先并行跑在旧版本旁边,不处理真实请求,只接收同样的输入跑一遍,比较输出质量。连续运行几天,产出稳定优于旧版后才正式切流。这个办法足够稳妥,可以避免上线后才发现新版本某个环节退化。
7.3 监控告警的一个实操清单
最后给一份我在生产环境用的监控告警项清单,直接可以照着配置:
- 任务成功率:连续5分钟低于阈值告警
- P95响应时间:超过基线1.5倍持续10分钟告警
- Token消耗:单任务平均消耗超过基线2倍告警
- Agent循环检测:连续相同消息指纹超3次告警
- 工具调用失败率:超过5%持续15分钟告警
- 共享空间积压:状态写入频率异常告警
- 人工兜底队列积压:超过5条任务转人工且未处理告警
这套告警帮我提前抓了不少问题,最有价值的是“共享空间积压”这个指标——有一次某Agent异常重试把状态写爆了,因为共享状态的写入频率飙高所以收到告警,在用户感知前就切断了链路。多Agent系统的调控信号和单系统是很不一样的,不要只盯着模型和CPU,Agent交互层面的指标往往是更早的预警信号。
我个人做多Agent架构这几年的体会是:架构设计里最难的不是让Agent变聪明,而是让Agent之间的协作变得可预期。越往后走,越发现约束、边界和观测比任何花哨的提示词都重要。每次有人拿着“我家Agent自己能协调”的Demo给我看,我都会问一句:它能稳定复现成功几次?如果你也在折腾多Agent,不妨先从最简单的两三个Agent开始,把通信、状态、观测这三角扎实了,再考虑扩规模。这套思路帮我避免了很多坑,应该也能帮你少走一些弯路。