1. 引言

在多智能体系统中,如何让多个专家 Agent 协同工作是一个核心问题。SpringAI Alibaba 框架提供了多种交接策略(Handoff Strategy),让主节点来决定选择后续需要执启用的子Agent,虽然在官方最新的版本中,移除了 SupervisorAgent 的支持,转而使用 Agent As Tool的方式来实现监督者策略

本教程将基于 /ali/L08-multi-agent-supervisor 项目,介绍一下如何在一个真实的应用场景中你,利用监督者策略,来实现一个旅游行程规划智能体,并简单对比一下SupervisorAgent 和 AgentAsTool两种实现策略的异同

重要提示:在 SpringAI Alibaba 的最新框架中,监督者策略已经被移除,改为将 Agent 作为工具(Agent-as-Tool)的方式来实现类似效果。 若只希望关注最新的应用案例的小伙伴,也可以不需了解SupervisorAgent,直接看下一篇的Agent As Tool即可

  1. 背景知识

2.1 多智能体交接策略概述

SpringAI Alibaba 框架支持多种多智能体协作模式:

模式 特点 适用场景
路由模式(Router) 单次决策,将请求路由到最合适的 Agent 简单的分类和路由任务
监督者模式(Supervisor) 多步循环,监督者协调多个专家 Agent 复杂的多步骤协作任务
状态驱动交接(State-driven) 基于状态和条件的 Agent 切换 需要精确控制流程的任务,如典型的LangGraph应用案例

2.2 监督者策略的核心思想

监督者策略的核心是中心化的任务协调

  1. 监督者(Supervisor)

    :负责接收用户请求、分解任务、协调专家、整合结果

  2. 专家 Agent(Specialist)

    :专注于特定领域的任务执行

  3. 循环调度

    :监督者可以多次调用不同的专家,直到任务完成

用户请求 → 监督者 → 专家A → 监督者 → 专家B → 监督者 → 整合结果 → 用户

2.3 与其他模式的对比

特性 路由模式 监督者模式
决策次数 单次 多次
子 Agent 返回 直接结束 返回监督者
占位符支持 ✅ ({input})
状态聚合
复杂度
  1. 项目结构

3.1 整体架构

L08-multi-agent-supervisor/├── src/main/java/com/git/hui/springai/ali/│   ├── controller/│   │   ├── TravelPlanController.java      # REST 控制器(SSE 流式接口)│   │   └── HookFactory.java               # Hook 工厂(日志和监控)│   ├── planer/│   │   ├── TravelSupervisorPlanAgent.java # 监督者 Agent(核心)│   │   ├── AttractionAgent.java           # 景点推荐专家│   │   ├── HotelAgent.java                # 住宿推荐专家│   │   └── TransportAgent.java            # 交通规划专家│   └── L08Application.java                # Spring Boot 启动类├── src/main/resources/│   ├── templates/│   │   └── travel-plan.html               # 前端界面│   └── application.yml                    # 配置文件└── pom.xml                                # Maven 依赖

3.2 依赖配置

<!-- 不能使用 1.1.2.2+ 版本,因为 SupervisorAgent 被删除了     --><dependency>    <groupId>com.alibaba.cloud.ai</groupId>    <artifactId>spring-ai-alibaba-agent-framework</artifactId>    <version>1.1.2.1</version></dependency><!-- SpringAI Alibaba 核心依赖 --><dependency>    <groupId>org.springframework.ai</groupId>    <artifactId>spring-ai-starter-model-openai</artifactId></dependency><!-- Spring Boot Web --><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId>    </dependency></dependencies>

3.3 API 配置

spring:  ai:    openai:      api-key: ${silicon-api-key}      base-url: https://api.siliconflow.cn      chat:        options:          model: Qwen/Qwen3-8B
  1. 核心代码解析

4.1 监督者 Agent 实现

TravelSupervisorPlanAgent.java 是整个系统的核心,负责协调各个专家 Agent:

@ComponentpublicclassTravelSupervisorPlanAgent {    privatefinal AttractionAgent attractionAgent;    privatefinal HotelAgent hotelAgent;    privatefinal TransportAgent transportAgent;    privatefinal ChatModel chatModel;    public Agent agent() {        AgentHooklogHook= HookFactory.createLogAgentHook();                SupervisorAgentsupervisorAgent= SupervisorAgent.builder()                .name("supervisor_agent")                .description("内容管理监督者,负责协调景点推荐、城市规划、住宿推荐等")                .model(chatModel)                .mainAgent(ReactAgent.builder()                        .name("main_agent")                        .model(chatModel)                        .description("监督者主Agent,负责路由决策")                        .systemPrompt("""                                你是一个旅行规划监督者,你的任务是帮助用户制定旅行计划。                                你可以协调以下专家:                                - attraction_agent:负责推荐景点、安排游览路线。                                - transport_agent:负责规划城市间交通和市内交通。                                - hotel_agent:负责推荐酒店、民宿等住宿。                                                                ## 路由决策输出格式                                当需要做出路由决策时,请以 JSON 数组格式输出:                                - 选择单个子Agent: ["attraction_agent"]                                - 选择多个子Agent: ["transport_agent", "hotel_agent"]                                - 任务完成: [] 或 ["FINISH"]                                """)                        .instruction("用户的请求是: {input}")                        .outputKey("final_output")                        .build())                .subAgents(List.of(                    attractionAgent.agent(),                     hotelAgent.agent(),                     transportAgent.agent()                ))                .hooks(List.of(logHook))                .build();        return supervisorAgent;    }}

关键点解析

  1. mainAgent

    :监督者的主 Agent,负责路由决策

  2. subAgents

    :专家 Agent 列表

  3. hooks

    :用于日志记录和监控

  4. {input} 占位符

    :在执行时会被替换为实际的用户输入

  5. JSON 路由格式

    :监督者通过输出 JSON 数组来决定下一步调用哪个专家(或者哪几个专家)

4.2 专家 Agent 实现

本文的案例主要是为了演示监督者的交接方式,各子Agent的实现相对简陋,大家完全可以丰富子Agent的能力,将其与外部的工具进行联动,比如查询小红书的旅游推荐、地图的导航、美团/携程的酒店预定等能力

@RequiredArgsConstructor@ComponentpublicclassAttractionAgent {    privatefinal ChatModel chatModel;    public ReactAgent agent() {        ReactAgentagent= ReactAgent.builder()                .name("attraction_agent")                .model(chatModel)                .description("景点推荐专家,善于根据用户的需求推荐各种适合游玩的景点")                .instruction("""                        你是一个旅行景点推荐专家。请根据用户的目的地、天数、偏好,                        推荐合适的景点和游览顺序。                        当前已知信息:{input}                        如果某些信息不完整,请基于已有信息尽量给出合理建议。                        直接返回景点计划,包含每日安排。                        """)                .outputKey("attraction_plan")                .enableLogging(true)                .build();        return agent;    }}@RequiredArgsConstructor@ComponentpublicclassHotelAgent {    privatefinal ChatModel chatModel;    public ReactAgent agent() {        ReactAgentagent= ReactAgent.builder()                .name("hotel_agent")                .model(chatModel)                .description("住宿推荐专家,善于根据用户需求推荐适合的住宿")                .instruction("""                        你是一个住宿推荐专家。请根据用户的景点计划、预算,推荐合适的住宿地点和酒店。                        输入:{input}                        请返回住宿建议,包括区域和酒店示例。                        """                )                .outputKey("hotel_plan")                .enableLogging(true)                .build();        return agent;    }}@RequiredArgsConstructor@ComponentpublicclassTransportAgent {    privatefinal ChatModel chatModel;    public ReactAgent agent() {        ReactAgentagent= ReactAgent.builder()                .name("transport_agent")                .model(chatModel)                .description("交通规划专家,善于根据用户需求规划最佳的出行方式")                .instruction("""                        你是一个交通规划专家。请根据用户的出发地、目的地、景点安排,规划交通方式。                        输入:{input}                        请返回详细的交通方案,包括城际交通和市内交通建议。                          """                )                .enableLogging(true)                .outputKey("transport_plan")                .build();        return agent;    }}

关键点

  • name

    :Agent 的唯一标识符,用于路由决策

  • description

    :简短描述,帮助监督者理解 Agent 的职责

  • instruction

    :详细的指令模板,包含 {input} 占位符

  • outputKey

    :输出结果的键名,用于状态聚合

4.3 Agent 依赖关系

在旅游行程规划中,Agent 之间存在依赖关系:

用户请求    ↓监督者 (Supervisor)    ↓景点推荐 (AttractionAgent) ← 必须首先执行    ↓    ├── 住宿推荐 (HotelAgent) ← 依赖景点信息    └── 交通规划 (TransportAgent) ← 依赖景点信息    ↓监督者整合 → 最终方案

监督者通过系统提示中的指令来确保执行顺序:

.systemPrompt("""    请记得在制定计划时,始终先调用 attraction_agent 来推荐景点、安排旅游路线;    因为 transport_agent 和 hotel_agent 这两个子 Agent 的执行都依赖 attraction_agent 的输出    """)

4.4 Hook 机制

HookFactory 提供了 Agent 执行过程的监控能力:

public static AgentHook createLogAgentHook() {    returnnewAgentHook() {        @Override        public CompletableFuture<Map<String, Object>> beforeAgent(                OverAllState state, RunnableConfig config) {            System.out.println("BEFORE AGENT: " + getAgentName());            // 记录输入和状态            return CompletableFuture.completedFuture(Map.of());        }        @Override        public CompletableFuture<Map<String, Object>> afterAgent(                OverAllState state, RunnableConfig config) {            System.out.println("AFTER AGENT: " + getAgentName());            // 记录输出和结果            return CompletableFuture.completedFuture(Map.of());        }    };}
  1. 实战:旅游行程规划智能体

5.1 系统工作流程

  1. 接收用户请求

    :用户通过 API 提交旅行需求

  2. 监督者分解任务

    :将复杂任务分解为景点、住宿、交通等子任务

  3. 协调专家执行

    :按顺序调用各个专家 Agent

  4. 结果整合

    :汇总所有专家的建议,形成完整的旅行计划

5.2 流式 API 实现

TravelPlanController.java 实现了基于 SSE 的流式接口:

@GetMapping(value = "/plan", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<ServerSentEvent<String>> planTravelStream(        @RequestParam String destination,        @RequestParam(required = false, defaultValue = "3") Integer days,        @RequestParam(required = false) String budget,        @RequestParam(required = false) String preferences) {    AgentsupervisorAgent= travelSupervisorPlanAgent.agent();    // 构建用户请求    Stringprompt= String.format("我想去%s旅行%d天,预算%s,我喜欢%s。请帮我制定详细的旅行计划。",            destination, days, budget, preferences);    // 获取流式输出    Flux<NodeOutput> agentStream = supervisorAgent.stream(prompt, config);    return agentStream            .filter(nodeOutput -> !(nodeOutput instanceof StreamingOutput<?> so &&                    so.getOutputType() == OutputType.AGENT_MODEL_FINISHED))            .map(nodeOutput -> {                // 构建 SSE 事件                Map<String, Object> data = newHashMap<>();                data.put("node", nodeOutput.node());                data.put("agent", nodeOutput.agent());                data.put("content", extractContent(nodeOutput));                data.put("stage", determineStage(nodeOutput.agent()));                                return ServerSentEvent.<String>builder()                        .event("message")                        .data(objectMapper.writeValueAsString(data))                        .build();            });}

5.3 阶段标识

系统通过 Agent 名称来确定当前执行阶段:

private String determineStage(String agentName) {    if (agentName.contains("attraction")) {        return"attraction"; // 景点推荐    } elseif (agentName.contains("hotel")) {        return"hotel"; // 住宿推荐    } elseif (agentName.contains("transport")) {        return"transport"; // 交通规划    } elseif (agentName.contains("supervisor")) {        return"supervisor"; // 监督者统筹    }    return"unknown";}

5.4 API 使用示例

# 请求curl -X GET "http://localhost:8080/api/travel/plan?destination=北京&days=5&budget=5000元&preferences=美食,历史文化"# 响应(SSE 流式)event: messagedata: {"node":"attraction_agent","agent":"attraction_agent","content":"推荐景点:故宫、天坛...","stage":"attraction"}event: messagedata: {"node":"hotel_agent","agent":"hotel_agent","content":"推荐住宿:王府井附近...","stage":"hotel"}event: messagedata: {"node":"supervisor_agent","agent":"supervisor_agent","content":"完整方案:...","stage":"supervisor"}
  1. 流式输出与前端展示

6.1 前端架构

前端采用四面板布局,实时展示各个专家的工作进度:

<div class="content-section">    <!-- 景点推荐面板 -->    <divclass="stage-panel"id="attractionPanel">        <divclass="stage-header">            <divclass="stage-icon">🏛️</div>            <divclass="stage-title">景点推荐</div>        </div>        <divclass="stage-content"id="attractionContent">            <divclass="placeholder-text">等待开始规划...</div>        </div>    </div>        <!-- 其他面板... --></div>

6.2 SSE 连接处理

function startPlanning() {    const url = `/api/travel/plan?destination=${encodeURIComponent(destination)}&days=${days}`;    eventSource = newEventSource(url);    eventSource.addEventListener('message', function(event) {        const data = JSON.parse(event.data);                if (data.stage && data.hasContent) {            updateStageContent(data.stage, data.content);            activatePanel(data.stage);            updateAgentBadge(data.stage);        }    });    eventSource.addEventListener('done', () => {        completePlanning();    });}

6.3 Markdown 渲染

前端使用 marked.js 渲染 Markdown 内容:

function updateStageContent(stage, content) {    contentAccumulators[stage] += content;        const contentElement = document.getElementById(stage + 'Content');    if (contentElement) {        const htmlContent = marked.parse(contentAccumulators[stage]);        contentElement.innerHTML = htmlContent;        contentElement.scrollTop = contentElement.scrollHeight;    }}

6.4 Agent体验

接下来我们来实际体验一下这个agent的表现情况,直接浏览器访问

  1. 框架迁移:从监督者到 Agent-as-Tool

7.1 监督者模式的局限性

监督者模式虽然强大,但也存在一些问题:

  1. 复杂度高

    :需要维护复杂的路由逻辑和 SUPERVISOR_NEXT_KEY 状态管理

  2. 调试困难

    :多步骤的执行流程难以追踪

  3. 灵活性不足

    :Hub-and-spoke 模式限制了 Agent 之间的直接交互

7.2 Agent-as-Tool 模式

在最新版本的 SpringAI Alibaba 中,推荐使用 Agent-as-Tool 模式(也称为 Agent Tool 模式):

import com.alibaba.cloud.ai.graph.agent.ReactAgent;import com.alibaba.cloud.ai.graph.agent.AgentTool;// 创建专家 AgentReactAgentattractionAgent= ReactAgent.builder()        .name("attraction_agent")        .model(chatModel)        .description("景点推荐专家")        .instruction("你是一个旅行景点推荐专家...")        .build();ReactAgenthotelAgent= ReactAgent.builder()        .name("hotel_agent")        .model(chatModel)        .description("住宿推荐专家")        .instruction("你是一个住宿推荐专家...")        .build();// 创建主 Agent,将专家 Agent 作为工具ReactAgentsupervisorAgent= ReactAgent.builder()        .name("supervisor_agent")        .model(chatModel)        .instruction("你是一个旅行规划助手,使用工具来完成任务。")        .tools(            AgentTool.getFunctionToolCallback(attractionAgent),            AgentTool.getFunctionToolCallback(hotelAgent)        )        .build();// 使用Optional<OverAllState> result = supervisorAgent.invoke("帮我规划北京5日游");

7.3 模式对比

特性 监督者模式 (已弃用) Agent-as-Tool 模式
实现方式 SupervisorAgent.builder() ReactAgent.builder().tools()
路由机制 显式 JSON 路由 LLM 自动工具选择
执行模式 Hub-and-spoke 循环 标准工具调用
子 Agent 返回 返回监督者继续循环 执行后返回结果
状态管理 SUPERVISOR_NEXT_KEY 标准工具调用状态
复杂度
可维护性

7.4 多智能体模式选择指南

根据官方文档,选择合适的多智能体模式:

需求场景 推荐模式
集中式工作流控制 AgentTool (工具调用)
Agent 直接与用户交互 Handoffs (交接)
一次性路由决策 LlmRoutingAgent (路由)
多步骤迭代路由 AgentTool (循环工具调用)

7.5 迁移示例

旧代码(SupervisorAgent - 已弃用)

SupervisorAgent supervisor = SupervisorAgent.builder()    .name("supervisor")    .model(chatModel)    .mainAgent(ReactAgent.builder()        .name("main_agent")        .systemPrompt("路由任务到 Agent...")        .build())    .subAgents(List.of(writerAgent, translatorAgent))    .build();

新代码(Agent-as-Tool - 推荐)

ReactAgent supervisor = ReactAgent.builder()    .name("supervisor")    .model(chatModel)    .instruction("使用工具来完成任务。")    .tools(        AgentTool.getFunctionToolCallback(writerAgent),        AgentTool.getFunctionToolCallback(translatorAgent)    )    .build();

7.6 注释代码示例

TravelSupervisorPlanAgent.java 中,我们可以看到被注释掉的旧实现:

// 旧的实现方式(已被注释)ReactAgent agent = ReactAgent.builder()        .name("supervisor_agent")        .model(chatModel)        .systemPrompt("你是一个旅行规划监督者...")        .saver(new MemorySaver())        .tools(            AgentTool.getFunctionToolCallback(attractionAgent.agent()),            AgentTool.getFunctionToolCallback(hotelAgent.agent()),            AgentTool.getFunctionToolCallback(transportAgent.agent())        )        .build();

学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%免费

在这里插入图片描述

Logo

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

更多推荐