多Agent编排技术让AI协作更高效,Spring AI Alibaba 1.1.2版本提供了5种实用模式,本文将详细解析每种模式的实现方法与应用场景。
单一大型模型处理复杂任务往往效率低下,合理的方式是将任务分解,让专业AI分工协作。

任务分解的核心思路包括:
这种分工协作就是多Agent编排的精髓。Spring AI Alibaba 1.1.2.2版本提供了5种编排模式:Supervisor / Routing / Handoffs / Skills / Workflow,本文将通过官方示例源码逐一讲解。
当用户提出包含多个子任务的复合请求时,例如"帮我安排明天9点站会,再发邮件通知团队",需要:
Supervisor模式就是这样的任务协调中心。
实现思路:先为子Agent配置name/description/systemPrompt/inputType等参数,再用AgentTool.getFunctionToolCallback(agent)方法封装。
关键API示例(来自官方源码SupervisorConfig.java):
// 第一步:构建子Agent - 需配置四个关键要素
ReactAgent orderAgent = ReactAgent.builder()
.name("query_order") // 工具标识名
.description("查询订单状态。当用户询问订单、物流时调用。") // 功能描述
.systemPrompt("你是订单查询助手。根据用户提供的订单号查询订单状态。") // 系统提示
.model(chatModel)
.methodTools(orderQueryTools) // 关联工具集
.inputType(String.class) // 输入类型
.build();// 第二步:封装为工具 - 仅接收ReactAgent参数
AgentTool.getFunctionToolCallback(orderAgent)// 第三步:构建Supervisor - 注册子Agent工具
ReactAgent supervisorAgent = ReactAgent.builder()
.name("personal_assistant")
.systemPrompt("你是一个智能个人助手。你可以查询订单状态和发送通知。"
+ "将用户请求分解为合适的工具调用,协调结果。")
.model(chatModel)
.saver(memorySaver) // 记忆存储
.tools(
AgentTool.getFunctionToolCallback(orderAgent), // 子工具注册
AgentTool.getFunctionToolCallback(notifyAgent))
.build();
<properties>
<spring-ai.version>1.1.2spring-ai.version>
<spring-ai-alibaba.version>1.1.2.2spring-ai-alibaba.version>
<spring-ai-alibaba-extensions.version>1.1.2.2spring-ai-alibaba-extensions.version>
properties><dependencies>
<dependency>
<groupId>com.alibaba.cloud.aigroupId>
<artifactId>spring-ai-alibaba-starter-dashscopeartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloud.aigroupId>
<artifactId>spring-ai-alibaba-agent-frameworkartifactId>
dependency>
dependencies>
@Configuration
public class SupervisorConfig { @Bean
public MemorySaver memorySaver() { return new MemorySaver(); } @Bean
public ReactAgent orderAgent(ChatModel chatModel, OrderQueryTools orderQueryTools) {
return ReactAgent.builder()
.name("query_order")
.description("查询订单状态。当用户想查询订单、物流、发货情况时调用此工具。")
.systemPrompt("你是订单查询助手。根据用户提供的订单号查询订单状态。")
.model(chatModel)
.methodTools(orderQueryTools)
.inputType(String.class)
.build();
} @Bean
public ReactAgent notifyAgent(ChatModel chatModel, NotifyTools notifyTools) {
return ReactAgent.builder()
.name("send_notification")
.description("发送通知消息。当用户想发送通知、提醒时调用此工具。")
.systemPrompt("你是通知发送助手。根据用户的要求发送通知消息。")
.model(chatModel)
.methodTools(notifyTools)
.inputType(String.class)
.build();
} @Bean("supervisorAgent")
public ReactAgent supervisorAgent(
ChatModel chatModel,
ReactAgent orderAgent,
ReactAgent notifyAgent,
MemorySaver memorySaver) {
return ReactAgent.builder()
.name("personal_assistant")
.systemPrompt("你是一个智能个人助手。")
.model(chatModel)
.saver(memorySaver)
.tools(
AgentTool.getFunctionToolCallback(orderAgent),
AgentTool.getFunctionToolCallback(notifyAgent))
.build();
}
}
@Component
public class OrderQueryTools {
@Tool(description = "查询订单状态,返回订单详情")
public String queryOrderStatus(@ToolParam(description = "订单号") String orderId) {
return "订单 " + orderId + " 状态:已发货,预计明天到达";
}
}@Component
public class NotifyTools {
@Tool(description = "发送通知给用户")
public String sendNotification(
@ToolParam(description = "收件人") String recipient,
@ToolParam(description = "通知内容") String message) {
return "已发送通知给 " + recipient + ":" + message;
}
}
@Test
void testSupervisor() throws GraphRunnerException {
String query = "查一下订单456的状态,然后通知用户已发货";
AssistantMessage response = supervisorAgent.call(new UserMessage(query));
System.out.println(response.getText());
}
当用户问题可能有多种类型时:
Routing模式实现智能路由——LLM先理解用户意图,再分发给最合适的子Agent。
Routing与Supervisor的主要区别:
@Bean("routingAgent")
public ReactAgent routingAgent(ChatModel chatModel,
ReactAgent githubAgent, ReactAgent notionAgent, ReactAgent slackAgent) {
return ReactAgent.builder()
.name("router")
.systemPrompt("""
你是一个智能路由器。根据用户的提问内容,
判断属于哪个专业领域,然后调用对应的专业工具。
重要规则:一次只调用一个工具。""")
.model(chatModel)
.tools(
AgentTool.getFunctionToolCallback(githubAgent),
AgentTool.getFunctionToolCallback(notionAgent),
AgentTool.getFunctionToolCallback(slackAgent))
.build();
}
客服系统中的典型流程:
Handoffs是状态驱动的模式——同一Agent根据当前步骤动态调整行为。
三大核心组件:
current_step动态切换系统提示和工具getStateForUpdate(toolContext)更新状态Step 1: HandoffsConfig
@Configuration
public class HandoffsConfig { @Bean("supportAgent")
public ReactAgent supportAgent(ChatModel chatModel, MemorySaver memorySaver) {
List allTools = List.of(
SupportTools.recordWarrantyStatusTool(),
SupportTools.recordIssueTypeTool(),
SupportTools.provideSolutionTool(),
SupportTools.escalateToHumanTool()); return ReactAgent.builder()
.name("support_agent")
.systemPrompt("你是客服助手,帮助用户解决设备问题。")
.model(chatModel)
.tools(allTools)
.hooks(new HandoffsSupportHook())
.saver(memorySaver)
.build();
}
}
Step 2: HandoffsSupportHook
public class HandoffsSupportHook extends ModelHook { private final ModelInterceptor stepConfigInterceptor; public HandoffsSupportHook() {
this.stepConfigInterceptor = new StepConfigInterceptor(Map.of(
"warranty_collector", new StepConfig(
"你是客服助手,负责收集保修状态。",
List.of(SupportTools.recordWarrantyStatusTool()), List.of()),
"issue_classifier", new StepConfig(
"你是技术支持,判断硬件故障还是软件问题。",
List.of(SupportTools.recordIssueTypeTool()),
List.of("warranty_status")),
"resolution_specialist", new StepConfig(
"你是解决方案专家。提供方案或转人工。",
List.of(SupportTools.provideSolutionTool(),
SupportTools.escalateToHumanTool()),
List.of("warranty_status", "issue_type"))));
} @Override
public List getModelInterceptors() {
return List.of(stepConfigInterceptor);
} @Override
public Map getKeyStrategys() { // 注意方法名
return Map.of(
"current_step", new ReplaceStrategy(),
"warranty_status", new ReplaceStrategy(),
"issue_type", new ReplaceStrategy());
} public record StepConfig(String prompt, List tools,
List requiredKeys) {}
}
Step 3: StepConfigInterceptor
class StepConfigInterceptor extends ModelInterceptor { private final Map stepConfigMap; StepConfigInterceptor(Map stepConfigMap) {
this.stepConfigMap = stepConfigMap;
} @Override
public ModelResponse interceptModel(ModelRequest request,
ModelCallHandler handler) {
Map context = request.getContext();
String currentStep = (String) context.getOrDefault(
"current_step", "warranty_collector"); StepConfig stepConfig = stepConfigMap.getOrDefault(
currentStep, stepConfigMap.get("warranty_collector")); for (String required : stepConfig.requiredKeys()) {
if (context.get(required) == null) {
throw new IllegalStateException(
required + " 必须在进入 " + currentStep + " 之前设置");
}
} List toolNames = stepConfig.tools().stream()
.map(t -> t.getToolDefinition().name())
.toList(); ModelRequest overridden = ModelRequest.builder(request)
.systemMessage(new SystemMessage(stepConfig.prompt()))
.tools(toolNames)
.build(); return handler.call(overridden); // 必须调用handler继续执行
}
}
Step 4: SupportTools
public final class SupportTools { @Tool(name = "record_warranty_status",
description = "记录客户的保修状态,并切换到故障分类步骤")
public String recordWarrantyStatus(
@ToolParam(description = "in_warranty 或 out_of_warranty") String status,
ToolContext toolContext) {
ToolContextHelper.getStateForUpdate(toolContext)
.ifPresent(update -> { // Optional处理
update.put("warranty_status", status);
update.put("current_step", "issue_classifier");
});
return "已记录保修状态:" + status;
} @Tool(name = "record_issue_type",
description = "记录故障类型(硬件或软件),并切换到解决方案步骤")
public String recordIssueType(
@ToolParam(description = "hardware 或 software") String issueType,
ToolContext toolContext) {
ToolContextHelper.getStateForUpdate(toolContext)
.ifPresent(update -> {
update.put("issue_type", issueType);
update.put("current_step", "resolution_specialist");
});
return "已记录故障类型:" + issueType;
} // 其他工具方法...
}
@Test
void testHandoffsWorkflow() throws GraphRunnerException {
RunnableConfig config = RunnableConfig.builder()
.threadId("test-session-1")
.build(); AssistantMessage r1 = supportAgent.call(new UserMessage("我手机屏幕碎了"), config);
AssistantMessage r2 = supportAgent.call(new UserMessage("还在保修期内"), config);
AssistantMessage r3 = supportAgent.call(new UserMessage("摔了一下屏幕裂了"), config);
AssistantMessage r4 = supportAgent.call(new UserMessage("怎么办"), config);
}
当Agent拥有大量技能时,全量加载会导致上下文过长,资源浪费。Skills模式实现按需加载——初始只提供描述,使用时才加载完整内容。
Skills模式基于渐进披露原则:
read_skill工具按需加载完整SKILL.mdsrc/main/resources/skills/
├── sales_analytics/
│ └── SKILL.md
└── inventory_management/
└── SKILL.md
SKILL.md示例:
---
name: sales_analytics
description: 数据库Schema和业务逻辑,用于销售数据分析。包含客户、订单、收入等表。
---# 销售数据分析## 数据库Schema| 表名 | 说明 | 主要字段 |
|------|------|----------|
| customers | 客户信息 | id, name, email |
| orders | 订单信息 | id, customer_id, amount |
| revenue | 收入记录 | id, order_id, amount |## 示例查询SELECT c.name, SUM(o.amount) as total_amount
FROM customers c JOIN orders o ON c.id = o.customer_id
WHERE o.order_date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
GROUP BY c.id, c.name HAVING total_amount > 1000;
@Configuration
public class SkillsConfig { @Bean
public SkillRegistry skillRegistry() {
return ClasspathSkillRegistry.builder()
.classpathPath("skills")
.build();
} @Bean
public SkillsAgentHook skillsAgentHook(SkillRegistry skillRegistry) {
return SkillsAgentHook.builder()
.skillRegistry(skillRegistry)
.build();
} @Bean("sqlAssistantAgent")
public ReactAgent sqlAssistantAgent(ChatModel chatModel,
SkillsAgentHook skillsAgentHook) {
return ReactAgent.builder()
.name("sql_assistant")
.systemPrompt("""
你是一个SQL查询助手,帮助用户编写针对业务数据库的查询。
当需要特定领域的详细表结构或业务逻辑时,使用read_skill工具。""")
.model(chatModel)
.hooks(List.of(skillsAgentHook))
.build();
}
}