一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Spring AI Alibaba 1.1.2 实战详解:5大多Agent编排模式权威指南

时间:2026-05-29 17:50:02 编辑:袖梨 来源:一聚教程网

多Agent编排技术让AI协作更高效,Spring AI Alibaba 1.1.2版本提供了5种实用模式,本文将详细解析每种模式的实现方法与应用场景。

Spring AI Alibaba 1.1.2 实战:5种多Agent编排模式完全指南

先说结论

单一大型模型处理复杂任务往往效率低下,合理的方式是将任务分解,让专业AI分工协作。

Spring AI Alibaba 1.1.2 实战:5种多Agent编排模式完全指南

任务分解的核心思路包括:

  1. 查询类任务由专门Agent处理
  2. 执行类任务交给特定Agent
  3. 汇总任务由协调Agent完成

这种分工协作就是多Agent编排的精髓。Spring AI Alibaba 1.1.2.2版本提供了5种编排模式:Supervisor / Routing / Handoffs / Skills / Workflow,本文将通过官方示例源码逐一讲解。


一、Supervisor模式:一个大总管调度多个小弟

1.1 适用场景

当用户提出包含多个子任务的复合请求时,例如"帮我安排明天9点站会,再发邮件通知团队",需要:

  1. 调用日历Agent安排会议
  2. 调用邮件Agent发送通知
  3. 汇总结果返回给用户

Supervisor模式就是这样的任务协调中心

1.2 核心API速览

实现思路:先为子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();

1.3 完整代码

POM依赖
<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();
    }
}
子Agent的工具类
@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模式:看菜下单,谁擅长谁来

2.1 适用场景

当用户问题可能有多种类型时:

  1. 咨询GitHub使用 → GitHub Agent
  2. 询问Notion功能 → Notion Agent
  3. 了解Slack操作 → Slack Agent

Routing模式实现智能路由——LLM先理解用户意图,再分发给最合适的子Agent。

2.2 实现思路

Routing与Supervisor的主要区别:

  1. Supervisor:协调多个子Agent同时工作
  2. Routing:仅负责分发,每次调用一个子Agent
@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模式:A干不了就递给B

3.1 适用场景

客服系统中的典型流程:

  1. 收集保修信息 → 基础问题处理
  2. 故障分类 → 判断硬件/软件问题
  3. 解决方案 → 提供方案或转人工

Handoffs是状态驱动的模式——同一Agent根据当前步骤动态调整行为。

3.2 实现原理

三大核心组件:

  1. ModelHook:注册拦截器和状态管理策略
  2. ModelInterceptor:根据current_step动态切换系统提示和工具
  3. ToolContextHelper:通过getStateForUpdate(toolContext)更新状态

3.3 完整代码

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;
    }    // 其他工具方法...
}
使用效果(4轮对话,同一threadId)
@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);
}

四、Skills模式:需要时才召唤

4.1 适用场景

当Agent拥有大量技能时,全量加载会导致上下文过长,资源浪费。Skills模式实现按需加载——初始只提供描述,使用时才加载完整内容。

4.2 实现原理

Skills模式基于渐进披露原则:

  1. 启动时注入技能元数据
  2. 通过read_skill工具按需加载完整SKILL.md
  3. 核心组件包括SkillRegistry、SkillsAgentHook和标准化的SKILL.md格式

4.3 完整代码

技能文件结构
src/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();
    }
}
运行

热门栏目