Java 转 Agent 开发之路(七):多 Agent 协作、框架选型与评测——从单 Agent 运行时到工程化体系
前六篇从模型接入一路走到编排运行时,完成了单 Agent 的完整装配。但一个单 Agent 运行时解决的是“一个 Agent 如何被正确执行”,它没有回答接下来必然浮现的三个问题:当一个 Agent 的工具多到选不过来、上下文长到跟不住时,要不要拆成多个 Agent?拆完之后用什么框架承载?拆出来的系统又怎么知道它“还是对的”?
这一篇从三个角度切入:架构模式(多 Agent 协作的适用边界与代价)、框架选型(Java 生态中 Spring AI、LangGraph4j、Spring AI Alibaba 的分工)、评测与可观测性(如何让 Agent 系统的行为可回归、可归因)。最后回到一个更根本的判断:Java 工程师在这场转型中真正不可替代的能力是什么。
一、先厘清边界:Advisor 链管“一次调用”,Agent 运行时管“一个服务的治理”
第六篇的核心结论需要在这里再确认一次,因为它是讨论多 Agent 的前提。
Spring AI 2.0 把工具调用循环从 ChatModel 的内部实现提升为 advisor 链的一等公民。在 1.x 中,每个 chat model 实现都藏着一个私有的工具执行循环,功能上能用,但无法挂载、无法观测中间步骤、无法与其他行为组合。2.0 的 ToolCallingAdvisor 是一个递归 advisor:它反复重新进入下游链,直到模型产出不含工具调用的响应为止。链中的其他 advisor 能否看到每一次工具往返,取决于它相对于 ToolCallingAdvisor(默认 order HIGHEST_PRECEDENCE + 300)的位置——在外面只看到最终结果,在里面能看到每一次迭代。
这套机制在单次 ChatClient 调用的尺度上是完整的。但它有一个默认的容器边界:一个 ChatClient 实例、一条 advisor 链、一个进程内的执行。当多个 Agent 需要协作时,问题从“链上 advisor 怎么排序”变成了“Agent 之间怎么传递状态、谁来决定路由、一个 Agent 的失败如何不拖垮整个任务”。这些不是 Advisor 链能回答的问题,它们属于运行时治理的范畴。
多 Agent 协作不是“多写几个 ChatClient”。它首先是一个架构决策,然后才是一个框架选择。
二、多 Agent 协作:四种协同模式与它们的真实代价
Spring AI Alibaba 将多 Agent 协作归纳为四种核心模式:顺序执行、并行执行、LLM 路由、监督者(Supervisor) 。这个分类本身不复杂,但每一种模式的工程代价差异很大,选错模式比选错框架更伤。
顺序执行:最简单的管道,也是最容易被误用的
Agent A 的输出作为 Agent B 的输入,依次传递,最后一个 Agent 返回结果。这种模式的优点是确定性强——每一步的执行者、输入、输出都是固定的,调试和回归都容易。缺点是没有动态性:如果 B 在执行中发现 A 的输出有误,它无法让 A 重做,只能在自己的输出中“带着错误往前走”。
顺序执行适合步骤之间依赖关系严格、每一步的职责边界清晰的任务,比如“检索文档 → 生成草稿 → 事实核查”。它不适合那些需要“回头”的任务。把需要反思和修正的任务硬塞进顺序管道,反思逻辑就只能塞进某一个 Agent 的 Prompt 里,重新回到“内隐 Planning”的老路。
并行执行:吞吐量的代价是合并成本
同一输入分发给多个 Agent,各自产出结果后合并。并行在子任务相互独立时是合理的,比如从多个数据源同时检索、从多个视角同时分析。但并行的代价不在执行阶段,在合并阶段。多个 Agent 的输出可能在事实上冲突、在粒度上不一致、在格式上不兼容。如果合并逻辑只是一段“把所有结果拼起来”的 Prompt,那么并行带来的吞吐收益很可能被合并阶段的质量损失抵消。
LLM 路由:把选择权交给模型,也把不确定性交给模型
一个路由 Agent 根据用户输入决定把任务交给哪个下游 Agent。这看起来是“专业化分工”的自然实现,但它引入了一个新的失败模式:路由错误。路由 Agent 本身也是一个 LLM 调用,它的判断同样受 Prompt 质量、工具描述清晰度和上下文长度的影响。当路由 Agent 选错下游时,下游 Agent 会在一个错误的前提下工作,而且它通常没有能力识别“我本来不该被调用”。
路由模式适合类别边界清晰、下游 Agent 数量有限的场景。当下游 Agent 超过一定数量,或者类别之间存在语义重叠时,路由的准确率会下降,维护成本会上升。
监督者(Supervisor):中心化协调的收益与单点负担
监督者模式由一个 Supervisor Agent 作为协调中枢,动态决定调用哪些 Worker Agent。在 Spring AI Alibaba 的实践中,监督者模式通常通过将子 Agent 封装为工具来实现:Supervisor 持有 ReactAgent 实例并配置 AgentTool,子 Agent 是独立的 ReactAgent,拥有自己的 System Prompt 和专用工具。子 Agent 不直接与用户对话,只执行任务并返回结果;控制流是集中式的,所有路由都经过 Supervisor。
监督者模式的优点是协调逻辑集中、可审计:你能在一个地方看到路由决策的完整轨迹,子 Agent 的失败可以在 Supervisor 层统一处理。代价是Supervisor 成为单点:它的上下文会随着子 Agent 数量和交互轮次增长而膨胀,它的决策质量直接决定整个系统的上限。如果一个任务需要 Supervisor 做十几次路由决策,它的 Prompt 和上下文管理本身就是一项工程负担。
一个务实的选择原则:多 Agent 协作的收益来自上下文隔离和工具集隔离,而不是“Agent 数量本身”。当单个 Agent 的工具多到选择准确率下降、上下文长到关键信息被淹没时,拆分才有意义。如果拆分后每个子 Agent 仍然需要完整的全局上下文,那么拆分只是把复杂度从 Prompt 转移到了通信层,没有真正降低系统的认知负担。
三、框架选型:Java 生态中三个“不同层”的框架
多 Agent 协作需要承载它的框架,但 Java 生态中的 AI 框架并不在同一个抽象层上。把它们放在“谁更好”的框架下比较,本身就是选型中最常见的错误。
2026 年初的 Java AI 框架格局大致是:Spring AI 提供模型接入和 Advisor 链的基础抽象,Spring AI Alibaba 在 Spring AI 之上叠加 Graph Core 和 Agent Framework,LangGraph4j 提供框架无关的有状态工作流编排,LangChain4j 主打开发体验和多模型支持。它们的关系更接近分层互补,而不是互斥替代。
Spring AI:模型接入层与 Advisor 骨架
Spring AI 的定位是Spring 生态中的模型接入和调用编排基础。它提供了 ChatClient、Advisor 链、工具调用、结构化输出、ChatMemory 等核心抽象。第六篇讨论的 Advisor 顺序、递归循环、Token 累积,都是在这一层完成的。
Spring AI 2.0 的 ToolCallingAdvisor 把工具循环变成了可组合的链上组件,这使得自定义的 Planning、Reflection、Memory 逻辑可以以 advisor 的形式插入,而不需要 fork 框架或绕开抽象。这是 Spring AI 在单 Agent 运行时层面的核心价值。
Spring AI Alibaba:在 Spring AI 之上做“平台层”
Spring AI Alibaba 的架构可以看作三层:底层是 Spring AI 的 ChatClient、Tool Calling、RAG、Memory;中间是 Graph Core,提供基于 DAG 的工作流编排、状态管理和断点恢复;上层是 Agent Framework,提供 Skills、A2A 协议和多 Agent 协作模式。
如果 Spring AI 回答的是“一次 Agent 调用怎么执行”,Spring AI Alibaba 回答的是“多个 Agent 组成的工作流怎么被定义、状态怎么在节点间流转、断点恢复怎么做”。它的监督者模式、顺序/并行/路由模式,都是在 Graph Core 的 DAG 语义上实现的。代价是它引入了一套自己的状态模型(OverAllState、占位符、节点),学习曲线比纯 Spring AI 更陡。
LangGraph4j:框架无关的状态机编排
LangGraph4j 的定位更窄也更明确:有状态、多智能体的工作流编排引擎,同时支持 LangChain4j 和 Spring AI 两种底层。它不提供模型接入,不提供 RAG,不提供 Memory——它只管“图的执行和状态管理”。它的核心价值是状态机语义:节点、边、条件路由、断点恢复、并行分支。
如果你已经有一个基于 Spring AI 的 Agent 运行时,但需要把多个 Agent 组织成一个有循环、有条件分支、可中断恢复的工作流,LangGraph4j 是一个比在 ChatClient 外面手写 while 循环更合适的承载层。但如果你需要的是模型接入、工具调用、记忆管理这些基础能力,LangGraph4j 本身不提供,你仍然需要 Spring AI 或 LangChain4j。
一个常见的选型判断是:用 Spring AI 做单 Agent 运行时,用 LangGraph4j 或 Spring AI Alibaba Graph 做多 Agent 工作流编排。两者不是替代关系。真正需要警惕的是“在 Spring AI 里手写一套工作流状态管理”,或者在 LangGraph4j 里重复实现工具调用循环——这两者都是在框架已经覆盖的层面上重新造轮子。
四、评测:没有轨迹断言的多 Agent,是在盲飞
多 Agent 系统比单 Agent 更难评测,根本原因在于中间层的增加放大了误差传播。路由错误会让下游 Agent 在错误前提下工作,合并阶段的冲突会掩盖子任务的正确性,Supervisor 的上下文膨胀会让它逐渐偏离目标。如果只看最终答案,你无法区分“答案是错的因为子 Agent A 错了”和“答案是错的因为 Supervisor 选错了 A”。
2026 年的 Agent 评测实践正在形成一个清晰的分层共识:确定性断言层与 LLM Judge 语义层必须分开,轨迹断言负责“路径对不对”,LLM-as-judge 只覆盖“读起来好不好”。
轨迹断言:多 Agent 系统的最低回归门槛
轨迹断言断言的是执行路径:调用了哪些工具、调用的顺序是什么、参数是否合法、路由是否走了预期的分支、是否在达到 max-iterations 时终止、租户过滤是否生效。这些是确定性的,不依赖模型输出的语义判断,可以作为每个 PR 的硬性门槛。
在多 Agent 场景中,轨迹断言的价值进一步放大。它可以直接回答“Supervisor 是否把退款请求错误路由到了查询 Agent”“子 Agent 是否在无权限的情况下被调用”“合并阶段是否遗漏了某个子 Agent 的输出”。这些问题的答案不在最终回复的文本里,在轨迹里。
LLM-as-judge:只产出弱信号,不充当硬门槛
LLM-as-judge 适合评估那些轨迹断言无法覆盖的维度:回复的完整性、语气、要点覆盖率。但 2026 年的实践已经明确了一系列必须用工程手段压制的已知问题:judge 偏好冗长回答,对策是在 rubric 中显式写入长度约束并按要点覆盖计分,而不是给整体印象分;judge 不可复现,对策是 temperature 归零、rubric 版本化归档、保留原始打分供抽查;judge 与被测模型同族耦合,对策是 judge 模型与被测模型解耦,且judge 只产出弱信号报表,不作为 PR 合并的硬门槛。
一个关键的分工是:轨迹断言回答“Agent 有没有按规矩办事”,LLM judge 回答“办得漂不漂亮” 。把两者混为一谈,要么让 judge 承担了它不该承担的确定性职责,要么让轨迹断言试图判断它无法判断的语义质量。
Mock 的边界:下沉到 HTTP 层,而不是 mock ChatModel
单 Agent 时代的反模式——@MockBean ChatModel 然后断言返回字符串——在多 Agent 场景中更加有害。mock 切在 ChatModel 边界,等于把整条 Agent 链路的装配正确性排除在测试之外。
正确的 mock 边界仍然是HTTP 层:MockWebServer 或 WireMock 打桩模型供应商端点,让真实的 Advisor 链、真实的工具循环、真实的多 Agent 路由逻辑跑起来,只把“模型返回什么”替换为可控的响应。这样测的是编排的正确性,而不是一段字符串的传递。Mock 评测在每个 PR 运行,不打真实模型,作为硬门槛;真实模型评测每夜或发布前运行,覆盖终答质量、judge 弱信号和成本时延,不通过则阻止发布或触发回滚。
五、可观测性:Agent 的 span 不能只覆盖“一次模型调用”
Spring AI 2.0 内置了 Micrometer instrumentation,自动生成 gen_ai.client.operation、gen_ai.client.token.usage 等指标,遵循 OpenTelemetry GenAI 语义约定。这覆盖了单次模型调用的粒度,但多 Agent 系统的可观测性需求远不止于此。
递归循环需要独立子 span,而不是累积后覆盖。 一个 Planning 循环跑了 3 轮、工具循环跑了 5 次往返、Supervisor 做了 4 次路由决策,最终响应只报告最后一轮的 Token,和报告整条链的真实成本,是两件事。UsageAccumulator 解决的是报告层面的累积,但定位“哪一轮 Planning 最贵”“哪个子 Agent 的工具调用最慢”需要的是每一次迭代的独立 span。
Agent 级 span 需要语义规范,而不只是“HTTP 调用链”。 OpenTelemetry 的 GenAI 语义约定已经覆盖了 Agent、LLM、Tool 等 span 类型,阿里与蚂蚁的 LoongSuite 规范在此基础上进一步抽象了 Agent Entry/Step Span 和 Skill 语义——Skill 既不是单一的 Tool 调用,也不是一次完整的 Agent 执行,而是业务功能聚合层的一个可观测单元。对于多 Agent 系统,这意味着 trace 的粒度需要从“一次 LLM 调用”上移到“一次 Agent 交接”“一次 Supervisor 路由决策”“一次子 Agent 任务”,否则 trace 会退化成大量孤立的模型调用记录,无法回答“为什么走了这条路”。
PII 掩码必须在导出层完成,而不是靠“不要记录 prompt”来回避。 生产环境打开 prompt/completion 日志会暴露租户数据和 PII。可观测性 starter 的做法是在 SpanExporter 层面做 PII masking:信用卡号经过 Luhn 校验和发卡行前缀识别后才掩码,电话号码覆盖常见格式,敏感字符串在离开进程之前就已经被脱敏。这比在应用层“小心不要 log 敏感信息”可靠得多,因为日志泄露通常不是有意的,而是某个异常堆栈把整个请求体带进了日志。
六、回到转型本身:Java 工程师的能力迁移路径
这一篇讨论的三个角度——多 Agent 架构、框架选型、评测可观测性——最终都指向同一个判断:Java 工程师转 Agent 开发,补的是上层,守的是底座。
需要补的短板集中在三块:上下文工程、Agent 编排、评测与可观测性。上下文工程不是“把 Prompt 写长”,而是决定什么信息在什么时刻进入上下文、什么信息该被压缩或丢弃;Agent 编排不是“写一个 while 循环调模型”,而是理解 Advisor 链、状态机、递归循环的控制流和终止条件;评测与可观测性不是“加一个日志”,而是把轨迹断言、分层评测、Token 归因、PII 掩码做成流水线的一部分。
而 Java 工程师原有的能力,恰恰是 Agent 从 demo 走向生产时最稀缺的那一层。企业真正要把 Agent 上线,最后处理的仍然是权限、状态、超时、成本、审计、回滚这些问题。多租户隔离需要在 ToolContext 中传递租户 ID 并在工具方法内部做参数级鉴权,而不是信任模型生成的参数;ChatMemory 需要按 conversationId 和租户 ID 双重分区,而 Spring AI 不会自动完成这个隔离;MCP 工具需要三级执行权限(READ / WRITE / DANGEROUS)和危险操作的人工确认;JdbcChatMemoryRepository 不支持工具调用消息,如果需要工具历史,就必须换用支持工具消息的存储或在应用层做合并。
这些不是“AI 特有的新问题”,它们是分布式系统和多租户 SaaS 的老问题,换了一个执行主体。模型从“被调用的服务”变成了“做决策的组件”,但隔离、审计、预算、回滚这些约束一个都没有消失。Java 工程师的优势不在于比谁更会写 Prompt,而在于知道这些约束应该在哪个层面被强制执行,而不是交给模型自觉。
七、收束:Agent 工程化的三个不可回避的判断
这一篇从多 Agent 协作讲到框架选型,再到评测和可观测性,核心可以收束为三个判断。
第一,多 Agent 不是目标,上下文隔离和工具集隔离才是。 顺序、并行、路由、监督者四种模式各有明确的适用边界和失败模式。拆分之前先问:拆完之后每个子 Agent 是否真的只需要局部上下文?如果答案是否定的,拆分只是把复杂度搬到了通信层。
第二,Java 生态的框架是分层的,不是竞争的。 Spring AI 做模型接入和 Advisor 骨架,LangGraph4j 做状态机编排,Spring AI Alibaba 在 Spring AI 之上做 Graph 和 Agent Framework。选型的正确姿势是确认自己的问题在哪一层,而不是问“哪个框架最好”。
第三,评测和可观测性不是上线前的最后一步,是运行时设计的一部分。 轨迹断言是每个 PR 的硬门槛,LLM judge 只产出弱信号,span 的粒度必须覆盖 Agent 交接和路由决策,PII 掩码必须在导出层完成。没有这些,多 Agent 系统的行为漂移是无法被发现的。
系列到此,从一次 LLM 调用到多 Agent 工程化体系,地图的轮廓已经完整。如果继续往下走,值得单独深挖的方向包括:用 JdbcChatMemoryRepository 之外的支持工具消息的会话存储替换默认实现;把 Supervisor 的路由轨迹做成可回放的评测数据集;或者从零搭建一个带多租户隔离、轨迹断言流水线和 OTel GenAI 可观测性的最小企业 Agent 项目。这些是“从会写 Agent 到能交付 Agent 系统”之间最后一段路,也是 Java 工程师最能拉开差距的地方。
- 点赞
- 收藏
- 关注作者
评论(0)