当一个Agent要处理很多复杂的事情,就会出现效果不佳的情况,这时候Multi-Agent就可以将复杂任务进行拆分,更好的完成我们的任务。
本文基于Spring AI Alibaba框架,详解Multi-Agent的核心概念、占位符用法,以及顺序执行、并行执行、路由调度、监督者管控四大核心模式,搭配完整可运行的代码示例,快速上手多智能体开发。
一、Multi-Agent 核心概念
官方对Multi-Agent的定义清晰直白:
Multi-agent 将复杂的应用程序分解为多个协同工作的专业化Agent。与依赖单个Agent处理所有步骤不同,Multi-agent架构允许你将更小、更专注的Agent组合成协调的工作流。
Multi-agent系统在以下情况下很有用:
- 单个Agent拥有太多工具,难以做出正确的工具选择决策
- 上下文或记忆增长过大,单个Agent难以有效跟踪
- 任务需要专业化(例如:规划器、研究员、数学专家)
二、指令占位符(Instruction)用法
支持使用占位符来动态引用状态中的数据。比如AgentB需要使用AgentA处理后的数据,就需要通过Instruction来获取
1、支持的占位符
| 占位符 | 说明 | 使用场景 |
|---|---|---|
{input} |
用户输入的原始内容 | 第一个Agent或需要用户输入的 Agent |
{outputKey} |
引用其他Agent通过 outputKey 存储的输出 |
顺序执行中,后续Agent引用前面Agent的输出 |
{stateKey} |
引用状态中的任意键值 | 访问状态中的任何数据 |
2、占位符工作原理
- 自动替换:系统会在执行 Agent 的 instruction 时,自动将占位符替换为对应的实际值
- 状态查找 :占位符会从当前状态(
OverAllState)中查找对应的值 - 类型安全:占位符的值会被转换为字符串并插入到 instruction 中
三、公共代码(ChatModel获取)
我先把获取ChatModel这个公共代码放在这里,后面就不重复写进来了
默认模型qwen-plus
java
public static ChatModel getChatModel() {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AliQwen_API"))
.build();
return DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.defaultOptions(DashScopeChatOptions.builder()
// Note: model must be set when use options build.
.model(DashScopeChatModel.DEFAULT_MODEL_NAME)
.temperature(0.5)
.maxToken(1000)
.build())
.build();
}
四、顺序执行(Sequential Agent)
顾名思义,多个Agent按照顺序依次执行,上一个Agent的输出结果可以传递给下一个Agent
1. 执行流程
- Agent A处理初始输入
- Agent A 的输出传递给Agent B
- Agent B 处理并传递给Agent C
- 最后一个Agent返回最终结果

2. 示例代码
java
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import com.alibaba.cloud.ai.graph.NodeOutput;
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
import com.alibaba.cloud.ai.graph.agent.flow.agent.SequentialAgent;
import com.alibaba.cloud.ai.graph.exception.GraphRunnerException;
import com.alibaba.cloud.ai.graph.streaming.StreamingOutput;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.model.ChatModel;
import reactor.core.publisher.Flux;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import com.alibaba.cloud.ai.graph.OverAllState;
public class SequentialAgentTest {
public static void main(String[] args) throws GraphRunnerException, IOException {
ChatModel chatModel = getChatModel();
// 创建专业化的子Agent
ReactAgent writerAgent = ReactAgent.builder()
.name("writer_agent")
.model(chatModel)
.description("专业写作Agent")
.instruction("你是一个知名的作家,擅长写作和创作。请根据用户的提问进行回答:{input}。")
.outputKey("article")
.build();
ReactAgent translateAgent = ReactAgent.builder()
.name("translate_agent")
.model(chatModel)
.description("专业翻译Agent")
.instruction("""
你是一个知名的翻译官,擅长对文章翻译。
待翻译文章:
{article}
最终只返回翻译后的文章。""")
.outputKey("reviewed_article")
.build();
// 创建顺序Agent
SequentialAgent blogAgent = SequentialAgent.builder()
.name("blog_agent")
.description("根据用户给定的主题写一篇文章,然后将文章交给翻译员进行翻译")
.subAgents(List.of(writerAgent, translateAgent))
.build();
// 测试
Optional<OverAllState> result = blogAgent.invoke("帮我写一个100字左右的散文,不用输出字数");
if (result.isPresent()) {
OverAllState state = result.get();
// 访问第一个Agent的输出
state.value("article").ifPresent(article -> {
if (article instanceof AssistantMessage) {
System.out.println("原始文章: " + ((AssistantMessage) article).getText());
}
});
// 访问第二个Agent的输出
state.value("reviewed_article").ifPresent(reviewedArticle -> {
if (reviewedArticle instanceof AssistantMessage) {
System.out.println("翻译后文章: " + ((AssistantMessage) reviewedArticle).getText());
}
});
}
}
3. 运行结果
java
原始文章: 晨光初染窗棂,茶烟袅袅浮起,如一段未写完的旧信。院中老槐静立,枝桠间漏下碎金,在青砖上缓缓游移。风来,几片薄叶旋落,无声栖于石阶,像时光轻轻踮脚走过。邻家孩童追着纸鸢跑远,笑声清亮,撞碎一巷薄雾。我凝望这寻常片刻------原来人间至味,并非惊雷烈酒,而是晨光、微风、落叶与未凉的茶,在素常里酿出微光。
翻译后文章: Dawn's first light gently tints the window frame; tea steam rises in delicate, lingering wisps---like an unfinished old letter. In the courtyard, an ancient locust tree stands still, its branches filtering golden shards of sunlight that slowly drift across the bluish-gray bricks. A breeze stirs: a few slender leaves spiral down, settling silently on the stone steps---as if time itself tiptoed past. A neighbor's child chases a kite down the lane, laughter bright and clear, shattering the morning mist. Gazing upon this ordinary moment, I realize: life's truest flavor lies not in thunderclaps or strong wine, but in dawn light, soft wind, falling leaves, and tea still warm---subtle radiance brewed quietly in the everyday.
4. 关键特性
- 按顺序执行 :Agent按照
subAgents列表中定义的顺序执行 - 状态传递 :每个Agent的输出通过
outputKey存储在状态中,可被后续Agent访问 - 消息历史:默认情况下,所有Agent共享消息历史
- 推理内容控制 :使用
returnReasoningContents控制是否在消息历史中包含中间推理
五、并行执行(Parallel Agent)
当不考虑智能体的执行顺序时,可以使用Parallel Agent,多个智能体接收相同的输出进行处理,最后将结果汇总
1. 执行流程
- 输入同时发送给所有Agent
- 所有Agent并行处理
- 结果被合并成单一输出

2. 示例代码
java
public static void main(String[] args) throws GraphRunnerException {
ChatModel chatModel = getChatModel();
// 创建多个专业化Agent
ReactAgent proseWriterAgent = ReactAgent.builder()
.name("prose_writer_agent")
.model(chatModel)
.description("专门写散文的AI助手")
.instruction("你是一个知名的散文作家,擅长写优美的散文。" +
"用户会给你一个主题:{input},你只需要创作一篇100字左右的散文。")
.outputKey("prose_result")
.build();
ReactAgent poemWriterAgent = ReactAgent.builder()
.name("poem_writer_agent")
.model(chatModel)
.description("专门写现代诗的AI助手")
.instruction("你是一个知名的现代诗人,擅长写现代诗。" +
"用户会给你的主题是:{input},你只需要创作一首现代诗。")
.outputKey("poem_result")
.build();
ReactAgent summaryAgent = ReactAgent.builder()
.name("summary_agent")
.model(chatModel)
.description("专门做内容总结的AI助手")
.instruction("你是一个专业的内容分析师,擅长对主题进行总结和提炼。" +
"用户会给你一个主题:{input},你只需要对这个主题进行简要总结。")
.outputKey("summary_result")
.build();
// 创建并行Agent
ParallelAgent parallelAgent = ParallelAgent.builder()
.name("parallel_creative_agent")
.description("并行执行多个创作任务,包括写散文、写诗和做总结")
.mergeOutputKey("merged_results")
.subAgents(List.of(proseWriterAgent, poemWriterAgent, summaryAgent))
.mergeStrategy(new CustomMergeStrategy())
.build();
// 使用
Optional<OverAllState> result = parallelAgent.invoke("以'西湖'为主题");
if (result.isPresent()) {
OverAllState state = result.get();
// 访问各个Agent的输出
state.value("prose_result").ifPresent(r ->
System.out.println("散文: " + r));
state.value("poem_result").ifPresent(r ->
System.out.println("诗歌: " + r));
state.value("summary_result").ifPresent(r ->
System.out.println("总结: " + r));
// 访问合并后的结果
state.value("merged_results").ifPresent(r ->
System.out.println("合并结果: " + r));
}
}
3. 自定义合并策略
通过自定义合并策略来控制组合多个Agent的输出:
java
public class CustomMergeStrategy implements ParallelAgent.MergeStrategy {
@Override
public Object merge(Map<String, Object> mergedState, OverAllState state) {
// 从每个Agent的状态中提取输出
state.data().forEach((key, value) -> {
// 检查key不为null且以"_result"结尾
if (key != null && key.endsWith("_result")) {
String resultText = "";
if (value instanceof GraphResponse graphResponse) {
if (graphResponse.resultValue().isPresent()) {
HashMap messageMap = (HashMap) graphResponse.resultValue().get();
AssistantMessage assistantMessage = (AssistantMessage) messageMap.get(key);
resultText = assistantMessage.getText();
}
} else if (value != null) {
resultText = value.toString();
}
Object existing = mergedState.get("all_results");
if (existing == null) {
mergedState.put("all_results", resultText);
}
else {
mergedState.put("all_results", existing + "\n\n---\n\n" + resultText);
}
}
});
return mergedState;
}
}
4. 输出结果
java
合并结果: {all_results=《曲径证词》
粉墙是未拆封的宣纸,
苔痕在青砖缝里写小楷------
一笔,就洇开三百年雨。
假山不假:它用太湖石的嶙峋,
把整座江南叠进一拳掌中;
游鱼在漏窗格子里游成篆字,
而影子,在池底临摹另一座园林。
你数过九曲桥的弯吗?
每一道折,都把直路还给流水,
把时间还给回廊的弧度。
当夕光斜切过飞檐,
瓦上霜色忽然浮起------
原来最深的幽静,
是光在转身时,
轻轻合拢的门。
(石阶微凉,而月光正从花窗进来,
替所有未出口的留白,
落款。)
---
苏州园林是中国古典私家园林的杰出代表,以"咫尺乾坤"的造园理念,融合诗、书、画、印等艺术形式,追求自然意趣与人文精神的统一。其典型特征包括精巧的布局(如借景、框景、对景)、丰富的建筑元素(亭、台、楼、阁、廊、舫)、写意的山水营造(旱园水做、石峰点景)、细腻的装饰工艺(花窗、铺地、彩绘、木雕)以及深厚的文化内涵(隐逸思想、文人审美)。代表园林有拙政园、留园、网师园、狮子林等,1997年被联合国教科文组织列入《世界遗产名录》。
---
。。。。不粘贴出来了
六、智能路由(LlmRoutingAgent)
在路由模式中,使用大语言模型(LLM)动态决定将请求路由到哪个子Agent。这种模式非常适合需要智能选择不同专家Agent的场景。
1.执行流程
- 路由Agent接收用户输入
- LLM分析输入并决定最合适的子Agent
- 选中的子Agent处理请求
- 结果返回给用户

2. 示例代码
java
public static void main(String[] args) {
ChatModel chatModel = getChatModel();
ReactAgent proseWriterAgent = ReactAgent.builder()
.name("prose_writer_agent")
.model(chatModel)
.description("Can write prose articles.")
.instruction("You are a renowned writer skilled in writing prose. Please respond to the following request: {input}")
.outputKey("prose_article")
.build();
ReactAgent poemWriterAgent = ReactAgent.builder()
.name("poem_writer_agent")
.model(chatModel)
.description("Can write modern poetry.")
.instruction("You are a famous poet skilled in modern poetry. Please use tools to respond to the following request: {input}")
.outputKey("poem_article")
.tools(List.of(createPoetToolCallback()))
.build();
LlmRoutingAgent blogAgent = LlmRoutingAgent.builder()
.name("blog_agent")
.model(chatModel)
.description("Can write articles or poems based on user-provided topics.")
.subAgents(List.of(proseWriterAgent, poemWriterAgent))
.build();
try {
GraphRepresentation representation = blogAgent.getGraph().getGraph(GraphRepresentation.Type.PLANTUML);
System.out.println(representation.content());
Optional<OverAllState> result = blogAgent.invoke("帮我写一个100字左右的现代诗");
blogAgent.invoke("帮我写一个100字左右的现代诗");
Optional<OverAllState> result3 = blogAgent.invoke("帮我写一个100字左右的现代诗");
OverAllState state = result.get();
OverAllState state3 = result3.get();
AssistantMessage poemContent = (AssistantMessage) state.value("poem_article").get();
AssistantMessage poemContent3 = (AssistantMessage) state3.value("poem_article").get();
System.out.println(result.get());
System.out.println("------------------");
System.out.println(result3.get());
}
catch (CompletionException | GraphRunnerException e) {
e.printStackTrace();
}
}
3. 输出结果
java
10:45:58.958 [main] INFO com.alibaba.cloud.ai.graph.agent.flow.node.RoutingNode -- RoutingAgent blog_agent routed to single sub-agent poem_writer_agent.
Poet tool called : 100字左右的现代诗
10:46:03.509 [main] INFO com.alibaba.cloud.ai.graph.agent.flow.node.RoutingNode -- RoutingAgent blog_agent routed to single sub-agent poem_writer_agent.
Poet tool called : 100字左右的现代诗
10:46:08.768 [main] INFO com.alibaba.cloud.ai.graph.agent.flow.node.RoutingNode -- RoutingAgent blog_agent routed to single sub-agent poem_writer_agent.
Poet tool called : 帮我写一个100字左右的现代诗
{"OverAllState":{"data":{"_graph_execution_id_":"438452b3-d336-4581-99ac-690e56564841","input":"帮我写一个100字左右的现代诗","messages":[{"messageType":"USER","metadata":{"messageType":"USER"},"media":[],"text":"帮我写一个100字左右的现代诗"},{"messageType":"USER","metadata":{"messageType":"USER"},"rendered":false,"text":"You are a famous poet skilled in modern poetry. Please use tools to respond to the following request: {input}"},{"messageType":"ASSISTANT","metadata":{"search_info":"","role":"ASSISTANT","messageType":"ASSISTANT","finishReason":"STOP","id":"08c74cd3-a22f-476e-b9dd-52506b5642be","reasoningContent":""},"toolCalls":[],"media":[],"text":"在城市的缝隙里, \n一束光悄悄发芽, \n穿过钢筋水泥的沉默, \n在风中轻轻说话。 \n\n夜色如墨,却不再黑, \n星星点亮了每一个角落, \n我站在时间的边缘, \n等一朵云,轻轻落下。 \n\n------这是属于你的一首现代诗,简洁而有呼吸感,愿它在喧嚣中为你留出一片静默与微光。"}],"poem_article":{"messageType":"ASSISTANT","metadata":{"search_info":"","role":"ASSISTANT","messageType":"ASSISTANT","finishReason":"STOP","id":"08c74cd3-a22f-476e-b9dd-52506b5642be","reasoningContent":""},"toolCalls":[],"media":[],"text":"在城市的缝隙里, \n一束光悄悄发芽, \n穿过钢筋水泥的沉默, \n在风中轻轻说话。 \n\n夜色如墨,却不再黑, \n星星点亮了每一个角落, \n我站在时间的边缘, \n等一朵云,轻轻落下。 \n\n------这是属于你的一首现代诗,简洁而有呼吸感,愿它在喧嚣中为你留出一片静默与微光。"}}}}
------------------
省略。。
4. 自定义提示词
LlmRoutingAgent支持使用SystemPrompt指定系统提示词,下面摘抄自官方示例:
text
final String ROUTING_SYSTEM_PROMPT = """
你是一个智能的内容路由Agent,负责根据用户需求将任务路由到最合适的专家Agent。
## 你的职责
1. 仔细分析用户输入的意图和需求
2. 根据任务特性,选择最合适的专家Agent
3. 确保路由决策准确、高效
## 可用的子Agent及其职责
### writer_agent
- **功能**: 擅长创作各类文章,包括散文、诗歌等文学作品
- **适用场景**:
* 用户需要创作新文章、散文、诗歌等原创内容
* 简单的写作任务
- **输出**: writer_output
### reviewer_agent
- **功能**: 擅长对文章进行评论、修改和润色
- **适用场景**:
* 用户需要修改、评审或优化现有文章
* 需要提高文章质量
- **输出**: reviewer_output
### translator_agent
- **功能**: 擅长将文章翻译成各种语言
- **适用场景**:
* 用户需要将内容翻译成其他语言
* 多语言转换需求
- **输出**: translator_output
## 决策规则
1. **写作任务**: 如果用户需要创作新内容,选择 writer_agent
2. **修改任务**: 如果用户需要修改或优化现有内容,选择 reviewer_agent
3. **翻译任务**: 如果用户需要翻译内容,选择 translator_agent
## 响应格式
只返回Agent名称(writer_agent、reviewer_agent、translator_agent),不要包含其他解释。
""";
LlmRoutingAgent routingAgent = LlmRoutingAgent.builder()
.name("content_routing_agent")
.description("根据用户需求智能路由到合适的专家Agent")
.model(chatModel)
.systemPrompt(ROUTING_SYSTEM_PROMPT)
.subAgents(List.of(writerAgent, reviewerAgent, translatorAgent))
.build();
七、监督者(SupervisorAgent)
SupervisorAgent 是多智能体系统的 "大脑 / 协调者",核心职责:
- 接收用户请求,理解并拆解复杂任务
- 决策调度:根据任务类型,选择最合适的子智能体(如写作、翻译、搜索等)
- 循环执行:多次调用不同子智能体,完成多步骤任务
- 结果整合:汇总子智能体输出,形成最终答案
1. 执行流程
- 监督者Agent接收用户输入或前序Agent的输出
- LLM分析当前状态并决定最合适的子Agent
- 选中的子Agent处理任务
- 子Agent执行完成后返回监督者
- 监督者 根据结果决定:
- 继续路由到另一个子Agent(多步骤任务)
- 返回
FINISH完成任务

2. 示例代码
javav
static final String SUPERVISOR_SYSTEM_PROMPT = """
你是一个智能的内容管理监督者,负责协调和管理多个专业Agent来完成用户的内容处理需求。
## 你的职责
1. 分析用户需求,将其分解为合适的子任务
2. 根据任务特性,选择合适的Agent进行处理
3. 监控任务执行状态,决定是否需要继续处理或完成任务
4. 当所有任务完成时,返回FINISH结束流程
## 可用的子Agent及其职责
### writer_agent
- **功能**: 擅长创作各类文章,包括散文、诗歌等文学作品
- **适用场景**:
* 用户需要创作新文章、散文、诗歌等原创内容
* 简单的写作任务,不需要后续评审或修改
- **输出**: writer_output
### translator_agent
- **功能**: 擅长将文章翻译成各种语言
- **适用场景**: 当文章需要翻译成其他语言时
- **输出**: translator_output
## 决策规则
1. **单一任务判断**:
- 如果用户只需要简单写作,选择 writer_agent
- 如果用户需要翻译,选择 translator_agent
2. **多步骤任务处理**:
- 如果用户需求包含多个步骤(如"先写文章,然后翻译"),需要分步处理
- 先路由到第一个合适的Agent,等待其完成
- 完成后,根据剩余需求继续路由到下一个Agent
- 直到所有步骤完成,返回FINISH
3. **任务完成判断**:
- 当用户的所有需求都已满足时,返回FINISH
## 响应格式
只返回Agent名称(writer_agent、translator_agent)或FINISH,不要包含其他解释。
""";
public static void main(String[] args) throws GraphRunnerException, IOException {
ChatModel chatModel = getChatModel();
// 创建专业化的子Agent
ReactAgent writerAgent = ReactAgent.builder()
.name("writer_agent")
.model(chatModel)
.description("擅长创作各类文章,包括散文、诗歌等文学作品")
.outputKey("writer_output")
.build();
ReactAgent translatorAgent = ReactAgent.builder()
.name("translator_agent")
.model(chatModel)
.description("擅长将文章翻译成各种语言")
.outputKey("translator_output")
.build();
// 创建监督者Agent
SupervisorAgent supervisorAgent = SupervisorAgent.builder()
.name("content_supervisor")
.description("内容管理监督者")
.systemPrompt(SUPERVISOR_SYSTEM_PROMPT)
.mainAgent(writerAgent)
.model(chatModel)
.subAgents(List.of(writerAgent, translatorAgent))
.build();
// 使用 - 监督者会根据任务自动路由并支持多步骤处理
Flux<NodeOutput> flux = supervisorAgent.stream("先帮我写一篇关于春天的短文,然后将文章翻译成英文");
flux.subscribe(chunk -> {
if (chunk instanceof StreamingOutput<?> streamingOutput) {
String newContent = "";
Message message = streamingOutput.message();
if (message instanceof AssistantMessage assistantMessage) {
Object finishReason = message.getMetadata().get("finishReason");
if (finishReason == null) {
newContent = assistantMessage.getText();
}
if (finishReason != null && !finishReason.toString().equals("STOP")) {
newContent = assistantMessage.getText();
}
}
System.out.println(newContent);
}
});
System.in.read();
}
3. 输出结果
java
11:06:21.373 [main] INFO com.alibaba.cloud.ai.graph.agent.flow.node.MainAgentNodeAction -- Invoking mainAgent 'writer_agent' compiled graph with threadId: Optional[subgraph_writer_agent]
Agent output text: **中文短文:春天的信使**
当冬寒悄然退去,大地便轻轻舒展腰身------春天来了。
柳枝最先醒来,在微风中抽出嫩黄的新芽,像一串串小小的音符,轻轻摇曳在清冽的空气里。桃花、杏花、梨花次第绽放,粉的娇羞,白的澄澈,红的热烈,把山坡、小院、河岸染成流动的锦缎。泥土松软温润,蚯蚓在深处翻动,草尖顶开枯叶,怯生生地探出一点新绿。
清晨,鸟鸣清亮如洗;午后,阳光温柔似蜜,晒得人懒洋洋地想打个盹;傍晚,归燕掠过屋檐,衔来南方的暖意与旧年的故事。孩子们脱下厚衣,在田野里奔跑,纸鸢乘着东风扶摇直上,仿佛把整个童年的欢笑都放飞到了云朵之间。
春天从不喧哗,却用最细腻的笔触,把希望写进每一片叶脉、每一滴露珠、每一双仰望天空的眼睛里。它提醒我们:凋零不是终点,而是生命在静默中积蓄力量,只为一次更盛大的重逢。
---
**English Translation: The Herald of Spring**
As winter's chill quietly retreats, the earth gently stretches its limbs---spring has arrived.
The willow branches are the first to awaken, sprouting tender yellow buds in the breeze---like tiny musical notes swaying softly in the crisp, clear air. Peach blossoms, apricot flowers, and pear blossoms bloom in gentle succession: pink ones blush with shy charm, white ones gleam with serene purity, and red ones blaze with quiet passion---painting hillsides, courtyards, and riverbanks with a flowing, living tapestry. The soil grows soft and warm; earthworms stir beneath the surface, while fresh green shoots push through last year's dry leaves, timidly raising their heads.
At dawn, birdsong rings out, clear and cleansing; at noon, sunlight pours down like golden honey---so warm and gentle it lulls one into drowsy contentment; by evening, swallows glide home across rooftops, carrying southern warmth and stories from seasons past. Children shed their heavy coats and race across open fields; kites soar high on the east wind, lifting childhood laughter all the way up into the clouds.
Spring never shouts---it speaks instead in whispers, using the finest brushstroke to inscribe hope into every leaf vein, every dewdrop, and every pair of eyes gazing upward toward the sky. It reminds us: decay is never an end, but rather life's quiet season of gathering strength---preparing, always, for a more magnificent reunion.
八、多种Agent混合使用
实际业务中,往往会将多种Agent模式组合使用,打造完整的工作流。以下以电商订单智能处理为例,融合并行查询、智能分析、路由处理、顺序执行,实现全自动售后处理。
1. 示例代码
java
public static void main(String[] args) throws GraphRunnerException {
ChatModel chatModel = getChatModel();
// 1. 创建并行查询Agent(同时查用户信息 + 订单信息)
ReactAgent userQueryAgent = ReactAgent.builder()
.name("user_query")
.model(chatModel)
.description("查询用户信息、会员等级、历史行为")
.instruction("根据用户ID查询用户信息:{input}")
.outputKey("user_info")
.build();
ReactAgent orderQueryAgent = ReactAgent.builder()
.name("order_query")
.model(chatModel)
.description("查询订单状态、物流、商品信息")
.instruction("根据订单号查询订单详细信息:{input}")
.outputKey("order_info")
.build();
// 并行执行:同时查用户+订单,大幅提速
ParallelAgent queryAgent = ParallelAgent.builder()
.name("parallel_query")
.description("并行查询用户信息与订单信息")
.subAgents(List.of(userQueryAgent, orderQueryAgent))
.mergeOutputKey("query_data")
.build();
// 2. 智能分析Agent(分析问题类型:退款/换货/补发/咨询)
ReactAgent analysisAgent = ReactAgent.builder()
.name("order_analysis")
.model(chatModel)
.description("分析用户问题、订单状态,给出处理建议")
.instruction("""
分析以下查询数据,判断用户需求类型:
1. 未发货仅退款 → 退款
2. 已收货质量问题 → 换货
3. 少发/漏发 → 补发
4. 其他 → 人工客服
数据:{query_data}
""")
.outputKey("analysis_result")
.build();
// 3. 路由处理Agent(根据分析结果,自动选择处理方式)
ReactAgent refundAgent = ReactAgent.builder()
.name("refund_process")
.model(chatModel)
.description("自动生成退款方案")
.instruction("""
根据订单与分析结果生成退款处理方案:
订单信息:{order_info}
分析结果:{analysis_result}
""")
.outputKey("refund_solution")
.build();
ReactAgent exchangeAgent = ReactAgent.builder()
.name("exchange_process")
.model(chatModel)
.description("自动生成换货方案")
.instruction("""
根据订单与分析结果生成换货处理方案:
订单信息:{order_info}
分析结果:{analysis_result}
""")
.outputKey("exchange_solution")
.build();
ReactAgent resendAgent = ReactAgent.builder()
.name("resend_process")
.model(chatModel)
.description("自动生成补发方案")
.instruction("""
根据订单与分析结果生成补发处理方案:
订单信息:{order_info}
分析结果:{analysis_result}
""")
.outputKey("resend_solution")
.build();
// LLM智能路由:自动选最合适的处理Agent
LlmRoutingAgent processAgent = LlmRoutingAgent.builder()
.name("process_router")
.description("根据分析结果智能路由到对应处理流程")
.model(chatModel)
.subAgents(List.of(refundAgent, exchangeAgent, resendAgent))
.build();
// 4. 组合成完整工作流(顺序执行)
SequentialAgent orderWorkflow = SequentialAgent.builder()
.name("ecommerce_order_workflow")
.description("电商订单智能处理全流程:并行查询 → 智能分析 → 路由处理")
.subAgents(List.of(queryAgent, analysisAgent, processAgent))
.build();
// 使用:传入用户问题 + 订单号
Optional<OverAllState> result = orderWorkflow.invoke("订单号:123456,我要退款,商品还没发货");
System.out.println(result.get());
}
2. 业务流程图

九、总结
Spring AI Alibaba的Multi-Agent架构,通过分工协作,旨在解决单个Agent的能力瓶颈。四种核心模式各有侧重,适配不同场景:
- 顺序执行:适合流水线、有先后依赖的任务
- 并行执行:适合无依赖、需提速的批量任务
- 智能路由:适合任务类型多变、需智能分流的场景
- 监督者模式:适合复杂长流程、多步骤协作任务
文中代码已上传GitHub,地址: