Spring AI Alibaba 1.x 系列【39】多智能体(Multi-agent)架构
1. 概述
多智能体 (Multi-agent)将复杂的应用程序分解为多个协同工作的专业化 Agent 。
与依赖单个Agent承载全量任务、全量工具、全量逻辑不同,Multi-agent 架构可以将更小、职责单一、高度专注的轻量化 Agent,组合为可编排、可协作、可路由的标准化工作流。
单 Agent 架构核心痛点:
- 单个
Agent挂载大量工具,工具选择决策混乱、大模型幻觉严重 - 全局上下文、对话记忆持续膨胀,
Token开销大、推理性能低 - 业务职责臃肿耦合,难以维护、迭代、横向扩展
- 无法实现工具隔离、权限隔离、场景化资源管控
多智能体适用场景:
- 单
Agent工具过多,模型无法精准决策 - 上下文/历史记忆体量过大,单
Agent难以高效处理 - 任务需要专业化分工(规划
Agent、检索Agent、审核Agent、计算Agent) - 跨领域业务协作、多角色专家接力处理、复杂长链路流程
2. 两种模式
框架原生提供两种主流多智能体协作模式,覆盖流程编排与拟人化对话两类场景。
两大模式核心对比:
| 对比维度 | 工具调用(Agent Tool) | 交接模式(Handoffs) |
|---|---|---|
| 控制模式 | 集中式(Supervisor 统一调度) | 去中心化(Agent 自主移交) |
| 用户交互 | 子Agent不直接对话,仅返回结果 | 交接后新Agent直接与用户交互 |
| 对话能力 | 有限,适合固定任务流水线 | 极强,支持跨领域连续对话 |
| 流程约束 | 强固化、可编排、易管控 | 弱约束、动态灵活、自适应流转 |
| 上下文优化 | 支持分层裁剪、工具隔离 | 依赖 returnReasoningContent 做上下文瘦身 |
| 典型组件 | SupervisorAgent、Flow顺序/并行编排 | 会话级Agent、领域专属Agent |
最佳实践:混合使用两种模式
- 大领域切换使用「
Handoffs交接」;- 单个领域内部复杂子任务,使用「
Tool Calling子Agent调用」;- 结合
outputKey/includeContents实现安全、高效的跨节点数据流转。
2.1 Tool Calling 工具调用模式
工作原理:
Supervisor总管Agent将其他子Agent封装为工具进行调用;- 子
Agent仅执行专属任务、产出结果,不直接对接用户。
控制流:
- 集中式管控:所有路由、调度、任务分发统一由
Supervisor控制。
适用场景:
- 固定结构化工作流、后台自动化任务、子任务拆解编排、权限集中管控。
2.2 Handoffs 智能体交接模式
工作原理:
- 当前活跃
Agent自主判断业务边界,主动将会话控制权+全局状态移交至目标专业Agent; - 交接完成后,活动
Agent自动切换,用户直接与新Agent持续交互。
控制流:
- 去中心化协作:每个
Agent具备自主决策能力,可主动切换会话处理方,无统一总管调度。
适用场景:
- 跨领域自然对话、专家角色接力、开放式问答流转、人工介入接管。
标准执行流程:
- 当前
Agent判断自身能力边界,判定需要其他专业Agent协助 - 完整传递会话控制权 + 全局State状态 + 上下文至目标
Agent - 新
Agent成为活动节点,直接响应用户对话 - 循环往复:新
Agent可继续交接、或任务完成结束流程
2.3 如何选择
两种模式分工:
| 模式 | 核心用途 | 适用场景 |
|---|---|---|
| 智能体交接 Handoffs | 会话主体切换 完整移交对话控制权,换人服务 |
跨领域、专家转接、主角色变更、长会话接力 |
| 工具调用 Agent Tool | 内部子任务调用 不切换当前会话主体,仅后台调用子能力 |
数据查询、专项计算、原子化独立任务、临时能力复用 |
整体思路:
| 选择判断问题 | 工具调用 (Agent Tool) | 交接(Handoffs) |
|---|---|---|
| 需要集中控制工作流程? | ✅ 是 | ❌ 否 |
| 希望Agent直接与用户交互? | ❌ 否 | ✅ 是 |
| 专家之间复杂的、类人对话? | ❌ 有限 | ✅ 强 |
你可以混合使用两种模式:
使用交接(Handoffs) 做 Agent 整体身份切换;
同时每个Agent,可把子智能体当作工具(Agent Tool) 调用,完成专属子任务。
3. Agent 文本指令
ReactAgent(通过 Builder)提供 3 个文本指令字段,分别控制不同层面的行为:
| 字段 | 类型 | 对应消息类型 | 消息位置 | 模板渲染 | 典型用途 |
|---|---|---|---|---|---|
description |
String | 不直接生成 Message | — | 否 | Agent 能力描述,供 LLM 做路由/工具选择 |
instruction |
String | AgentInstructionMessage |
列表末尾 | 支持({{}} 占位符) |
Agent 行为指令,告诉模型"如何做" |
systemPrompt |
String | SystemMessage( |
列表开头(index=0) | 否 | 系统级指令,设置模型角色/上下文 |
代码示例:
// Java专家Agent(工具)
ReactAgent javaExpertAgent = ReactAgent.builder()
.name("java_expert_agent")
.model(dashScopeChatModel)
.systemPrompt("你是资深Java后端架构师,严格遵循Java编码规范与企业级最佳实践,提供专业、严谨、可落地的技术方案。")
.description("""
Java技术专家工具,专注于Java后端开发、代码审查、架构设计、Bug排查、性能优化,
输出专业、规范、可直接运行的代码与解决方案,遵循阿里Java开发手册
""")
.instruction("""
你是专业的Java后端技术专家,负责解答用户Java相关技术问题、生成高质量代码、排查Bug、优化程序。
要求:
1. 代码必须规范、可编译、可运行;
2. 遵循阿里巴巴Java开发手册,异常、日志、命名严格标准化;
3. 优先使用主流框架:Spring Boot/Spring Cloud/MyBatis;
4. 解释清晰,重点突出,不冗余,技术严谨。
""")
.saver(new MemorySaver())
.build();
在消息列表中的最终顺序:
[0] SystemMessage(systemPrompt) ← ReactAgent.systemPrompt
[1] UserMessage(用户输入) ← 调用时传入
[2] AgentInstructionMessage(instruction) ← ReactAgent.instruction(经模板渲染)

3.1 description(能力描述)
不参与 LLM 对话,仅在 Agent 发现与路由阶段使用:
| 场景 | 使用方式 |
|---|---|
| LlmRoutingAgent 路由决策 | LLM 根据 name + description 选择子 Agent |
| AgentTool 工具注册 | ToolCallback.description(agent.description()) |
| TaskTool 子 Agent 列表 | - name: description 文本拼接 |
// RoutingNode.java — LLM 路由时生成子 Agent 列表
for (Agent subAgent : subAgents) {
sb.append("- ").append(subAgent.name())
.append(": ").append(subAgent.description()).append("\n");
}
// LLM 看到:
// - prose_writer_agent: 可以写散文。
// - poem_writer_agent: 可以写现代诗。
// → LLM 据此决定路由到哪个 Agent
3.2 instruction(行为指令)
参与 LLM 对话,通过 AgentInstructionMessage 注入:
关键特征:
- 支持模板变量(如
{{role}}、{{skill}}),运行时替换 - 被
outputSchema增强时自动转义大括号({→\{) - 序列化
ID为"TEMPLATED_USER"
// InstructionAgentHook.beforeAgent() — 阶段 1 注入
AgentInstructionMessage instructionMessage =
AgentInstructionMessage.builder().text(reactAgent.instruction()).build();
newMessages.add(instructionMessage); // 追加到列表末尾
// AgentLlmNode.renderTemplatedUserMessage() — 阶段 2 模板渲染
instructionMessage.mutate()
.text(renderPromptTemplate(textContent, processedParams)) // {{role}} → "作家"
.rendered(true)
.build();
3.2.1 AgentInstructionMessage
Spring AI 中定义了四种消息类型:
| 消息类型 | 来源 | 用途 | MessageType |
|---|---|---|---|
UserMessage |
用户输入 / 代码直接构造 | 用户请求 | USER |
SystemMessage |
ReactAgent.systemPrompt | 系统级指令 | SYSTEM |
AssistantMessage |
LLM 响应 | 模型输出 | ASSISTANT |
ToolResponseMessage |
工具执行结果 | 工具返回 | TOOL |
Spring AI Alibaba 中扩展了指令消息类型 AgentInstructionMessage ,用于在消息流中包裹、传递 Agent 的 instruction(业务指令),单实际对于大模型来说也属于 USER 类型(本身只有四种),只是 Agent 会进行区分。
构造函数:
public AgentInstructionMessage(String textContent, Map<String, Object> metadata, boolean rendered) {
super(MessageType.USER, textContent, metadata);
this.rendered = rendered;
}
和 UserMessage 对比说明:
- 同为
MessageType.USER,LLM端无法区分 AgentInstructionMessage额外提供rendered标记,支持模板引擎渲染AgentInstructionMessage支持mutate()不可变更新(模板渲染后替换)
3.2.2 Instruction 占位符
在 Multi-agent 系统中,instruction 支持使用占位符来动态引用状态中的数据。这是实现 Agent 之间数据传递的关键机制。
支持的占位符:
| 占位符 | 说明 | 使用场景 |
|---|---|---|
| {input} | 用户原始输入 | 第一个 Agent 接收用户问题 |
| {outputKey} | 引用其他 Agent 的输出 | 第二个 Agent 读取第一个 Agent 的结果 |
| {stateKey} | 读取全局状态 | 读取会话里的任意数据 |
占位符工作原理:
- 你在
instruction里写{xxx} - 框架执行
Agent时自动替换 - 从全局状态
OverAllState里找对应的值 - 替换成真实字符串,传给
AI
最佳实践(开发必看):
-
outputKey 必须有意义
例如:article、user_info、tool_result -
占位符必须与 outputKey 一致
outputKey = xxx 占位符 = {xxx} -
一个 instruction 支持多个占位符
请根据用户问题 {input},参考资料 {docs},分析结果 {result} -
值不存在时,会保留原始 {xxx} 字符串
示例,写作智能体,输出结果存在 article 中
ReactAgent writerAgent = ReactAgent.builder()
.name("writer")
.instruction("你是作家,请根据用户问题创作文章:{input}")
.outputKey("article") // 输出存在这里
.build();
评审智能体,使用 {article} 读取上一个Agent的结果
ReactAgent reviewerAgent = ReactAgent.builder()
.name("reviewer")
.instruction("请评审并修改文章:\n{article}")
.outputKey("final_article")
.build();
3.3 systemPrompt (系统级指令)
关键特征:
MessageType 为SYSTEM,LLM侧作为系统指令处理- 不支持模板渲染(纯字符串)
- 始终位于消息列表最前面(最高优先级)
通过 ModelRequest.systemMessage() 注入:
// AgentLlmNode.apply()
if (StringUtils.hasLength(this.systemPrompt)) {
requestBuilder.systemMessage(new SystemMessage(this.systemPrompt));
}
// appendSystemPromptIfNeeded() — 插入到消息列表头部
if (modelRequest.getSystemMessage() != null) {
messages.add(0, modelRequest.getSystemMessage()); // index=0,最前面
}
4. 自定义 Agent 上下文
多智能体系统的核心:控制每个 Agent 能看到什么信息。
Spring AI Alibaba 允许你精细控制:
- 给每个
Agent看不同的历史消息 - 给每个
Agent传不同的状态数据 - 给每个
Agent定制不同的提示词 - 给每个
Agent自定义输入/输出格式 - 控制是否给
Agent看中间思考过程
为什么上下文工程很重要?
因为:
- 信息太多 →
Agent会混乱 - 信息太少 → `Agent 无法工作
- 信息错误 →
Agent回答跑偏
5. 模式一:智能体作为工具
比较简单,使用 AgentTool 转换为工具后,添加到 ReactAgent 中即可:
AgentTool.getFunctionToolCallback(topicAgent)
6. 模式二:交接
四大智能体对比:
| 特性 | 顺序智能体 SequentialAgent |
并行智能体 ParallelAgent |
循环智能体 LoopAgent |
路由智能体 LlmRoutingAgent |
|---|---|---|---|---|
| 执行逻辑 | 线性依次执行 | 并发执行 | 重复执行1个子智能体 | LLM决策,路由到1个子智能体 |
| 子智能体数量 | 无限制 | 2~10个 | 仅1个 | 多个(候选池) |
| 核心价值 | 分步流程 | 提升效率 | 重试/遍历 | 智能决策、统一入口 |
| 动态工具场景 | 分阶段切换工具 | 多工具并行 | 循环调用工具 | 按路由场景加载工具 |
| 定位 | 流程执行 | 性能优化 | 迭代重试 | 工作流大脑 |
6.1 顺序执行智能体(SequentialAgent)
FlowAgent 的具体子类,专门用于线性、按顺序执行子智能体的工作流场景,将所有子智能体按照【添加的先后顺序】线性、依次执行(无分支、无循环)。
在顺序执行模式中,多个 Agent 按预定义的顺序依次执行:
Agent A处理初始输入Agent A的输出传递给Agent BAgent B处理并传递给Agent C- 最后一个
Agent返回最终结果
关键特性:
- 按顺序执行:
Agent按照subAgents列表中定义的顺序执行 - 状态传递:每个
Agent的输出通过outputKey存储在状态中,可被后续Agent访问 - 消息历史:默认情况下,所有
Agent共享消息历史 - 推理内容控制:使用
returnReasoningContents控制是否在消息历史中包含中间推理

6.2 并行执行智能体(Parallel Agent)
在并行执行模式中,多个 Agent 同时处理相同的输入。它们的结果被收集并合并。
流程:
- 输入同时发送给所有
Agent - 所有
Agent并行处理 - 结果被合并成单一输出

6.3 循环智能体(LoopAgent)
循环执行智能体,继承自 FlowAgent,核心能力是按指定策略循环执行单个子智能体,支持固定次数、条件判断、JSON 数组遍历等多种循环模式。
支持多种循环模式,用于重复执行单个子智能体:
COUNT(次数循环):执行固定次数的循环CONDITION(条件循环):根据条件判断是否继续循环,满足条件时终止循环,结构类似do-whileJSON_ARRAY(数组遍历):解析 JSON 数组,遍历数组内每个元素并执行子智能体- 自定义策略:可实现
LoopStrategy接口,自行拓展自定义循环逻辑
核心约束:LoopAgent 有且仅能配置一个子智能体,该子智能体将在每一轮循环中重复执行。
6.4 路由执行智能体(LlmRoutingAgent )
利用大模型的理解能力,自动决策、智能路由到最合适的子智能体执行。
核心功能:
- 基于大模型(
ChatModel)理解用户意图 - 自动从子智能体列表中,路由到最匹配的子智能体执行
- 支持兜底智能体,路由失败时自动降级
- 支持自定义系统提示词、路由指令,灵活控制路由逻辑
适用场景:多场景智能体统一入口、意图识别、动态分支决策

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)