Spring AI Alibaba 多智能体(Multi-agent)实战:6 大协作模式 + 完整代码
一、前言:单个 Agent 越强,反而越菜?
兄弟们,先抛个扎心问题:
你是不是也遇到过这种情况——
- Agent 工具塞了十几个,模型挑工具挑到“精神分裂”;
- Prompt 越写越长,Token 烧得飞起,回答却越来越像“废话生成器”;
- 同一个 Agent 又要写代码、又要写诗、还要算命,最后活成了“四不像”。
别急着换模型,大概率是 架构问题,不是模型问题。
Spring AI Alibaba 的多智能体(Multi-agent)框架,就是来治这种“全能 Agent 病”的。把一个超级 Agent 拆成多个专业 Agent,再用合适的协作模式串起来,效果往往立竿见影。
这篇文章,我会结合自己 demo 仓库里的 MultiAgent 模块,把 6 种主流多智能体协作模式掰开揉碎讲清楚:
| 序号 | 模式 | 一句话理解 |
|---|---|---|
| 1 | 顺序执行(Sequential) | A 干完给 B,B 干完给 C,一条流水线 |
| 2 | 并行执行(Parallel) | 三个小弟同时干活,老大最后汇总 |
| 3 | 路由(LlmRouting) | 让 LLM 当“前台”,自动分诊到对应专家 |
| 4 | 监督者(Supervisor) | 派一个“项目经理”,动态调度多个小弟 |
| 5 | 自定义条件(Customized Conditional) | 不靠 LLM,靠规则关键词精准路由 |
| 6 | 混合模式(Compound) | 监督者里套路由,复杂业务直接起飞 |
这坑我替你踩过了,下面直接上硬菜。
二、环境速览
先把家底亮一下,方便后面所有代码直接跑:
| 项目 | 内容 |
|---|---|
| JDK | 17 |
| Spring Boot | 3.x |
| Spring AI Alibaba | 1.0.x |
| ChatModel | DashScope(通义千问)/ Ollama 均可 |
| 关键依赖 | spring-ai-alibaba-agent-framework |
核心 Maven 依赖:
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-agent-framework</artifactId>
<version>1.0.0</version>
</dependency>
别急着 Ctrl+C / Ctrl+V,先把场景看完。
三、什么是多智能体(Multi-agent)?
写正文之前,先把“多智能体”这个概念压实。
不然你后面看到SequentialAgent、LlmRoutingAgent一定会一脸懵。
3.1 一句话理解
Multi-agent 就是把一个“什么都干”的大 Agent,拆成多个“专精一门”的小 Agent,再按业务场景拼成一个协作工作流。
简单说:从“一个人干所有事”变成“一个团队协作”。
3.2 官方定义
Multi-agent 将复杂的应用程序分解为多个协同工作的专业化 Agent。与依赖单个 Agent 处理所有步骤不同,Multi-agent 架构允许你将更小、更专注的 Agent 组合成协调的工作流。
用人话翻译一下:
| 单 Agent 架构 | Multi-agent 架构 |
|---|---|
| 一个 Agent 身兼数职 | 每个 Agent 只干一件事 |
| 工具塞一坨,模型挑花眼 | 各 Agent 工具互不干扰 |
| Prompt 越写越长 | 每个 Agent 提示词短而精准 |
| 一个 Agent 挂了全挂 | 单点失败不影响全局 |
3.3 什么时候必须上 Multi-agent?
别为了“架构高级”强行上 Multi-agent,单 Agent 能解决的就别拆。
以下三种情况出现,基本就是 Multi-agent 出场的信号:
- 单个 Agent 拥有太多工具,难以做出正确的工具选择决策
- 工具超过 10 个,模型就开始“工具选择困难症”了;
- 拆成多个 Agent,每个 Agent 只挂 2~3 个工具,模型瞬间清醒。
- 上下文或记忆增长过大,单个 Agent 难以有效跟踪
- 对话超过 20 轮,Token 烧得飞起;
- 拆成多个 Agent,每个 Agent 只关心自己这一段上下文,省 Token 又高效。
- 任务需要专业化(例如:规划器、研究员、数学专家)
- 业务天然有分工(写代码的、写文档的、测试的);
- 一个 Agent 没法同时是“全栈工程师 + 资深文案 + 顶级测试”,那就各司其职。
经验之谈:当你的单 Agent Prompt 超过 500 字还没把任务说清楚时,就该考虑拆了。
3.4 两大协作模式:Tool Calling vs Handoffs
Spring AI Alibaba 的 Multi-agent 框架底层支持两种核心协作模式,搞懂这个,后面 6 种具体实现就是"排列组合":
| 模式 | 工作原理 | 控制流 | 使用场景 |
|---|---|---|---|
| Tool Calling | Supervisor Agent 将其他 Agent 作为工具调用。"工具"Agent 不直接与用户对话——只执行任务并返回结果 | 集中式:所有路由都通过调用 Agent | 任务编排、结构化工作流 |
| Handoffs | 当前 Agent 决定将控制权转移给另一个 Agent。活动 Agent 随之变更,用户可以继续与新的 Agent 直接交互 | 去中心化:Agent 可以改变当前由谁来担当活跃 Agent | 跨领域对话、专家接管 |
怎么选?
| 问题 | Tool Calling | Handoffs |
|---|---|---|
| 需要集中控制工作流程? | ✅ 是 | ❌ 否 |
| 希望 Agent 直接与用户交互? | ❌ 否 | ✅ 是 |
| 专家之间复杂的、类人对话? | ❌ 有限 | ✅ 强 |
实战建议:可以混合使用两种模式——用 Handoffs 进行 Agent 切换,并让每个 Agent 将子 Agent 作为工具调用来执行专门任务。
本文的 Sequential / Parallel / LlmRouting / Supervisor / Customized / Compound,本质上都是这两种模式的具体实现。
3.5 本文的 6 种协作模式预告
下面要讲的 6 种模式,就是 Spring AI Alibaba 给我们提供的 “多人协作剧本”:
| 模式 | 协作方式 | 一句话类比 |
|---|---|---|
| Sequential | 流水线 | 工厂的传送带 |
| Parallel | 一起干 | 小组会议同时发言 |
| LlmRouting | 智能分诊 | 公司前台 |
| Supervisor | 动态调度 | 项目经理派活 |
| Customized Conditional | 规则路由 | 按地区转客服 |
| Compound | 混合编排 | 大型项目多团队协作 |
记住这张表,后面看到名字就知道在干啥。
四、模式一:顺序执行(Sequential Agent)
4.1 场景故事
让 AI 写一篇散文,然后让 AI 当评委修改润色。
这就是典型的 流水线:写 → 审 → 输出。
4.2 核心原理
顺序模式下,每个 Agent 按 subAgents 列表顺序执行,前一个 Agent 的 outputKey 输出,会作为状态写入 OverAllState,下一个 Agent 通过 instruction 占位符 {outputKey} 引用。
流程图

一图胜千言:Input → 第一个 subAgent → 第二个 subAgent → … → Output,一条道走到黑,谁也别想插队。
4.3 关键代码
参考文件:[SequentialAgentChat.java](file:///d:/project/learn/spring_ai_alibaba_demo/src/main/java/com/spring/ai/alibaba/agent/springaialibabaagent/MultiAgent/impl/SequentialAgentChat.java)
// 写作 Agent
ReactAgent writingAgent = ReactAgent.builder()
.name("writingAgent")
.model(reactAgentChatModel)
.description("你是一个专业的写作Agent")
.instruction("你是一个知名的作家,擅长创作高质量的文学作品。请根据用户的提问进行回答:{input}。")
.outputKey("article") // 关键:输出键名
.build();
// 审核 Agent
ReactAgent reviewAgent = ReactAgent.builder()
.name("reviewAgent")
.model(reactAgentChatModel)
.description("你是一个专业的审核Agent")
.instruction("你是一个专业的写作审核Agent,擅长审核和修正文学作品。" +
"请对文章进行评审修正:\n{article}," + // 占位符引用上一个 Agent 的输出
"最终返回评审修正后的文章内容;不要返回:'评审意见'等文字")
.outputKey("reviewedArticle")
.build();
// 顺序编排
SequentialAgent sequentialAgent = SequentialAgent.builder()
.name("sequentialAgent")
.description("根据用户给的内容写一个文章,然后审核文章,最后返回审核修正后的文章内容")
.subAgents(List.of(writingAgent, reviewAgent))
.build();
// 执行
Optional<OverAllState> result = sequentialAgent.invoke("帮我写一个100字左右的散文");
OverAllState state = result.get();
state.value("article").ifPresent(article ->
log.warn("写作Agent输出: {}", ((AssistantMessage) article).getText()));
state.value("reviewedArticle").ifPresent(reviewedArticle ->
log.warn("评审后文章: {}", ((AssistantMessage) reviewedArticle).getText()));
4.4 关键特性
顺序执行模式有 4 个核心特性,每个都值得背下来:
- 按顺序执行:Agent 按照
subAgents列表中定义的顺序执行
- 写在前面的先跑,写在后面的后跑,别想插队。
- 状态传递:每个 Agent 的输出通过
outputKey存储在状态中,可被后续 Agent 访问
- 这是顺序模式能"传话"的根本原因。
- 消息历史:默认情况下,所有 Agent 共享消息历史
- 简单说就是:后面的 Agent 能看到前面 Agent 的对话记录。
- 推理内容控制:使用
returnReasoningContents控制是否在消息历史中包含中间推理
- 想省 Token 就关掉,想看完整链路就打开,自己权衡。
这 4 个特性决定了顺序模式的边界:能传话、能共享,但没法并行、没法动态跳转。
4.5 占位符机制(核心中的核心)
Spring AI Alibaba 的 instruction 支持三种占位符:
| 占位符 | 说明 | 使用场景 |
|---|---|---|
{input} |
用户输入的原始内容 | 第一个 Agent |
{outputKey} |
引用其他 Agent 的输出 | 顺序执行中引用前序输出 |
{stateKey} |
引用状态中的任意键值 | 访问任意状态数据 |
看似简单,实则是多 Agent 数据传递的命脉。
4.6 自定义 Agent 上下文(高级玩法)
Multi-agent 设计的核心是上下文工程——决定每个 Agent 看到什么信息。Spring AI Alibaba 提供了细粒度的控制:
| 参数 | 作用 | 实战建议 |
|---|---|---|
instruction |
在当前 Agent 节点处插入新的问题说明,支持占位符 | 每个 Agent 的 instruction 要短而精准 |
returnReasoningContent |
控制子 Agent 的上下文是否返回父流程。设为 false,其他 Agent 看不到这个子 Agent 的推理过程,只能看到 outputKey 输出 |
想省 Token 就关掉 ,想看完整链路就打开 |
includeContents |
控制当前子 Agent 执行时,是只基于自己的 instruction 工作,还是带上所有父流程的上下文 | 设为 false 可以让子 Agent 专注于自己的任务,不受父流程复杂上下文的影响 |
outputKey |
指定输出内容的键名,可被后续 Agent 通过占位符引用 | 使用有意义的命名,如 article、reviewedArticle |
systemPrompt / instruction |
LlmRoutingAgent 和 SupervisorAgent 支持定制,用于覆盖默认实现,控制路由决策行为 | 路由准确性全靠这俩 ,后面章节专门讲 |
核心原则:系统的质量在很大程度上取决于上下文工程。目标是确保每个 Agent 都能访问执行任务所需的正确数据,不多不少。
4.7 适用场景
- 内容创作流水线(写 → 审 → 翻译)
- 数据处理管道(清洗 → 校验 → 入库)
- 多步骤业务编排(需求 → 设计 → 实现)
五、模式二:并行执行(Parallel Agent)
5.1 场景故事
“我是天蝎座,帮我分析一下我的星座、配对和星盘。”
一个用户问三个问题,为啥要排队回答?
并行模式:三个专家 Agent 同时上,结果最后汇总。
5.2 核心原理
所有子 Agent 同时接收同一份输入,各自执行完后再走 MergeStrategy 合并策略。
流程图

一张图看清 并行模式的本质:一个 Input 扇出到 N 个 subAgent,每个 subAgent 独立产出自己的 Output_1/Output_2/Output_3,最后由
MergeStrategy汇总。
三种默认合并策略
| 策略 | 行为 |
|---|---|
DefaultMergeStrategy |
拼接成键值 Map |
ConcatenationMergeStrategy |
拼接成单一字符串 |
ListMergeStrategy |
合并为 List |
5.3 关键代码
参考文件:[ParallelAgentChat.java](file:///d:/project/learn/spring_ai_alibaba_demo/src/main/java/com/spring/ai/alibaba/agent/springaialibabaagent/MultiAgent/impl/ParallelAgentChat.java)
ReactAgent constellationAgent = ReactAgent.builder()
.name("constellationAgent")
.model(reactAgentChatModel)
.instruction("你是一个星座分析大师。用户给的内容是:{input},请根据用户的内容分析星座。")
.outputKey("constellation")
.build();
ReactAgent pairAgent = ReactAgent.builder()
.name("pairAgent")
.model(reactAgentChatModel)
.instruction("你是星座配对大师。用户给的内容是:{input},请根据用户的内容配对星座。")
.outputKey("pair")
.build();
ReactAgent starDiskAgent = ReactAgent.builder()
.name("starDiskAgent")
.model(reactAgentChatModel)
.instruction("你是星盘大师。用户给的内容是:{input},请根据用户的内容分析星盘。")
.outputKey("starDisk")
.build();
ParallelAgent parallelAgent = ParallelAgent.builder()
.name("parallelAgent")
.subAgents(List.of(constellationAgent, pairAgent, starDiskAgent))
.description("并行执行多个创作任务")
.mergeOutputKey("parallel")
.mergeStrategy(deduplicationSummaryMergeStrategy) // 用自定义策略
.build();
5.4 进阶:自定义合并策略(重点!)
默认策略只能“傻拼”,但实际项目里,多个 Agent 输出经常有内容重复。怎么办?
自己写一个 MergeStrategy 接 LLM 做二次摘要去重。
参考文件:[DeduplicationSummaryMergeStrategy.java](file:///d:/project/learn/spring_ai_alibaba_demo/src/main/java/com/spring/ai/alibaba/agent/springaialibabaagent/MultiAgent/tool/DeduplicationSummaryMergeStrategy.java)
@Component
public class DeduplicationSummaryMergeStrategy implements ParallelAgent.MergeStrategy {
private final ChatModel reactAgentChatModel;
@Override
public Object merge(Map<String, Object> subAgentResults, OverAllState overallState) {
// 1. 聚合多 Agent 结果
String aggregated = aggregateSubAgentResults(subAgentResults);
// 2. 调一个总结 Agent 做二次去重
ReactAgent summaryAgent = ReactAgent.builder()
.name("deduplicationSummaryAgent")
.model(reactAgentChatModel)
.instruction("你是内容整合专家,擅长去重与摘要。输入:\n{input}\n" +
"请去除重复信息,整合输出一份结构清晰的综合报告。")
.outputKey("summaryReport")
.build();
try {
return summaryAgent.invoke(aggregated)
.map(state -> state.value("summaryReport").orElse(""))
.map(this::extractText)
.orElse("");
} catch (GraphRunnerException e) {
// 兜底:返回原始聚合
return aggregated;
}
}
// ... aggregateSubAgentResults / formatAgentOutput / extractText 略
}
这就是“看似能跑,其实已经埋雷”和“程序跑起来了,头发少了”的真实写照——不做二次去重,三个 Agent 输出的星座描述 80% 重复。
5.5 适用场景
- 多视角分析(星座/八字/紫微同时算)
- 多模态内容生成(标题/正文/标签并行产出)
- A/B 内容对比
六、模式三:路由(LlmRoutingAgent)
6.1 场景故事
“我梦见自己在大雾里开车……”(解梦)
“帮我分析下我的星座……”(星座)
“我是 1990-01-01 出生,帮我算下生命数字……”(数字密码)
每种问题对应一个专家 Agent,让 LLM 充当“前台分诊台”,自动判断该派给谁。
6.2 核心原理
LlmRoutingAgent 接收用户输入,调用 LLM 分析子 Agent 的 description,选择一个最匹配的子 Agent 执行。
流程图

一张图看清 路由模式的精髓:In → LLM Call Router(一次 LLM 调用决策走哪条线)→ 只选一个 LLM Call N → Out。
不是全选,是单选,虚线代表没被选中的路径。
注意:每次只选一个,不是全选。
6.3 关键代码
参考文件:[LlmRoutingAgentChat.java](file:///d:/project/learn/spring_ai_alibaba_demo/src/main/java/com/spring/ai/alibaba/agent/springaialibabaagent/MultiAgent/impl/LlmRoutingAgentChat.java)
ReactAgent constellationAgent = ReactAgent.builder()
.name("constellationAgent")
.model(reactAgentChatModel)
.description("你是一个专业的星座分析大师,擅长分析星座。") // 重要:路由靠这个判断
.instruction("你是一个星座分析大师,擅长分析星座")
.outputKey("constellation")
.build();
ReactAgent birthAgent = ReactAgent.builder()
.name("birthAgent")
.model(reactAgentChatModel)
.description("你是一个专业的生命数字密码分析大师,擅长分析生命数字密码。")
.instruction("你是一个生命数字密码分析大师")
.outputKey("birth")
.build();
ReactAgent zhugongAgent = ReactAgent.builder()
.name("zhugongAgent")
.model(reactAgentChatModel)
.description("你是一个专业的周公解梦大师,擅长解梦。")
.instruction("你是一个周公解梦大师")
.outputKey("zhugong")
.build();
LlmRoutingAgent llmRoutingAgent = LlmRoutingAgent.builder()
.name("llmRoutingAgent")
.model(reactAgentChatModel)
.description("根据用户需求智能路由到合适的专家Agent")
.subAgents(List.of(constellationAgent, birthAgent, zhugongAgent))
.build();
Optional<OverAllState> result = llmRoutingAgent.invoke("我梦见自己在一片大雾里开车,怎么也找不到回家的路");
6.4 关键特性
路由模式有 4 个核心特性,每个都值得背下来:
- 智能路由:LLM 根据输入内容和子 Agent 的描述自动选择最合适的 Agent
- 不用写
if-else,模型自己"看人下菜碟"。
- 灵活扩展:可以轻松添加新的专家 Agent,LLM 会自动识别并路由
-
加 Agent 不用改路由逻辑
,改
subAgents列表就行。
- 描述驱动:子 Agent 的
description非常重要,它告诉 LLM 何时应该选择该 Agent
-
description写不好,路由就废一半,下一节专门讲怎么写。
- 单次执行:每次请求只路由到一个 Agent 执行
-
不是"广播"是"派单"
,别指望 LLM 同时调多个。
这 4 个特性决定了路由模式的边界:能智能分诊,但没有状态记忆、不能多步串联。
6.5 路由准确性优化(避坑重点)
坑:为什么我的路由 Agent 经常选错?
罪魁祸首:description 写得太模糊!
反面教材:
description = "你是星座分析大师" // ❌ 太短,LLM 看不出区别
正确写法:
description = "专门处理星座分析问题,擅长分析星座运势、性格、配对。" +
"适用于用户问'我的星座怎么样'、'天蝎座配什么'等场景。" // ✅ 场景化
6.6 进阶:自定义 systemPrompt / instruction
除了靠 description 自动路由,LlmRoutingAgent 还支持通过 systemPrompt 和 instruction手动控制路由决策,这是官方文档里的高级玩法:
systemPrompt:设置路由决策的系统提示
替换默认系统提示,提供详细的决策规则和上下文:
final String ROUTING_SYSTEM_PROMPT = """
你是一个智能的内容路由Agent,负责根据用户需求将任务路由到最合适的专家Agent。
## 可用的子Agent及其职责
### constellationAgent
- 功能: 擅长星座分析
- 适用场景: 用户问星座运势、性格、配对
### birthAgent
- 功能: 擅长生命数字密码分析
- 适用场景: 用户问生命数字、数字密码
### zhugongAgent
- 功能: 擅长周公解梦
- 适用场景: 用户说"梦见"、"解梦"
## 决策规则
只返回Agent名称,不要包含其他解释。
""";
LlmRoutingAgent routingAgent = LlmRoutingAgent.builder()
.name("content_routing_agent")
.model(chatModel)
.systemPrompt(ROUTING_SYSTEM_PROMPT) // 关键:自定义系统提示
.subAgents(List.of(constellationAgent, birthAgent, zhugongAgent))
.build();
instruction:设置路由决策的用户指令
作为 UserMessage 添加到消息列表中,提供额外的上下文信息或特定的路由指导:
final String ROUTING_INSTRUCTION = """
请根据用户的需求,选择最合适的Agent来处理任务。
特别注意:
- 如果用户提到"星座"、"运势",选择 constellationAgent
- 如果用户提到"生命数字"、"数字密码",选择 birthAgent
- 如果用户提到"梦见"、"解梦",选择 zhugongAgent
""";
LlmRoutingAgent routingAgent = LlmRoutingAgent.builder()
.name("content_routing_agent")
.model(chatModel)
.instruction(ROUTING_INSTRUCTION) // 关键:自定义路由指令
.subAgents(List.of(constellationAgent, birthAgent, zhugongAgent))
.build();
实战建议:
systemPrompt定义路由决策的整体框架,instruction提供具体的路由指导。两个可以同时用,效果叠加。
6.7 适用场景
- 多领域客服(售前/售后/投诉自动分流)
- 多技能助手(编程/写作/翻译一键切换)
- 智能问诊(按症状自动派科室)
七、模式四:监督者(Supervisor Agent)
7.1 场景故事
“卜卦占星师,帮我分析一下今年我的运势,我的伴侣是什么星座?”
这问题至少需要两步:
- 运势分析
- 伴侣匹配
两次执行,先后顺序还不一定。路由模式搞不定(只能选一个),并行模式也不合适(步骤有依赖)。
这时候就要 监督者(Supervisor) 上场——一个“项目经理” Agent,动态决定先调谁、再调谁、最后调谁。
7.2 核心流程
流程图

一张图看懂 监督者的"项目管理循环":
主 Agent(content_supervisor)→ check state(状态评估)→ 选一个子 Agent(reviewer_agent / translator_agent)→ 回到主 Agent → 再次 check state → … → stop(FINISH)。
核心是"循环调度",不是"一次性派单"。
流程详解
监督者模式下,整个调度过程是一个循环,由 mainAgent(监督者)反复决策驱动:
- 监督者 Agent 接收用户输入或前序 Agent 的输出
- 第一轮接收用户原始需求,后续轮接收子 Agent 的执行结果。
- LLM 分析当前状态并决定最合适的子 Agent
- 这步由 mainAgent 完成,它是个纯路由器,输出严格的 JSON 数组。
- 选中的子 Agent 处理任务
- 每次只调一个子 Agent(一次调用原则)。
- 子 Agent 执行完成后返回监督者
- 结果写入
OverAllState,作为下一轮决策的输入。
- 监督者根据结果决定下一步:
-
继续路由到另一个子 Agent
(多步骤任务未完成)
-
返回 FINISH 完成任务
(所有需求已满足)
这个循环会一直跑下去,直到 mainAgent 输出
["FINISH"]才会退出。
千万别让 mainAgent 干业务,否则 JSON 解析必挂。
7.3 核心原理
SupervisorAgent 由两部分组成:
| 角色 | 作用 |
|---|---|
mainAgent |
纯路由器 ,只输出 JSON 数组,告诉框架下一步调谁 |
subAgents |
业务执行者 ,真正干活的 Agent |
关键约束:mainAgent 绝对不能是业务执行型 Agent! 否则它的业务输出(Markdown 文章等)会破坏 JSON 解析。
7.4 提示词模板(核心资产)
参考文件:[PromptConstant.java](file:///d:/project/learn/spring_ai_alibaba_demo/src/main/java/com/spring/ai/alibaba/agent/springaialibabaagent/MultiAgent/tool/PromptConstant.java)
public static final String SUPERVISOR_PROMPT_TEMPLATE =
"你是一个严格的【任务路由器】,不执行业务,只负责决定下一步调用哪一个子 Agent。\n" +
"\n" +
"## 可用子 Agent(必须使用下方 name 字段,不要自创名称)\n" +
"\n" +
"{agent_list}\n" +
"\n" +
"## 路由原则(极其重要)\n" +
"1. 【一次调用原则】每次只调用 1 个最匹配的子 Agent。\n" +
"2. 【无擅自追加】子 Agent 完成后,检查用户原始需求是否已满足。若已满足,直接返回 [\"FINISH\"]。\n" +
"3. 【严格收敛】当且仅当用户需求全部满足时,返回 [\"FINISH\"];中间过程禁止 FINISH。\n" +
"\n" +
"## 输出格式(极其重要,必须严格遵守)\n" +
"1. 你的回复必须且只能是一个 JSON 数组。\n" +
"2. 调用单个 Agent:[\"agentName\"]\n" +
"3. 任务完成:[\"FINISH\"]\n" +
"4. 禁止输出任何 JSON 以外的内容。\n";
{agent_list}会在运行时动态替换为子 Agent 列表,增删子 Agent 无需改模板——这才是企业级写法。
7.5 关键代码
参考文件:[SupervisorAgentChat.java](file:///d:/project/learn/spring_ai_alibaba_demo/src/main/java/com/spring/ai/alibaba/agent/springaialibabaagent/MultiAgent/impl/SupervisorAgentChat.java)
// 三个业务 Agent
ReactAgent constellationAgent = ReactAgent.builder()
.name("constellationAgent")
.model(reactAgentChatModel)
.description("你是一个专业的星座分析大师,擅长分析星座。")
.outputKey("constellation")
.build();
ReactAgent partnerMatchingAgent = ReactAgent.builder()
.name("partnerMatchingAgent")
.model(reactAgentChatModel)
.description("你是一个专业的伴侣匹配专家,擅长根据用户需求匹配伴侣。")
.outputKey("partnerMatching")
.build();
ReactAgent constellationContentEditorAgent = ReactAgent.builder()
.name("constellationContentEditorAgent")
.model(reactAgentChatModel)
.description("资深的卜卦占星师,擅长根据卜卦分析星座运势")
.outputKey("constellationContentEditor")
.build();
List<Agent> subAgents = List.of(constellationAgent, partnerMatchingAgent, constellationContentEditorAgent);
// 动态拼接子 Agent 列表到提示词
String agentListSection = subAgents.stream()
.map(agent -> "- " + agent.name() + ":" + agent.description())
.collect(Collectors.joining("\n"));
// mainAgent(纯路由器)
ReactAgent mainAgent = ReactAgent.builder()
.name("supervisorRouter")
.model(reactAgentChatModel)
.instruction(PromptConstant.SUPERVISOR_PROMPT_TEMPLATE
.replace("{agent_list}", agentListSection))
.build();
// 监督者
SupervisorAgent supervisorAgent = SupervisorAgent.builder()
.name("supervisorAgent")
.model(reactAgentChatModel)
.description("监督者代理服务")
.mainAgent(mainAgent)
.subAgents(subAgents)
.build();
7.6 关键特性
监督者模式有 4 个核心特性,和路由模式对比着记:
- 循环调度:不是一次性派单,而是"调完一个回来再决定下一个"
- 路由模式是单次执行,监督者是多轮循环。
- 动态决策:mainAgent 根据当前状态(包括前序 Agent 的输出)决定下一步
- 这就是"项目经理"和"前台"的区别——前台只管分诊,项目经理管全程。
- 严格 JSON 输出:mainAgent 必须输出
["agentName"]或["FINISH"]
-
千万别让 mainAgent 干业务
,否则 JSON 解析必挂。
- 状态累积:每轮调用的结果都写入
OverAllState,后续轮次可以访问
- 第二轮 Agent 能看到第一轮 Agent 的输出,信息不丢。
这 4 个特性决定了监督者模式的边界:能多步串联、能动态调度,但mainAgent 必须是纯路由器,不能干业务。
7.7 适用场景
- 任务多步骤且依赖关系不固定
- 需要根据中间结果动态调整下一步
- 业务复杂到单 Agent 根本 hold 不住
八、模式五:自定义条件代理(Customized Conditional Agent)
8.1 为什么需要自定义?
业务方要求:“星座关键词走星座 Agent,生肖关键词走生肖 Agent,不准用 LLM 路由,关键词必须严格匹配。”
官方没现成的“关键词路由” Agent。怎么办?
自己造一个 ConditionalAgent!
8.2 核心思路
继承 FlowAgent,手动用 StateGraph API 构建条件路由图:
START → 根透明节点 → 条件评估节点 → [AgentA | AgentB | ...] → END
8.3 关键代码
参考文件:[ConditionalAgent.java](file:///d:/project/learn/spring_ai_alibaba_demo/src/main/java/com/spring/ai/alibaba/agent/springaialibabaagent/MultiAgent/tool/ConditionalAgent.java)
public class ConditionalAgent extends FlowAgent {
private final Map<String, List<String>> conditionKeywords;
private final Map<String, Agent> conditionalAgents;
@Override
protected StateGraph buildSpecificGraph(FlowGraphBuilder.FlowGraphConfig config)
throws GraphStateException {
StateGraph graph = new StateGraph(config.getName(), config.getKeyStrategyFactory());
// 1. 根 Agent 透明节点
graph.addNode(name(), node_async(new TransparentNode()));
// 2. 条件评估节点
String conditionNodeName = name() + "_condition";
graph.addNode(conditionNodeName, node_async(state -> {
String input = Optional.ofNullable(state.value("input", ""))
.map(Object::toString).orElse("").toLowerCase();
String conditionResult = evaluateCondition(input);
return Map.of("_condition_result", conditionResult);
}));
// 3. 边:根 → 条件评估
graph.addEdge(name(), conditionNodeName);
// 4. 子 Agent 节点 + 条件边
Map<String, String> routingMap = new LinkedHashMap<>();
for (Map.Entry<String, Agent> entry : conditionalAgents.entrySet()) {
Agent subAgent = entry.getValue();
FlowGraphBuildingStrategy.addSubAgentNode(subAgent, graph);
routingMap.put(entry.getKey(), subAgent.name());
graph.addEdge(subAgent.name(), END);
}
routingMap.put("default", END);
graph.addConditionalEdges(conditionNodeName, new ConditionEvaluatorAction(), routingMap);
graph.addEdge(START, name());
return graph;
}
/**
* 最佳匹配策略:匹配数最多的关键词组胜出
*/
private String evaluateCondition(String input) {
return conditionKeywords.entrySet().stream()
.map(entry -> Map.entry(entry.getKey(),
entry.getValue().stream().filter(input::contains).count()))
.filter(entry -> entry.getValue() > 0)
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElse("default");
}
}
8.4 使用示例
参考文件:[CustomizedAgentChat.java](file:///d:/project/learn/spring_ai_alibaba_demo/src/main/java/com/spring/ai/alibaba/agent/springaialibabaagent/MultiAgent/impl/CustomizedAgentChat.java)
private static final List<String> CONSTELLATION_KEYWORDS = List.of(
"星座", "星盘", "占星", "卜卦", "天蝎", "白羊", "金牛", "双子", "巨蟹");
private static final List<String> ZODIAC_KEYWORDS = List.of(
"生肖", "属相", "本命年", "属鼠", "属牛", "属虎", "属龙", "属蛇");
ReactAgent constellationAgent = ReactAgent.builder()
.name("constellationAgent")
.model(reactAgentChatModel)
.instruction("你是一个星座分析大师。请根据用户的内容分析星座:{input}")
.outputKey("constellation")
.build();
ReactAgent zodiacAgent = ReactAgent.builder()
.name("zodiacAgent")
.model(reactAgentChatModel)
.instruction("你是一个生肖分析大师。请根据用户的内容分析生肖:{input}")
.outputKey("zodiac")
.build();
ConditionalAgent conditionalAgent = ConditionalAgent.builder()
.name("conditionalAgent")
.description("根据关键词条件路由到星座或生肖 Agent")
.conditionalAgent("constellation", constellationAgent, CONSTELLATION_KEYWORDS)
.conditionalAgent("zodiac", zodiacAgent, ZODIAC_KEYWORDS)
.subAgents(List.of(constellationAgent, zodiacAgent))
.build();
Optional<OverAllState> result = conditionalAgent.invoke("我是属蛇的,帮我分析一下我的生肖运势和属相");
8.5 避坑要点
千万别只用“第一个匹配的关键词”!
通用词如“运势”、“配对”会让精确条件被错覆盖。
正确做法:使用“最佳匹配”策略,匹配关键词数量最多的条件胜出。
九、模式六:混合模式(Compound Agent)
9.1 场景故事
“帮我查询一下长沙的天气,然后分析下适合干啥,再生成一份 HTML 报告和 MD 表格报告。”
这个需求包含:
-
顺序步骤
:查天气 → 分析天气
-
路由选择
:HTML 报告 vs MD 表格报告
-
多轮调度
:项目经理来决定先后顺序
这就是混合模式:监督者(Supervisor)里嵌套路由(Routing)。
9.2 架构图
SupervisorAgent
├── mainAgent (路由器)
├── WeatherAgent (查天气)
├── WeatherAnalyzerAgent (分析天气)
└── report_router (LlmRoutingAgent)
├── HTMLGeneratorAgent
└── MDTableGeneratorAgent
9.3 关键代码
参考文件:[CompoundAgentChat.java](file:///d:/project/learn/spring_ai_alibaba_demo/src/main/java/com/spring/ai/alibaba/agent/springaialibabaagent/MultiAgent/impl/CompoundAgentChat.java)
// 查天气
ReactAgent weatherAgent = ReactAgent.builder()
.name("WeatherAgent")
.model(reactAgentChatModel)
.outputKey("weather")
.instruction("这是一个查询天气的Agent,输入城市名称,返回天气信息")
.methodTools(compoundAgentTool) // 挂载天气查询工具
.build();
// 分析天气
ReactAgent weatherAnalyzerAgent = ReactAgent.builder()
.name("WeatherAnalyzerAgent")
.model(reactAgentChatModel)
.outputKey("weatherAnalyzer")
.instruction("这是一个分析天气的Agent,输入天气信息,返回天气分析结果")
.build();
// 报告生成(HTML vs Markdown 路由)
LlmRoutingAgent reportAgent = LlmRoutingAgent.builder()
.name("report_router")
.description("根据需求选择报告格式")
.model(reactAgentChatModel)
.subAgents(List.of(htmlGeneratorAgent, mdTableGeneratorAgent))
.build();
// mainAgent:项目经理
ReactAgent mainAgent = ReactAgent.builder()
.name("MainDispatchAgent")
.model(reactAgentChatModel)
.outputKey("supervisor_next")
.instruction("你是主调度Agent,根据用户输入决定下一步执行哪个子Agent。" +
"可用子Agent:WeatherAgent(查询天气)、WeatherAnalyzerAgent(分析天气)、" +
"report_router(生成报告)。你必须且只能以JSON数组格式输出。")
.build();
// 监督者编排
SupervisorAgent supervisorAgent = SupervisorAgent.builder()
.name("supervisor")
.mainAgent(mainAgent)
.subAgents(List.of(weatherAgent, weatherAnalyzerAgent, reportAgent))
.build();
Optional<OverAllState> result = supervisorAgent.invoke("帮我查询一下长沙的天气");
9.4 工具集成小贴士
.methodTools(compoundAgentTool) // 给 Agent 挂载 @Tool 标注的工具
工具类示例([CompoundAgentTool.java](file:///d:/project/learn/spring_ai_alibaba_demo/src/main/java/com/spring/ai/alibaba/agent/springaialibabaagent/MultiAgent/tool/CompoundAgentTool.java)):
@Tool(name = "weather", description = "查询指定城市未来 15 天的天气信息")
public String weather(String city) {
// ... 查天气逻辑
}
这是 Spring AI 原生
@Tool注解,与 Agent 无缝集成。
9.5 适用场景
- 复杂业务编排(多步骤 + 多分支)
- 报告生成系统(查询 → 分析 → 多格式输出)
- 工作流引擎核心
十、六大模式对比与选型
| 模式 | 并行性 | 依赖性 | 路由方式 | 适合场景 |
|---|---|---|---|---|
| Sequential | ❌ 串行 | ✅ 强依赖 | 固定顺序 | 流水线 |
| Parallel | ✅ 并行 | ❌ 无依赖 | 无 | 多视角分析 |
| LlmRouting | ❌ 单次 | ❌ 无 | LLM 智能选择 | 多专家分诊 |
| Supervisor | ❌ 串行 | ✅ 动态依赖 | LLM 路由器 | 复杂多步任务 |
| Customized Conditional | ❌ 单次 | ❌ 无 | 关键词匹配 | 规则化路由 |
| Compound | ✅ 可并行 | ✅ 强依赖 | 多层组合 | 复杂业务编排 |
选型口诀
流水线 → Sequential
一起干 → Parallel
智能派单 → LlmRouting
动态调度 → Supervisor
规则路由 → Customized
复杂业务 → Compound
十一、避坑指南(我踩过的坑)
1. mainAgent 不能是业务执行型
❌ 让 mainAgent 既负责路由又负责写文章 → JSON 解析必挂
✅ mainAgent 严格只输出 ["agentName"] 或 ["FINISH"]
2. 占位符名要和 outputKey 严格一致
❌ outputKey = "article",instruction 写 {Article} → 替换失败
✅ 完全小写匹配
3. 并行模式必须做二次去重
❌ 三个 Agent 直接拼接 → 70% 内容重复
✅ 自定义 MergeStrategy 调 LLM 摘要
4. description 写不清楚 = 路由必错
❌ "你是聊天助手"
✅ "专门处理用户闲聊、寒暄、打招呼,不处理具体业务问题"
5. 关键词路由不能用“首个匹配”
❌ 输入"我是属蛇的,帮我看星座" → 误匹配"蛇"
✅ 最佳匹配策略:哪个条件关键词命中最多选哪个
6. Agent name 必须全局唯一
❌ 两个 Agent 都叫 "agent" → 状态覆盖、路由错乱
✅ 命名规范:业务前缀_功能 (例:weather_query_agent)
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

更多推荐

所有评论(0)