资讯动态

多智能体系统架构选型:通用框架与自研编排的混合实践

发布时间:2026/10/20 16:26:46 来源:尧图企业网站定制
1. 从一次深夜告警说起为什么架构选型不能只看Demo凌晨两点监控面板上一条红色的告警线突然拉起来——某个多智能体协作任务在跑了四十多分钟后卡死日志里只有一句含糊的“等待下游响应超时”。这不是第一次了。过去两周团队用某通用编排框架搭的原型在演示环境里跑得挺漂亮三个智能体分工明确、消息流转顺畅可一旦把任务复杂度提上来、把并发数从个位数拉到几十各种诡异问题就开始冒头状态丢失、消息重复消费、某个Agent明明已经完成了子任务却迟迟不触发下一步。那次告警之后我们花了整整三天做复盘最终得出一个当时听起来有点“反直觉”的结论通用框架和自研编排我们都不该全押真正适合我们业务的是混合架构。这篇文章就把这段选型过程完整拆开讲——不是给你一个标准答案而是把我们在“自研编排”和“通用框架”之间反复横跳、最后走向混合架构的思考链路、踩过的坑、以及最终落地的分层设计原原本本摊开。如果你正在做多智能体系统Multi-Agent System的架构设计或者团队里有人拍着桌子说“直接用现成框架不就行了”那这篇内容应该能帮你少走至少两个月的弯路。我会尽量说人话把编排、状态管理、通信协议这些听起来很唬人的东西用实际项目里的场景讲清楚。先说清楚一个前提多智能体系统的“架构抉择”本质上不是选一个框架那么简单而是要回答三个问题——谁来定义任务流转的拓扑结构、谁来管理跨Agent的状态一致性、谁来兜底异常和重试。这三个问题通用框架和自研编排给出的答案完全不同而混合架构的价值恰恰在于让它们各管一段。2. 通用框架的甜蜜期与它的三堵墙2.1 为什么一开始大家都倾向用通用框架刚接触多智能体编排的时候几乎所有人的第一反应都是找现成框架。原因很朴素多智能体系统里有一堆“脏活累活”——消息队列、任务调度、Agent生命周期管理、工具调用封装、上下文传递——如果每个都自己写光是把第一个能跑通的Demo搭起来就得花掉两三周。通用框架把这些东西打包好了你只需要定义几个Agent、写几段提示词、连几条边一个能跑的多智能体流程就出来了。我们当时也是这么想的。选型阶段对比了几个主流方案评估维度主要是这几项评估维度通用框架表现自研编排表现上手速度快半天出Demo慢至少一周搭骨架拓扑灵活性受框架抽象限制完全自由状态管理框架内置但黑盒自己掌控透明异常处理通用重试策略可按业务定制调试可观测性依赖框架日志全链路自己埋点长期维护成本受框架版本影响自己背维护责任表格里能看出来通用框架在“上手速度”这一项上是碾压性的。我们当时用了一个下午就把三个Agent的协作流程跑通了一个负责拆解任务一个负责调用工具执行一个负责汇总结果。演示给业务方看的时候对方眼睛都亮了。那段时间团队士气很高觉得这事儿稳了。但甜蜜期大概只持续了两周。2.2 第一堵墙拓扑结构被框架的抽象“框死”了通用框架通常会给你几种预设的协作模式比如顺序执行、路由分发、群组讨论、层级委派。这些模式覆盖了大部分常见场景但我们的业务里有一种很特殊的流转逻辑某个Agent的输出需要根据内容动态决定是走“并行分支”还是“串行回退”而且这个判断逻辑本身还需要调用一个外部服务来确认。在框架里这种动态拓扑很难优雅地表达。你当然可以用条件边conditional edge来模拟但当分支嵌套超过三层之后整个流程图就变成了一团意大利面连当初写它的人都很难说清楚某个请求到底会走哪条路径。更麻烦的是框架的抽象层把底层的执行顺序隐藏了你想在某个特定节点插入一个“检查点”做状态快照发现框架根本没暴露这个钩子。这里有个经验通用框架的抽象层次越高你能插入自定义逻辑的地方就越少。而多智能体系统恰恰是一个“自定义逻辑密度极高”的场景。2.3 第二堵墙状态一致性在并发下变成玄学单机、低并发的时候框架的状态管理看起来没问题。但当我们把并发任务数拉到30以上问题就来了。框架内部用的是一个共享的状态存储多个Agent实例同时读写同一个会话状态时出现了经典的“读-改-写”竞争。具体表现是Agent A读取了状态S准备写入S但在它写入之前Agent B已经把状态改成了S结果A的写入直接覆盖了B的修改导致B的某个子任务结果凭空消失。我们翻框架源码才发现它默认的状态更新策略是“最后写入获胜”last-write-wins而且没有提供乐观锁或版本号的机制。这意味着在高并发下状态丢失是必然的只是概率问题。要解决这个问题要么自己在框架外面再包一层状态管理要么换框架——但换框架意味着前面两周的工作全部推倒重来。2.4 第三堵墙异常处理的“通用策略”救不了业务特有的失败模式框架提供的重试策略通常是“失败后重试N次指数退避”。这在调用外部API时很好用但多智能体系统里的失败模式远不止“调用超时”这一种。比如Agent输出了格式正确但语义错误的结果框架认为“成功”但业务上需要重新规划某个子任务依赖的上游数据还没准备好需要“等待并轮询”而不是“立即重试”多个Agent同时失败需要判断是“独立故障”还是“级联故障”前者可以各自重试后者必须整体回滚。这些逻辑通用框架要么不支持要么需要用很别扭的方式绕过去。我们当时为了处理“级联故障回滚”在框架外面写了一个协调器结果这个协调器本身又变成了一个单点复杂度不降反升。3. 转向自研编排自由是自由但代价是什么3.1 自研编排的核心设计把控制权拿回来被通用框架的三堵墙撞得头破血流之后我们决定试试自研编排。核心思路很简单把任务流转的拓扑定义权、状态管理的控制权、异常处理的决策权全部拿回到自己手里。具体设计上我们定义了一个轻量的编排引擎核心概念只有三个TaskGraph用有向无环图DAG描述任务流转节点是Agent调用边是数据依赖和条件分支。和框架不同的是这个图是运行时动态构建的每个请求进来时根据输入内容生成专属的图。StateStore自己实现的状态存储每个任务有独立的版本号所有写入操作必须携带版本号做乐观锁校验冲突时抛出异常由上层决定重试还是合并。FailurePolicy每个节点可以挂载自己的失败策略支持重试、跳过、回退到指定节点、触发补偿任务等。这套东西搭起来大概花了一周半比用框架慢但搭完之后之前遇到的三个问题全部有了清晰的解法。动态拓扑TaskGraph本来就是运行时构建的想怎么连就怎么连。状态一致性版本号乐观锁直接解决。异常处理每个节点自己定义策略级联故障通过图的拓扑分析自动识别。3.2 自研带来的新问题基础设施的维护成本被低估了但自研的代价很快就显现出来了。最直接的是基础设施的维护成本。通用框架帮你处理了消息序列化、网络通信、Agent进程管理、日志收集这些“非功能性需求”自研之后这些全部得自己扛。我们当时踩的几个坑消息序列化一开始用JSON简单但体积大高并发下网络带宽成了瓶颈。后来换成二进制协议又得自己处理版本兼容。Agent进程管理Agent崩溃后如何自动拉起如何做优雅停机如何限制单个Agent的资源使用这些在框架里是内置的自研之后每个都得单独实现。可观测性框架自带了一套追踪和指标采集自研之后得自己埋点、自己搭看板。有段时间我们排查一个问题因为缺少链路追踪硬是靠打日志加时间戳对齐花了整整一天。更隐蔽的问题是团队认知负担。自研编排引擎的代码只有最初设计它的两个人最清楚其他人接手时光是理解TaskGraph的动态构建逻辑和StateStore的版本号机制就花了好几天。而通用框架至少有公开文档和社区讨论遇到问题还能搜一搜。3.3 一个具体的性能对比自研真的更快吗我们做了一组对比测试场景是“一个任务拆解Agent 五个并行执行Agent 一个汇总Agent”并发数50每个Agent模拟耗时200ms。结果如下指标通用框架自研编排平均端到端延迟1.8s1.2sP99延迟4.5s2.1s状态丢失率0.3%0%CPU占用较高框架开销较低开发耗时2周3周维护人力0.5人1.5人自研在延迟和可靠性上确实更好但开发耗时多了50%维护人力多了两倍。这个账怎么算取决于你的业务对延迟和可靠性的敏感程度以及团队有没有足够的人力去背这个维护责任。4. 混合架构的诞生让框架管“脏活”自研管“决策”4.1 混合架构的分层原则什么该交给框架什么必须自己攥着经过通用框架和纯自研两轮折腾我们逐渐摸清了一条分界线通用框架擅长的是“通信和生命周期”这类标准化程度高的脏活自研擅长的是“拓扑和决策”这类业务耦合度高的逻辑。混合架构的核心就是沿着这条线把系统切成两层。具体分层是这样的底层框架负责Agent的注册与发现、消息传输、进程健康检查、基础重试、日志与指标采集。这一层用通用框架的能力不重复造轮子。中层自研负责TaskGraph的动态构建与执行、状态版本管理、跨Agent的事务性协调、业务级异常策略。这一层完全自研框架不介入。上层业务负责每个Agent的具体提示词、工具调用逻辑、结果校验规则。这一层由业务团队自己维护。这样切的好处是框架的版本升级不会影响中层的核心逻辑而中层的业务变化也不需要动底层的通信机制。两层之间通过一个薄薄的适配层通信适配层的接口是我们自己定义的框架只是它的一个实现。4.2 适配层设计让框架“可替换”的关键混合架构能不能成立关键看适配层设计得好不好。我们的适配层定义了三个核心接口class AgentRuntime: def spawn(self, agent_spec): ... def send(self, agent_id, message): ... def on_message(self, callback): ... class StateBackend: def read(self, key, version): ... def write(self, key, value, expected_version): ... def watch(self, key, callback): ... class TelemetrySink: def emit_trace(self, span): ... def emit_metric(self, name, value): ...底层框架只需要实现这三个接口中层完全不关心底层用的是哪个框架。我们甚至做过实验把底层从框架A换成框架B中层的TaskGraph和StateStore代码一行没改只换了适配层的实现两天就完成了迁移。这个可替换性是纯自研或纯框架都做不到的。4.3 状态管理的混合方案框架管传输自研管一致性状态管理是混合架构里最微妙的部分。我们的做法是框架负责状态的传输和持久化自研负责状态的一致性语义。具体来说框架提供的是一个“至少一次”的消息传递保证消息可能会重复。自研的StateStore在写入时做幂等校验每个状态更新都带一个唯一的事务ID如果同一个事务ID已经写入过直接返回成功而不重复应用。这样即使框架重复投递消息状态也不会被重复修改。版本号机制则用来处理并发写入。StateStore的每次写入都要求携带期望的版本号版本号不匹配时抛出ConcurrentModificationError由上层的FailurePolicy决定是重试、合并还是放弃。这套机制在纯框架方案里是没有的在纯自研方案里是我们自己实现的现在在混合架构里它成了连接框架和业务的“一致性锚点”。5. 落地过程中那些文档不会写的坑5.1 框架的“默认配置”在高并发下全是雷通用框架的默认配置通常是为“低并发、快速上手”优化的。比如默认的消息队列容量、默认的线程池大小、默认的超时时间在Demo阶段完全够用但一到生产环境的高并发场景这些默认值就成了定时炸弹。我们踩过的一个典型坑框架默认的消息确认超时是30秒意味着一条消息发出去后如果30秒内没收到确认框架会认为投递失败并重试。但在我们的场景里某些Agent处理复杂任务需要超过30秒结果框架在Agent还在处理的时候就把消息重新投递了一遍导致同一个任务被处理了两次。这个问题的隐蔽性在于它不会报错只会让某些任务的结果出现重复排查起来非常费劲。经验任何框架的默认配置在上生产之前都必须逐项审查。重点看超时时间、重试次数、队列容量、线程池大小这四项。5.2 自研的TaskGraph在动态分支下的死锁风险自研TaskGraph的灵活性是一把双刃剑。我们设计了一种“动态分支”机制某个节点的输出可以决定后续走哪条分支分支的拓扑在运行时才确定。这个机制很强大但也引入了一个新的风险——死锁。具体场景是这样的节点A的输出决定走分支1还是分支2分支1依赖节点B的结果分支2依赖节点C的结果而节点B和节点C又都依赖节点A的某个中间状态。如果节点A的输出恰好让分支1和分支2互相等待对方的结果整个图就死锁了。我们后来加了一个静态分析器在TaskGraph构建完成后做一次拓扑检查检测是否存在“循环依赖”或“不可达节点”。但这个分析器只能检测静态的图结构对于运行时才确定的分支只能在执行时加超时兜底。这个坑让我们明白动态拓扑的自由度越高越需要配套的静态检查和运行时兜底。5.3 混合架构的调试复杂度跨层问题最难查混合架构最大的代价是调试复杂度。一个问题可能出在框架层、适配层、自研层或业务层而每一层的日志格式和追踪ID体系都不一样。我们遇到过一个案例某个任务偶尔会卡住日志显示框架层认为消息已投递自研层认为状态已更新但业务层就是没收到回调。最后查了两天才发现是适配层在转换消息格式时对某个特殊字符的处理有bug导致消息在框架层和自研层之间“消失”了。为了解决这个问题我们后来强制要求所有层使用统一的追踪ID并且在适配层加了详细的入参出参日志。虽然增加了日志量但跨层问题的排查时间从平均两天缩短到了两小时。6. 混合架构的适用边界与选型决策清单6.1 什么情况下混合架构是过度设计混合架构不是银弹。如果你的多智能体系统满足以下所有条件那直接用通用框架就够了混合架构反而是过度设计任务拓扑是静态的不需要运行时动态构建并发量在个位数状态一致性压力不大异常处理只需要通用的重试策略没有复杂的业务级回滚需求团队规模小没有足够人力维护自研层。我们团队之所以最终选择混合架构是因为上面四条我们一条都不满足。任务拓扑高度动态、并发量在几十到上百、异常处理有复杂的级联回滚需求、团队有专门的基础设施人力。这四个条件同时成立时混合架构的收益才能覆盖它的成本。6.2 一张选型决策表从需求反推架构下面这张表是我们复盘时整理的把关键需求维度和对应的架构选择对应起来供参考需求维度倾向通用框架倾向自研编排倾向混合架构拓扑动态性低高高并发规模低10高高状态一致性要求最终一致即可强一致强一致异常处理复杂度通用重试业务级策略业务级策略团队基础设施人力无充足中等上线时间压力大小中长期维护意愿低高中高这张表的使用方法是先看“倾向混合架构”那一列如果大部分维度都落在这一列那混合架构值得考虑如果大部分落在“倾向通用框架”那就别折腾直接用框架。6.3 混合架构的演进路径从框架起步逐步自研如果你决定走混合架构我建议的演进路径是先用通用框架快速搭出可运行的版本验证业务逻辑当遇到框架解决不了的问题时把那一部分逻辑抽出来自研通过适配层接回去。不要一上来就全自研那样风险太高。我们实际走的就是这条路第一版全框架第二版把状态管理抽出来自研第三版把TaskGraph抽出来自研第四版把异常策略抽出来自研。每一步都是在遇到具体问题后才动手而不是提前设计一个“完美架构”。这样每一步的改动都有明确的收益也容易回滚。7. 一些关于多智能体架构的个人体会做多智能体系统的架构设计最容易犯的错误是“用框架的抽象来思考业务”。框架给你的是顺序、路由、群组这些模式但业务需要的是“根据内容动态决定下一步”“多个Agent的结果需要事务性提交”“失败时要区分独立故障和级联故障”。这些需求框架的抽象往往表达不了硬套只会让代码越来越扭曲。混合架构的本质是承认“没有一种方案能同时满足标准化和定制化”然后把系统切成两层让每层做自己最擅长的事。框架管通信和生命周期自研管拓扑和决策适配层做翻译。这个思路不仅适用于多智能体系统任何“标准化基础设施 高度定制业务逻辑”的场景都可以参考。最后分享一个我们内部用的判断标准如果你发现自己在框架外面写了很多“协调代码”那这些协调代码就应该被抽出来成为自研层的一部分。框架应该是被自研层调用的工具而不是反过来让自研逻辑去适配框架的抽象。这个主次关系一旦理顺架构的复杂度就会大幅下降。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑