news 2026/10/13 20:08:32

多智能体系统架构选型:从自研编排到混合架构的实践之路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
多智能体系统架构选型:从自研编排到混合架构的实践之路

多智能体系统的架构抉择,这两年几乎是做AI应用绕不过去的一道坎。我们团队在搭建一个面向企业内部知识助手项目时,就卡在"自研编排还是通用框架"这个岔路口上,反复论证了小两个月。一开始团队里偏向自研的人占多数,理由很朴素:框架抽象多、黑盒重,出了问题不好排查。可真等第一版纯自研编排层跑起来,我们又很快发现"什么都能控"和"什么都得控"是两回事。后来一步步把通用框架的成熟能力吸收进来,同时保住了自研层的核心掌控,才算理顺了这套系统。这篇文章就把我们这段纠结、试错、最终落地混合架构的过程原原本本写出来,给正在做同样抉择的团队一个参考。

1. 我们真正在纠结的,其实是这三件事

1.1 多智能体系统里,编排层到底负责什么

先交代一下项目背景。我们的系统不是那种跑通Demo就结束的玩具,而是要把多个大模型Agent接进真实的业务流程里。系统里有好几个分工不同的Agent:有的负责把用户的自然语言需求拆成结构化任务,有的负责从企业内部文档库里检索相关资料,有的负责写初稿,还有的负责按一套业务规则做质检。如果全系统只有一个Agent,问题很简单,一个循环调用就结束了。但当Agent数量上到五六个,彼此之间还有复杂的依赖关系,事情很快就失控了。

用户的一个问题进来,可能要依次经过"意图识别 → 任务拆解 → 并行检索 → 生成草稿 → 质检 → 修正 → 汇总出稿"这一长串流程。这中间有顺序执行,有并行调用,有条件跳转,有失败重试,还要随时准备停下来等人工确认。把这些"Agent之间怎么流转"的逻辑管理起来的东西,就是编排层。

具体拆开,编排层实际要干四类活:第一,流程路由,决定下一步该调用哪个Agent,走哪个分支;第二,状态管理,记住当前这轮任务执行到哪一步了、已经拿到了哪些中间结果;第三,资源控制,管理并发上限、限流策略、失败重试;第四,可观测性,把每一次Agent调用的输入输出、token消耗、耗时都记录下来。

这里我想多说一句:很多团队一上来不重视可观测性,觉得业务跑通就行。实际上多智能体系统上线之后,80%的排查时间都花在"看清某一次任务到底是怎么走的"这个问题上。没有一套好用的链路追踪,出了问题只能靠猜,效率极低。

1.2 那段时间我们评估过的几个典型选项

我们的候选方案大概可以归成四类:纯自研编排、纯通用框架、框架为主加局部自研、自研为主加局部框架。前两种是典型的"单选题",后两种本质上都是混合方案,区别只在于主导方是谁。

当时市面上的开源框架,比如LangChain、AutoGen、CrewAI这一类的,我们也简单跑过一轮。在跑Demo的阶段,所有人都会觉得框架很香:一个Graph定义下去,节点和边清清楚楚,自带重试和链路追踪,社区里还有一堆现成的Agent模板可以直接抄作业。可越往生产环境靠,越会发现框架在一些边缘场景下的行为是不可控的。

我们团队里一位后端经验很扎实的同事当时说过一句话:"框架是给你省时间的,不是给你省思考的。"这句话后来基本成了我们选型的指导思想。

1.3 一句话说清楚"为什么不能照搬别人的架构"

我后来跟团队打过一个比方:通用框架像一辆配置齐全的家用车,自研编排像自己攒的越野车。家用车省油、好开、维护成本低,但你要拉着设备进无人区,很多原厂限制就会让你很憋屈;自己攒的越野车,底盘高度、悬挂、动力都可以按需调整,但所有零件都得自己找,出故障也得自己扛。

多智能体系统的架构也一样,没有"绝对正确"的答案,只有"是否匹配你的业务约束"。我们当时梳理出三条硬约束:第一,业务流程会频繁调整,业务方可能一周改两次拆分规则;第二,部分流程对状态准确性有硬性要求,绝不能出现任务漏执行或重复执行;第三,部署环境是内网,不能依赖任何闭源云服务,也不能让框架偷偷联网。这三条约束,直接决定了后面混合架构的切分方式。

2. 自研编排:控制力拉满,但隐性成本远超预期

2.1 一开始我们为什么想全部自研

有几个很实际的原因,让团队在项目初期几乎一边倒地倾向自研。

第一是可控性。用框架时,Agent的调用顺序由框架的Graph结构决定,但Graph里某个节点如果出现异常跳转,你很难在框架层拦截下来做自定义处理。自研就不一样,所有路由逻辑都是自己的代码,任何一个环节都能插桩,出了任何问题都能在源码层面追到根。

第二是部署环境。我们的目标环境是内网,部分框架生态组件会在某些边缘功能里偷偷依赖外部服务,要一个个排查非常烦躁。虽然主流框架都支持离线部署,但"支持"和"好用"之间还有不小的距离,这个距离只能靠踩坑去填。

第三是团队惯性。我们团队里有几位后端功底很扎实的同事,对"自己造轮子"这件事有天然的信心。后来复盘的时候,我们都承认,这第三点其实是最危险的风险源:业务还没跑通,大家就已经陷入"我们要做一个优雅的编排引擎"的自我感动里了。

2.2 自研之后才会撞上的四堵墙

等到第一版自研编排层真正跑起来,我们很快撞上了四堵墙。

第一堵墙是状态管理。多Agent之间要传递的中间结果五花八门:有纯文本、有JSON结构化数据、有向量检索回来的片段,还有Agent自己维护的短期记忆。自研一个状态管理器,听起来不难,但实际要处理的东西极其琐碎,包括序列化、过期清理、断点恢复,还有不同数据类型的转换和校验。我们用了整整两周才把这些边缘情况基本收拾干净,而且后续还持续冒出新的状态同步问题。

第二堵墙是重试与幂等。LLM调用天然不稳定,同一个Prompt两次结果都可能有差异,甚至会返回完全没有按指令走的格式。我们一开始只做了简单的超时重试,结果某个Agent在重试时被重复调用了两遍,把同一笔业务处理了两次。在工单场景里这是实打实的事故。

第三堵墙是并发控制。多个用户同时发起任务时,每个任务都是一套完整的Agent执行流。并发上限定多少、超出的请求怎么排队、Agent执行期间的中间状态怎么隔离,这些都要自己设计。框架里一个线程池能解决的事,自研时要考虑非常多的边界条件,比如数据库连接池被Agent输出占满这种让人哭笑不得的问题。

第四堵墙是可观测性。框架里有现成的trace和debug面板,自研就什么都要从零开始画。我们花了不少时间接日志、做链路ID、把每次调用的输入输出落到存储里,工作量比预期大得多。而且等到系统规模大了以后,trace数据的存储和查询本身又是一个新问题。

2.3 一个"写起来很爽、跑起来很痛"的真实片段

举一个具体例子。我们第一版自研编排里有个动态路由模块,会根据前一个Agent的输出来决定下一个该调用哪个Agent。这个模块的核心代码其实就是几张映射表加跳转逻辑,写起来确实很优雅,当时我们还专门写了详细的注释,觉得这个设计非常干净。

但上线第一天就出了状况。一个Agent在生成结果时突然输出了大段重复文本,导致后续负责意图判断的Agent被误导,任务走到错误分支上,最后给用户返回了一份牛头不对马嘴的回答。这个问题本身是模型输出不稳定导致的,但真正放大了事故的是我们的编排层:这版自研路由完全没有输出校验机制,Agent给的任何脏数据都直接成了路由决策的依据。

如果是成熟的框架,通常会在节点之间提供输出格式校验和修正的钩子。我们自研的第一版没有这个设计,只能临时在路由逻辑里打补丁。补丁越打越多,路由代码从最初的几百行膨胀到上千行,后续几乎没人敢动那个文件——改一个分支就可能牵动三四处补丁。那次经历让我们真正意识到,自研带来的"自由"是有代价的,每一份自由背后,都得用额外的工作量去换。

3. 通用框架:加速器不是万能钥匙

3.1 框架带来的"真香"时刻

在自研编排的泥潭里挣扎了一阵子之后,我们决定认认真真做一次框架评估。当时选了一个社区活跃度很高的开源Agent编排框架,搭了一个小范围验证项目。说实话,真香的地方确实非常明显。

第一是Graph定义直观。用框架先定义节点,再定义节点之间的边,顺序、分支、并行、循环,一眼就能看明白。我们原先那套自研路由代码,换成Graph描述之后逻辑清晰了一个量级。新同学接手框架项目时,看一遍Graph大概就能说出整体流程。

第二是组件生态成熟。LLM调用、工具调用、向量检索、短期记忆,框架都有现成的封装。Prompt模板还提供了继承和叠加机制,不用自己从零手写一套模板管理方案。

第三是可观测性好。框架自带trace面板,能看到一次任务执行里每一步的调用耗时、token消耗、输入输出。这个能力正好补上我们自研时最头疼的那块短板,排障效率提升非常明显。

验证项目两周就做出来了,效果出乎意料地好。当时团队里几乎要达成一致:"干脆全部迁到框架上算了。"

3.2 上生产之后,框架开始"不听话"

但把验证项目往生产环境推的时候,问题一个接一个浮出来。

第一个问题是黑盒行为。框架的Graph里,节点与节点之间的状态传递遵循它自己的一套序列化规则。我们的Agent输出经常带超长文本、嵌套JSON,甚至二进制文件描述,框架序列化到第三四层节点时,经常出现内容被截断或者类型被强制转换的情况。查起来非常痛苦,因为问题不在我们的业务代码里,而在框架内部某个看不到的角落。

第二个问题是版本迭代。框架的版本更新非常频繁,有时候只是升一个小版本,Graph的行为就变了。我们的一个流程在框架升级后,某个节点的重试策略从"失败重试三次"悄悄变成了"失败直接抛出",差一点酿成线上事故。为了稳定,我们只能把框架版本锁死,但锁死的代价是后续的安全修复和新能力都进不来,心里一直悬着。

第三个问题是定制成本。我们有两条业务流程需要非常特殊的控制逻辑:一条要按业务日历做工作日和非工作日路由,另一条要等待外部系统的回调才能继续往下执行。这在自研里只是写一个if判断的事,但在框架里要么费劲找插件,要么直接改框架源码。改源码就意味着后续升级基本不可能,团队得长期背负一个自己维护的框架分支。

这三个问题加在一起,让我们彻底放弃了"纯框架"这条路线。但同样地,我们也不愿意退回纯自研的老路上去。这时候,混合架构才真正被摆到桌面上。

3.3 框架选型时容易被忽略的四个评估维度

如果你也在做框架选型,除了看功能、看社区活跃度,有几个容易被忽略的维度,我建议你重点考察。

第一,离线部署能力。别只看官网Demo,把你最核心的那条流程放到完全断网的测试环境里完整跑一遍,看哪些功能会悄悄失效。第二,状态序列化方式。把你的真实Agent输出丢进去,压测一下复杂数据类型在多层节点传递后会不会变形。第三,升级策略。去看这个框架的版本发布频率和破坏性变更的比例,太激进的框架在生产环境里不一定加分。第四,问题排查手段。框架有没有独立的链路追踪面板,支不支持自定义插桩,这对后续排障非常重要。这些维度我们当时评估得不够细,后面都变成了实打实的坑。

4. 混合架构到底怎么切:编排层拆成三条线

4.1 我们的目标架构长什么样

在纯自研和纯框架之间反复碰壁之后,我们最终确定了一个原则:"稳定的部分用框架,多变的部分用自研,连接处用契约来隔离。"

具体到落地,我们把整个编排层拆成了三条线。

第一条线是基础支撑线,负责LLM调用封装、向量检索、上下文记忆、重试策略、trace采集这些偏基础设施的能力。这一块我们最终交给了通用框架。原因是这一层的能力已经比较成熟,自己重写既不经济,也没有必要,而且框架的最新能力更新,我们还能持续白嫖。

第二条线是业务编排线,负责真正跟业务强相关的流程逻辑:任务怎么拆解、Agent之间怎么路由、哪一步需要人工审批、哪一步要调用外部系统。这一块我们坚持自研,写成一个轻量的流程引擎。核心只有状态机和策略表,刻意不做通用化,只服务我们自己的业务场景。这样业务方要调整流程时,我们只需要改策略表,不需要动底层引擎。

第三条线是契约适配线。它本身不产生业务逻辑,只在框架的通用能力和自研的业务流程之间做翻译。比如框架返回的Agent输出,要先经过契约层标准化,再交给自研流程引擎;自研流程引擎决定该调用哪个Agent时,也通过契约层把指令翻译成框架能识别的Graph调用。

这个拆法的关键点在于:框架的能力和自研的逻辑不直接纠缠,所有交互都经过契约层,而契约层的数据结构由我们自己定义、自己维护。这样未来即使换一个框架,核心业务逻辑都不用动,只替换适配层就行。

4.2 哪些模块坚持自研,哪些模块放心交给框架

我整理了一个简化的划分表格,供参考:

模块归属理由
LLM调用封装框架成熟、跨厂商适配做得好
向量管理与检索框架生态成熟,需重点评估离线部署
重试与限流策略框架通用能力,足够使用
Trace与日志聚合框架自研成本极高,没必要
任务拆解与路由自研强业务逻辑,变化频繁且不可预期
状态机与流程控制自研需要硬性掌控,零容忍失控
人工审批与外部回调断点自研框架的通用实现难以满足
业务对象序列化自研需要稳定契约,避免框架升级影响

这个划分不是一步到位的,中间调整过两次。最初我们曾把"任务拆解"也放到框架里,后来业务方一周改了三次拆解规则,每次都要改Graph定义,痛苦得不行。迁回自研之后,改动成本立刻降了下来。所以我们的经验是:凡是业务上会频繁变化、而且变化方式不可预期的部分,尽量自研;凡是技术上通用、变化缓慢的部分,尽量用框架。

4.3 连接处的契约设计:一个稳定的中间层

契约层听起来抽象,我直接给一段简化后的Python代码作为示意,这是我们契约层的核心思路之一。

# 契约层:统一框架与自研流程引擎之间的数据格式 from dataclasses import dataclass, field from typing import Any, Optional @dataclass class AgentTask: task_id: str agent_name: str # 由自研流程引擎决定调用哪个Agent inputs: dict # 传给Agent的输入参数 expected_output_schema: Optional[dict] = None config: dict = field(default_factory=dict) @dataclass class AgentResult: task_id: str success: bool data: Optional[Any] # 标准化后的输出数据 raw: Optional[str] # Agent原始文本,仅用于排障 token_usage: dict = field(default_factory=dict) def normalize_result(raw_output: str, schema: dict) -> AgentResult: """把框架返回的原始输出转成结构化数据,失败时抛业务异常。 自研流程引擎只认AgentResult,完全不感知框架内部细节。""" # 这里做宽容解析,先剥掉可能的Markdown围栏,再做JSON解析 # 解析失败时抛出带上下文信息的异常,方便trace排查 ...

这个设计保证了两个重要的事。第一,自研流程引擎里永远不出现框架的专用类型,将来换框架,只需要改契约层,核心逻辑一行都不用动。第二,框架那边的Agent输出必须先经过标准化清洗,再脏的模型输出,也进不了我们的状态机。这两个保证,是混合架构能稳定的基础。

5. 转型踩坑实录:混合架构不是一混就灵

5.1 坑一:框架升级就像换了一个产品

我们切到混合架构后,框架版本还停留在验证期的版本。三个月后,因为一个安全公告,我们被迫升级框架补丁版本。契约层代码没有来得及做充分适配,结果某个节点的输出格式从纯净JSON变成了"带着Markdown围栏的JSON代码块",契约层的解析器把围栏也当成了内容的一部分,一连串任务全部被污染。我们花了整整一个下午才定位到问题根源——不是业务代码改了,是框架输出了多包了一层。

那次事故让我们定下两条规矩。第一,所有框架升级,不管大版本小版本,都必须先在预发环境完整回放至少一周的真实流量,确认契约层兼容性之后才能上生产。第二,契约层解析器必须写"宽容解析",先剥掉可能的围栏再解析JSON,而不是默认框架永远会输出纯净数据。现在我们的解析器对输入格式的容忍度高了很多,反而更稳了。

5.2 坑二:状态同步的"双份真相"问题

混合架构下,自研流程引擎有自己的一套状态,框架的Graph也有它的内部状态。如果一个节点的执行结果在两套状态里不一致,后面所有判断都会出错。我们初期没有处理好这个问题,出现过"流程引擎认为任务已经完成,框架那边却还在等一个后续调用"的僵局,整个会话卡死,用户那边的请求一直挂起。

这个问题的本质是"双份真相"——同一件事被两个地方各自记了一笔账,且没有定义谁是权威来源。我们的解决方案是单一状态源原则:框架的Graph状态只当作执行记录,不参与任何业务决策;业务决策只读自研流程引擎的状态。实现上就是契约层每次事件都回写流程引擎状态,Graph本身不做条件路由,只做机械执行。现在无论框架内部状态怎么变,只要流程引擎的状态是对的,整个系统就不会走偏。

5.3 坑三:人在回路的设计,复杂度天差地别

多智能体系统里,有几条流程必须支持人工介入。比如质检Agent发现初稿有问题时,需要停下来等人工确认,确认通过后才能往下走。这个"人等机器"和"机器等人"的处理逻辑完全不同。

我们最初想用框架自带的交互节点来实现,发现每一轮的暂停恢复都得把整个Graph状态序列化保存,实现非常绕,而且很容易丢上下文。后来我们调整了设计:把"人工确认"也封装成一个AgentTask,由自研流程引擎统一控制调度。人工输入被包装成一次普通的事件注入,框架那边完全无感,只需要等待下一个AgentTask被触发即可。这个调整让人工审批链路稳定了很多,调试时也能在流程引擎的状态里直接看到"等人工"这个中间态。

6. 什么情况下你不该学我们

6.1 决策不是看"哪个最先进",而是看"哪个最匹配"

坦诚地说,混合架构不是银弹。如果你的系统只有两三个Agent、流程相对固定、团队人手也比较紧,直接用通用框架把业务跑起来,很可能是性价比最高的选择。混合架构的维护成本是实打实的:两套状态体系、一遍契约适配、框架升级带来的持续维护任务,这些都会占掉原本可以花在业务逻辑上的精力。

我们最终选混合架构,核心驱动力是三条:流程变动频繁、部署环境受限、对状态控制有硬性要求。如果你没有这三个约束,那"自研为主"或者"框架为主"都可能是更简单的答案。不要看别人说混合架构好,就强行往自己身上套。

6.2 给团队的选型清单

如果你正在做多智能体系统的架构选型,我建议用下面这个清单自查一遍:

  1. 你们的业务流程多久变一次?每周变还是每季度变?变化方式是可预期的增删节点,还是经常出现结构性调整?
  2. 部署机房里,框架的所有生态组件能否完整离线运行?有没有偷偷依赖外网的地方?
  3. 你是否需要精确控制Agent之间的状态流转,还是说"能跑通"就行?
  4. 团队里有没有人能在两三天内把框架源码的某个核心模块读明白?
  5. 出了问题,你能接受"问题可能出在框架内部"的排查成本和不确定性吗?

对这五个问题的回答,基本能判断出你适合纯自研、纯框架还是混合架构。我们每条都踩过,回头看,如果项目初期就认真做一遍这个自查,至少能省下三周的试错时间。

6.3 最后说一点我们踩坑之后的心得

架构选型这种问题,最怕的不是选错,而是选错之后没有留出回退的余地。我们在推进混合架构的过程中,始终保留了一个开关:契约层可以同时兼容"框架执行"和"自研执行"两种后端,切换只需要改一个配置。这个开关在转型期救了我们很多次,也让团队在争论的时候心态稳定了不少,因为不会担心"一旦走了这条路就回不了头"。如果你最后也决定走混合路线,我建议你把"可回退"当作第一原则来设计,别一上来就把自己焊死在某一种实现上。架构是服务业务的,不是用来证明谁的判断更正确的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/13 20:06:49

VoLTE语数分层实战:QCI承载级切换与频段专用车道设计

简介:本资源是一份面向5G网络优化工程师与通信运维技术人员的专业技术文档,聚焦VoLTE语音与数据业务协同优化这一核心难题,系统阐述语数分层策略的设计逻辑、参数配置及多场景验证效果。文档深入解析QCI1/QCI5/QCI9承载机制,详述L…

作者头像 李华
网站建设 2026/10/13 20:04:09

AI嵌入研发全流程:从需求分析到代码评审的智能化实践

1. AI Coding只是冰山一角:先放下对“自动写代码”的执念 这段时间我观察到一个很有意思的现象。身边不少人试过AI编程工具之后,第一反应是“补全代码挺快”,第二反应是“但这东西写不出我想要的业务逻辑”。然后他们得出结论:AI目…

作者头像 李华
网站建设 2026/10/13 20:01:29

VNWOA优化LSSVM超参数:工业RUL预测实战指南

简介:本资源是一套面向机器学习与智能故障诊断方向的MATLAB算法实现包,适用于高校研究生、算法工程师及工业智能运维从业者,聚焦于LSSVM模型超参数优化这一关键工程问题。压缩包共107个文件,以103个.m函数脚本为主(含t…

作者头像 李华
网站建设 2026/10/13 20:01:23

YOLOv5异常行为检测毕设资源包:从环境到调参全解析

简介:基于YOLOv5的异常行为检测本科毕业设计完整实战资料,面向计算机专业学生、毕业设计开发者及目标检测入门者。资源提供从环境搭建到模型训练、推理验证的全流程内容,适合用于课程设计、毕设答辩准备或作为工程项目参考。压缩包共212个文件…

作者头像 李华
网站建设 2026/10/13 20:01:18

中医食疗小程序开发:症状-食材-方剂三级映射实现

简介:本资源是一套完整的微信小程序毕业设计/课程设计实战项目,面向计算机相关专业学生及小程序初学者,聚焦中医食疗健康领域的功能实现与系统开发。项目采用B/S架构,后端基于JavaMySQL,前端为微信小程序,涵…

作者头像 李华