尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
多智能体系统编排架构选型:自研与通用框架的混合实践
多智能体系统项目做了一半最怕的不是模型效果差而是架构卡住脖子功能都在demo里跑通了一上规模就到处打架。我们这半年就折腾了这么一件事——自研编排和通用框架到底怎么选。试过纯通用框架也试过纯自研最后落地成了一套混合架构把业务编排和单Agent能力拆开处理。这篇文章把这段架构抉择过程完整捋一遍希望能给正在这条路上纠结的人一点参考。1. 从一个Agent到一群Agent问题先于方案出现1.1 当时面对的真实场景事情起源于一个公司内部的智能工单响应项目。一开始只有一个Agent做的是接到问题描述调工具查数据返回结论这条单链路技术方案很轻松一个大模型调用包上几个工具函数跑个循环就完事。上线以后效果不错于是业务方很快提出了新需求——能不能让一个工单自动走多个处理环节比如先分类再检索知识库再匹配历史工单最后生成答复如果涉及跨部门流转还要走人工审批节点。这时候就不是一个Agent的问题了是一群Agent的问题。多个Agent各管一段需要有人告诉每个Agent什么时候该上场、上一个环节的产出怎么传给下一个环节、某个环节失败了是整个流程重跑还是只重跑这一个子任务以及最关键的人工审批步骤怎么插进去。这套安排谁、按什么顺序、失败怎么办的逻辑业内叫编排。而每一个Agent内部怎么调用模型、怎么选工具、怎么记住上下文是另一层逻辑。很多团队在初期容易把这两层混在一起觉得我的系统里有多个Agent所以我需要一个大框架把Agent拼起来。但做下去就会发现这两个问题的答案几乎不会来自同一个方案。1.2 编排到底在解决什么问题把编排这件事拆开看核心就五个问题流程拓扑怎么描述串行、并行、条件分支、循环、人工介入业务上怎么表达。状态怎么维护整个流程执行到哪一步每个Agent返回了什么谁在等谁。数据怎么流转一个Agent的输出如何映射为下一个Agent的输入字段名不一致怎么办。失败怎么处理超时、模型报错、工具调用失败是重试、跳过还是终止。过程怎么观测哪里慢、哪个Agent消耗了多少token、哪一步卡住了。这些问题听起来像是框架应该解决的但实际业务场景里每个问题的答案都和具体业务强耦合。比如人工审批环节有的团队希望审批人直接在一个内部系统里点按钮有的希望走企微通知有的要钉钉回调。通用框架通常只提供一个通用的human-in-the-loop接口但和内部系统打通、和审批流对接几乎必然要写大量胶水代码。1.3 为什么这事不能用一个Agent搞定一切有人会问能不能不做编排把所有功能塞进一个Agent让大模型自己决定调用顺序我们早期试验过。单个模型确实可以在几轮对话内完成部分多步骤任务但不可控因素太多。只要任务链路一长模型就会在某个环节忘记前面的约定或者反复调用同一个工具甚至自己发明一个不存在的工具名。稳定性完全取决于模型的临场发挥。多Agent的好处是可以把复杂任务拆解成相对简单的单Agent任务每个Agent只负责一个领域指令更聚焦prompt更容易调稳定。代价就是你必须引入一套编排机制。换句话说多智能体本质上是一个系统工程问题模型能力只是其中一环。2. 纯自研编排和纯通用框架为什么都没扛住2.1 先聊主流通用框架的写法与优势我们一开始选的是主流开源Agent编排框架这类框架通过声明式配置定义Agent和它们之间的协作关系内置了任务分配、对话记忆、工具注册等基础能力。用起来确实快定义两个Agent角色指定各自的工具集再声明协作方式半天就能跑通一个多Agent demo。它的优势集中在三点一是模型接入封装完善换模型厂商几乎只改配置二是记忆管理开箱即用短期记忆、长期记忆、向量检索都内置了三是社区生态活跃遇到问题一搜就有答案而且往前迭代非常快。对于原型验证和内部工具这种非核心链路这类框架性价比很高。2.2 业务变复杂后框架的墙一堵一堵出现项目进入第二阶段后框架的问题开始暴露。第一个问题出在条件分支和动态子任务上。框架内置的协作模式偏向静态拓扑Agent之间的连接关系基本上一开始就定死了。但我们的工单流程里有些环节要根据前置结果决定后续走向甚至要在运行中动态生成子任务列表。比如一个工单被判定为跨部门问题就需要临时创建多个调查子任务每个子任务对应不同部门。这种动态性在框架的配置体系里非常难表达最后只能大量使用hack式的回调函数把流程逻辑塞进去代码越写越脏。第二个问题是人工审批。框架的human-in-the-loop只是暂停等待外部输入但我们的审批要嵌入企业内部的审批系统审批人、审批级别、超时催办都有一套业务规则。框架层面只提供了暂停和恢复的接口剩下的业务对接、回调、审计日志全部要自己写。既然都要自己写那框架提供的价值就很有限了。第三个问题更致命——可观测性割裂。框架会生成自己的trace和日志我们自己写的业务逻辑又有另一套日志两套体系对不上排查一个问题要在两个系统里来回跳。年底压测时出了问题定位花了一个下午当时就意识到这个模式撑不过生产环境。2.3 纯自研编排那几天自由是真的工程量也是真的被框架憋了一段时间后团队内部自然冒出一个想法干脆编排层全部自己写不要框架了。我们当时花了一周搭了一套基于状态机的流程引擎配合Redis做状态存储确实爽——业务上任何奇怪的分支都能表达任何审批节点都能自由插入日志也能完全按自己的规范做。但两周之后就发现问题了Agent内部那一层也就是模型上下文管理、工具调用协议、输出结构化解析全都要重新造轮子。模型调用要自己处理重试和超时工具调用要自己维护注册表和参数校验记忆管理要自己实现向量化和缓存——这些恰恰是通用框架最成熟的部分我们却在重写它们。开发效率断崖式下降而且写出来的东西很难保证质量。更麻烦的是自研意味着要长期维护。Agent框架这类项目迭代很快今天大模型出了新功能、新协议自研方案要自己跟上而框架可以等社区更新。团队精力有限不可能既维护业务系统又维护一套Agent基础设施。2.4 两轮试错之后的结论两轮试错总结下来核心矛盾很清晰复杂业务流程需要高自由度编排但单Agent内部的成熟能力没必要重复发明。框架擅长后者却受限于前者自研擅长前者却在后者上拖后腿。所以答案不是二选一而是把系统按职责拆成两层——编排层用自研Agent内执行层用框架。3. 混合架构的分工边界编排层自研执行层用框架3.1 架构总览调度器与执行器分离最终落地的架构我们内部叫调度器-执行器分离模型。核心思想是定义一个自研的流程编排层自己管理拓扑、状态、流转、审批、重试而当一个节点真正要执行某个Agent干活时编排层把任务交给框架由框架去完成模型调用、工具选择、上下文汇聚这些工作。这么说可能有点抽象我用一个具体例子解释。用户提交了一个登录报错的工单编排层首先根据业务规则把流程切为四个节点意图分类、知识库检索、历史工单匹配、答复生成。它依次调度这几个节点每个节点配置的是一个Agent执行器。Agent执行器由框架管理内部完成调用大模型理解工单从知识库工具取数据生成建议答复等步骤。节点执行完毕执行器把结构化结果返回给编排层编排层再依据结果决定下一步走向——如果意图分类结果显示是网络问题就走网络故障分支如果匹配到相似历史工单就额外合并一份参考建议。整个流程的状态、分支、审批、超时都由编排层的状态机控制和框架完全无关。3.2 为什么这条边界放在这里最合理选择这条边界下面四个理由都是从实际踩坑里长出来的。第一编排层的使用频率相对低但每次使用都走在关键路径上必须可控。它是整个系统的骨架企业内部的流程规则、权限、审计都在这里自研能保证绝对适配。而框架在某个版本改个行为模式编排层不会跟着受牵连。第二Agent内部的能力是高频使用且相对标准化的。每个节点都要调用模型、使用工具、管理上下文这些恰好是通用框架最成熟的领域。放着成熟轮子不用非要自己造是对团队精力的浪费。第三编排层是业务方直接感知的审批逻辑、超时规则、节点字段都映射到业务语言。自研意味着产品经理可以直接对着状态图提需求改动一个节点的前后关系不涉及任何框架API。而框架的抽象语言是给开发者看的业务方理解成本很高。第四故障隔离。编排层出了问题受影响的是流程调度能力Agent执行层出了问题受影响的是单节点能力。两者解耦之后互不拖累。早期用纯框架时一个Agent内部崩了可能导致整个流程无法恢复这种事故在混合架构里基本不会发生。3.3 自研编排层的核心实现思路我们的编排层没有发明多复杂的模型就是一个DAG图加状态机。每个节点有四个状态pending、running、succeeded、failed外加一个special的blocked状态用于等人工审批。节点之间的边定义依赖关系和数据映射关系。有一点必须提醒很多自研编排系统死在状态和业务混在一起。我们一开始也犯过这个错——节点状态里存了业务字段、审批人、重试次数、上下文数据结果状态变得无比臃肿并发一高就有并发写冲突。后来重构成状态机只管流转状态和生命周期业务数据放在独立的数据表里关联用request_id串起来。状态机只回答现在到哪一步了业务数据回答这一步发生了什么。这个分离让整个系统的复杂度大幅下降定位问题也快了很多。3.4 通用框架在混合架构中的定位在混合架构里框架不是被用完即弃的而是降级为一个组件。我们的落地方式是在自研编排层内实现一个适配器接口框架作为该接口的实现。编排层的节点只需要声明我用这个执行器执行具体执行器内部是框架还是裸模型调用编排层不关心。将来框架出了新款或者模型能力有重大变化替换成本也小。再强调一点即使用了框架也不要让框架反过来定义你的流程结构。流程结构永远是业务侧的资产应该存在自己的系统里而不是藏在框架的配置文件里。一旦框架出问题至少业务资产不会跟着被锁死。4. 落地过程中的关键设计与踩坑复盘4.1 两套并发模型的碰撞混合架构最常见的一个坑是编排层和框架层各自有不同的并发模型。我们的编排层用的是一个独立调度循环加Redis队列而框架内部是异步事件驱动。两边一对接问题就来了编排层把任务交给框架执行器之后框架通过回调通知结果但回调的线程池不是我们控制的偶尔回调丢失任务就这么卡在running状态。后来我们改了一个压舱石方案所有任务下发之后编排层只认最终落库的结果状态不认临时回调。执行器完成工作后必须把结果写回专用结果表同时更新任务状态编排层定期扫描超时未完成的任务做补偿。这套设计虽然多了一次查询但可靠性高了一个量级。4.2 Agent状态同步失败别依赖内存早期我们用框架自带的内存态来保存Agent当前对话历史。单机跑没问题几个节点并发也没问题一旦多个执行器实例同时工作内存态就完全不可靠了。最典型的问题是两次流程中途重启Agent忘了自己干到哪一步直接重新开始用户收到两份回复。解决办法是把Agent的上下文状态全部外置到Redis和PostgreSQL每轮交互结束都同步一次。框架本身支持持久化和恢复但业务上真正需要的状态同步其实发生在编排层——每个节点执行前后编排层都会把关键数据物化确保任何节点挂了都能从最近的持久化点恢复而不是从头再来。4.3 重试风暴每个Agent都在努力重试多环节流程里的另一个隐患是重试风暴。模型调用偶尔超时很正常Agent内部做了重试也没什么问题。但多个Agent同时失败、同时重试重试窗口重叠模型服务一下子被打到限流然后引发更大面积的重试。我们压测时经历过一次本来只是模型服务闪断三秒结果系统自动重试把负载放大了20倍。最终团队定下三条规矩第一不同环节的重试次数按重要性差异化配置核心环节最多三次辅助环节最多一次第二统一开启指数退避加抖动不让重试请求在同一秒打出第三全局加一层熔断一旦任务失败率超过阈值就停止分发新任务等人为确认。在代码注释里我们会写清楚哪些工具是幂等的、哪些不是因为幂等是重试的前提。非幂等工具在任何情况下都不允许自动重试只能标记为需要人工介入。4.4 上下文传递别让状态变成面条代码多Agent协作中常用的数据传递方式是互相传完整上下文这在初期很爽后期就变成噩梦。一个节点往上下文里塞一段数据下一个节点又叠一段到了第五个节点上下文里堆满了无用字段每次传输都带上全部内容token消耗直线上升排查问题时根本不知道当前值是从哪一层来的。我们后来规定编排层定义一份数据契约每个节点只允许读取契约中声明的输入字段也只能写入契约中声明的输出字段。超出契约的数据必须显式声明并走独立的数据通道不允许直接塞进上下文。这条规则一开始会让人不习惯但两个月后回头看系统的可维护性提高了一个档次。4.5 人工审批节点怎么嵌入另一个值得展开讲的点是人工审批节点。我们的流程里有几个环节需要人工确认后才能继续一开始做得特别简陋就是一个状态卡住加一个定时轮询检查。后来发现审批不只有同意/拒绝两种结果还有打回修改和加签转派。按原来那套设计根本表达不了。重构之后编排层把审批节点也建模为一种特殊节点审批动作作为该节点的外部输入事件。审批人不同操作对应不同的事件事件带着目标节点信息状态机根据事件决定是回到前序节点还是跳到后序节点。这套表达比通用框架的human-in-the-loop要灵活多因为它不是简单暂停/恢复而是让审批动作真正参与流程路由决策。5. 可观测性与性能调优的实测经验5.1 一条Trace贯穿两套体系前面提到过纯框架阶段日志割裂的问题混合架构必须在一开始就解决它。我们的方案是统一引入trace_id从用户请求进入编排层开始生成之后每一步、每一次模型调用、每一次工具执行、每一次状态变更都带上这个trace_id。日志收集端把编排层的状态流转日志和框架内部的执行日志汇聚到同一个搜索平台通过trace_id可以完整串联一条工单从进来到结束的全过程。实测下来之后排查问题的时间比之前缩短了七成。这个收益远远超出预期强烈建议哪怕项目再小也把trace_id这个习惯养好。5.2 状态事件驱动埋点而不是日志字符串刚开始做可观测性时我们依赖日志文本去匹配节点行为比如搜索某个关键字看看节点是不是失败了。后来发现这种方式在复杂流程下根本不够用因为同样的失败有多种原因关键字匹配不到上下文。改造方案是把编排层每个节点的状态变化做成结构化事件包含节点ID、节点类型、流转前后状态、耗时的完整信息统一发到事件中心。想看某个节点最近执行得稳不稳直接按节点ID查事件流而不是翻日志。同时把模型调用次数、token消耗、工具调用耗时都作为事件字段打点成本核算也有数据支撑。5.3 线程池调优LLM慢不代表你要阻塞我们早期犯过一个性能错误编排层调度器用固定线程池处理任务线程数设小了任务排队设大了模型服务被并发请求打爆。后来把调度器和执行器彻底解耦调度器只负责任务分发不阻塞等待执行结果执行器用独立的异步队列消费任务并发上限单独控制。对每类工具调用也设置了不同的超时时间模型调用耗时通常几十秒但缓存查询必须在几百毫秒内返回两者绝不能用同一个超时阈值。之前统一超时导致快工具白白等待慢工具整体吞吐被拖垮。拆开之后单节点平均耗时下降了约三成整个流程的P99时延从几十秒压到了十几秒。5.4 token成本混合架构并不天然省钱最后提醒一句成本问题。混合架构并不能天然降低token开销甚至因为多Agent之间的上下文流转增多可能导致整体token消耗比单Agent方案更高。我们在生产环境做了一轮削减对每个节点限定最大输出长度对上下文做裁剪让Agent只看到必需信息同时对流程中可不调用模型的节点做了规则化替代。比如简单的字段拼接和格式判断完全不用模型参与用代码直接处理。整体token成本降了四成而业务效果几乎没变。在排查慢节点时那个人工审批环节的等待时间是最常被忽视的瓶颈——系统设计再快如果审批人一天后才点按钮全链路时长照样很难看。这属于流程治理问题跟技术架构无关。项目上线三个月最大的体会是架构选型不存在最好只有在约束下最合适。框架负责把Agent内部的复杂度藏起来自研编排负责把业务复杂度显式表达出来两边各管各的边界。将来如果再做一个多智能体项目我会先划分流程资产和技术资产再决定哪些给框架、哪些自己持有。这条路不一定适合所有人但思路大概是通用的。
RELATED

相关推荐

AI系统设计核心:从数据管道到推理服务的完整架构

AI系统设计核心:从数据管道到推理服务的完整架构

先想清楚:AI系统设计与传统系统设计到底差在哪以前带过一个小团队,大家写了好几年后端,自认为系统设计那套东西已经滚瓜烂熟了:接口怎么拆、缓存怎么放、消息队列怎么用、数据库怎么分库分表。直到某次项目评审,要设计…

📅 2026/10/13 8:37:35
券商系统压力测试背后的关键:中间件如何决定系统韧性

券商系统压力测试背后的关键:中间件如何决定系统韧性

券商系统的压力测试,这几年已经成了每年雷打不动的“大考”。新的行业要求明显不只是“扛住高并发就算过关”那么简单,而是把峰值吞吐、故障恢复速度、数据一致性放在同一个考核面里看:系统不只在极端流量下不能垮,还要在故障出现…

📅 2026/10/13 8:37:35
压力测试新规下,中间件如何铸就券商系统韧性?

压力测试新规下,中间件如何铸就券商系统韧性?

券商系统最怕两件事:一是行情一火爆就被客户在社交平台上刷屏吐槽,二是监管压力测试新规落地后,自己交不出一份像样的"体检报告"。压力测试这几年已经从"选做题"变成了"必答题",监管层对信息系统稳…

📅 2026/10/13 8:37:35
MORE NEWS

更多资讯

📰

AI写的PowerShell脚本一跑就崩?根因分析与实用提示词模板

前几天帮朋友排查一个调度任务,卡在一个PowerShell脚本上,AI一口气生成了四十多行“看起来很完整”的代码,结果跑起来第一行就报“术语无法识别”,后面全部白给。这不是我第一次见到AI写的PowerShell翻车了。它给出的命令确实存在…

📰

基于OpenCV的单目与双目相机测距:标定、视差与精度实践

简介:一套基于Python和OpenCV的普通相机图像测距系统资料包,面向计算机视觉与立体成像方向的开发者和学习者,解决通过普通相机拍摄图像实现精确距离测量的问题。系统涵盖单目相机标定校正、双目相机空间位置关系标定、左右视图视差计算与深度…

📰

dplyr 值映射重编码:深入解析 `recode_values()` 与 `replace_values()` 的语义、类型安全与防御性编程

数据分析 【免费下载链接】dplyr dplyr: A grammar of data manipulation 项目地址: https://gitcode.com/gh_mirrors/dp/dplyr 点击查看 免费下载 recode_values() 与 replace_values() 是 dplyr 1.2.x 引入的"按值匹配"重编码函数族:前者用…

📰

基于 Rust 的 Farm TailwindCSS 插件:配置文件加载与工具类生成原理(@farmfe/plugin-tailwindcss 2.0.0-beta.1)

前端构建构建工具开发工具 【免费下载链接】farm Extremely fast Vite-compatible web build tool written in Rust 项目地址: https://gitcode.com/gh_mirrors/fa/farm 点击查看 免费下载 导读 farmfe/plugin-tailwindcss 是 Farm 官方提供的 Rust 原生 Tailwind…

📰

Docker私有镜像仓库:稳、快、准、可控的容器交付中枢

1. 这不是“搭个仓库”那么简单:Docker私有镜像仓库到底在解决什么问题?“Docker私有镜像仓库搭建”这八个字,看起来像一句运维手册里的标准操作指令,但如果你真把它当成“照着文档敲几行命令就能完事”的小任务,大概率…

📰

Qt与SQLite开发实战:轻量级桌面应用数据存储方案

1. 为什么选择QtSQLite组合在桌面应用开发中,数据持久化是绕不开的话题。我经历过多个需要本地存储的中小型项目,从早期的文件存储到后来的各种数据库方案,最终沉淀下来的黄金组合就是QtSQLite。这个组合特别适合需要轻量级数据存储的场景&am…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬