前言

什么是 Spring AI StateGraph 多智能体?

你可以把它理解为: AI 团队协作工作流

  • 路由智能体:产品经理,拆解需求、分发任务

  • 执行智能体:开发 / 设计 / 运营,专注单一能力

  • 汇总智能体:项目经理,整理结果、统一输出

  • StateGraph:流程引擎,自动驱动智能体按顺序 / 分支执行

Spring AI 1.0 官方推出 StateGraph 状态图,真正实现多智能体自动化编排。 你只需要定义:

  • 智能体节点(咨询、库存、支付、物流、汇总)

  • 状态流转(顺序 / 分支 / 并行)

  • 业务工具(@Tool)

AI 就能像团队协作一样,自动完成: 咨询商品 → 校验库存 → 创建订单 → 支付宝支付 → 物流查询 → 结果汇总 全流程无需人工干预。

案例一:简易多智能体(入门必备)

场景

用户一句话: 介绍Spring AI,计算128/4,告诉我现在时间

智能体自动分工:

  • 路由 Agent → 拆分子任务

  • 执行 Agent → 调用知识、计算、时间工具

  • 汇总 Agent → 整理友好回复

1. 工具类(业务能力)

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Component
public class AgentTools {

    // 知识讲解
    @Tool(description = "讲解技术知识、概念介绍,用户询问技术内容时调用")
    public String explainTech(@ToolParam(description = "需要讲解的内容") String content) {
        if ("Spring AI".equals(content)) {
            return "Spring AI 是 Spring 官方 AI 框架,统一封装大模型、工具调用、RAG、智能体能力,无缝对接 Spring Boot 项目。";
        }
        return "暂无相关介绍";
    }

    // 数学计算
    @Tool(description = "数学加减乘除运算,用户需要计算时调用")
    public String calculate(double num1, String op, double num2) {
        double res = switch (op) {
            case "+" -> num1 + num2;
            case "-" -> num1 - num2;
            case "*" -> num1 * num2;
            case "/" -> num1 / num2;
            default -> 0;
        };
        return "计算结果:" + res;
    }

    // 获取时间
    @Tool(description = "获取当前服务器时间,用户问时间、几点时调用")
    public String getNowTime() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }
}

2. 状态上下文(智能体共享数据)

import lombok.Data;
import java.util.List;

@Data
public class UniversalTaskState {
    // 用户原始请求
    private String userQuery;

    // 动态子任务列表(通用!任意数量)
    private List<String> subTasks;

    // 动态执行结果列表
    private List<String> taskResults;

    // 最终返回给用户的结果
    private String finalReply;
}

3. StateGraph 多智能体编排(核心)

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.graph.StateGraph;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class UniversalAgentConfig {

    private final ChatClient chatClient;
    private final AgentTools agentTools;

    public UniversalAgentConfig(ChatClient.Builder builder, AgentTools agentTools) {
        this.chatClient = builder.build();
        this.agentTools = agentTools;
    }

    @Bean
    public StateGraph<UniversalTaskState> universalAgentGraph() {
        StateGraph.Builder<UniversalTaskState> builder = StateGraph.builder(UniversalTaskState.class);

        // ======================
        // 节点1:路由智能体(动态拆任意子任务)
        // ======================
        builder.addNode("router", state -> {
            String prompt = """
                请把用户的请求拆成多个独立子任务,每行一个。
                不要编号,不要多余内容。
                用户请求:%s
                """.formatted(state.getUserQuery());

            String response = chatClient.prompt(prompt).call().content();
            List<String> tasks = response.lines()
                    .map(String::trim)
                    .filter(line -> !line.isBlank())
                    .toList();

            state.setSubTasks(tasks);
            state.setTaskResults(new ArrayList<>());
        });

        // ======================
        // 节点2:执行智能体(自动批量执行所有子任务)
        // ======================
        builder.addNode("executor", state -> {
            List<String> tasks = state.getSubTasks();
            List<String> results = state.getTaskResults();

            for (String task : tasks) {
                String result = chatClient.prompt()
                        .user(task)
                        .tools(agentTools)
                        .call().content();

                results.add(result);
            }
        });

        // ======================
        // 节点3:汇总智能体(统一输出)
        // ======================
        builder.addNode("summarizer", state -> {
            String allResult = String.join("\n", state.getTaskResults());
            String prompt = "请把以下结果整理成友好的自然语言回复:\n" + allResult;

            String finalReply = chatClient.prompt(prompt).call().content();
            state.setFinalReply(finalReply);
        });

        // ======================
        // 通用流程(不写死任何任务)
        // ======================
        builder.startWith("router")
               .then("executor")
               .then("summarizer")
               .end();

        return builder.build();
    }
}

4. 接口入口

import org.springframework.ai.graph.StateGraph;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UniversalAgentController {

    private final StateGraph<UniversalTaskState> graph;

    public UniversalAgentController(StateGraph<UniversalTaskState> graph) {
        this.graph = graph;
    }

    @GetMapping("/ai/agent/universal")
    public String run(@RequestParam String query) {
        UniversalTaskState state = new UniversalTaskState();
        state.setUserQuery(query);
        state = graph.run(state);
        return state.getFinalReply();
    }
}

5. 测试

http://localhost:8080/ai/agent/universal?query=介绍Spring AI,算128/4,现在几点
http://localhost:8080/ai/agent/universal?query=现在时间+介绍Java
http://localhost:8080/ai/agent/universal?query=计算99+199

案例二:电商支付多智能体


一、整体架构

用户请求
   ↓
【路由智能体】解析意图、抽取参数
   ↓
【咨询智能体】回答商品问题
   ↓
【库存智能体】校验库存
   ↓(分支:库存不足直接结束)
【支付智能体】调用支付宝Tool生成订单 & 收银台
   ↓
【物流智能体】预生成物流状态
   ↓
【汇总智能体】格式化返回结果

二、环境说明

  • SpringBoot 3.3.4

  • Spring AI 1.0.0-M1

  • 支付宝 SDK 4.34.0.ALL

  • 无需新增任何依赖(StateGraph 已内置)

  • 已有的:AlipayUtil、PaymentTool、yml 配置全部复用


三、第一步:增强版电商工具类

包含:商品咨询、库存、支付宝支付、物流

import lombok.RequiredArgsConstructor;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import java.util.UUID;

@Component
@RequiredArgsConstructor
public class EcommerceTool {

    private final AlipayUtil alipayUtil;

    // 1. 商品咨询
    @Tool(description = "用户咨询商品信息、功能、介绍时调用")
    public String goodsInfo(
            @ToolParam(description = "商品名称") String goodsName) {
        return "【商品介绍】" + goodsName + ":官方正版,永久有效,售后无忧";
    }

    // 2. 库存校验
    @Tool(description = "查询商品库存是否足够,是否可购买")
    public String stockCheck(
            @ToolParam(description = "商品名称") String goodsName) {
        // 真实项目对接数据库
        return "库存充足(198件),可正常下单";
    }

    // 3. 创建支付宝订单(核心!)
    @Tool(description = "创建支付订单,生成支付宝支付页面,用户确认购买时调用")
    public String createAliOrder(
            @ToolParam(description = "商品名称") String goodsName,
            @ToolParam(description = "支付金额,单位元") String amount) {
        String orderNo = "ORD_" + UUID.randomUUID().toString().replace("-", "");
        // 调用支付宝工具生成收银台表单
        String payHtml = alipayUtil.createPagePay(orderNo, goodsName, amount);
        return "订单创建成功!订单号:" + orderNo + "\n支付链接:" + payHtml;
    }

    // 4. 物流状态
    @Tool(description = "根据订单号查询物流状态")
    public String logisticsQuery(
            @ToolParam(description = "订单编号") String orderNo) {
        return "【物流】订单 " + orderNo + ":支付完成后24小时内发货,全程跟踪";
    }
}


四、第二步:状态实体(核心上下文传递)

智能体之间共享数据:商品名、订单号、各步骤结果

import lombok.Data;

@Data
public class EcommerceState {
    // 用户输入
    private String userQuery;
    // 抽取的商品名
    private String goodsName;
    // 订单金额
    private String amount;
    // 订单号(支付生成后传递)
    private String orderNo;

    // 各智能体结果
    private String infoResult;
    private String stockResult;
    private String payResult;
    private String logisticsResult;

    // 最终返回用户
    private String finalResponse;
}


五、第三步:StateGraph 多智能体编排(完整版)

包含:顺序流转 + 条件分支 + 参数传递

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.graph.StateGraph;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class EcommerceAgentGraph {

    private final ChatClient chatClient;
    private final EcommerceTool ecommerceTool;

    public EcommerceAgentGraph(ChatClient.Builder builder, EcommerceTool ecommerceTool) {
        this.chatClient = builder.build();
        this.ecommerceTool = ecommerceTool;
    }

    @Bean
    public StateGraph<EcommerceState> ecommerceStateGraph() {
        StateGraph.Builder<EcommerceState> graph = StateGraph.builder(EcommerceState.class);

        // ====================== 节点1:路由 & 信息抽取 ======================
        graph.addNode("RouterAgent", state -> {
            String prompt = """
                从用户 query 里抽取:商品名称、金额(默认99元)
                输出格式:商品名=xxx;金额=xxx
                用户输入:%s
                """.formatted(state.getUserQuery());

            String extract = chatClient.prompt(prompt).call().content();
            String[] arr = extract.split(";");
            state.setGoodsName(arr[0].split("=")[1]);
            state.setAmount(arr[1].split("=")[1]);
        });

        // ====================== 节点2:商品咨询智能体 ======================
        graph.addNode("InfoAgent", state -> {
            String res = chatClient.prompt()
                    .user("介绍商品:" + state.getGoodsName())
                    .tools(ecommerceTool)
                    .call().content();
            state.setInfoResult(res);
        });

        // ====================== 节点3:库存智能体 ======================
        graph.addNode("StockAgent", state -> {
            String res = chatClient.prompt()
                    .user("查询库存:" + state.getGoodsName())
                    .tools(ecommerceTool)
                    .call().content();
            state.setStockResult(res);
        });

        // ====================== 节点4:支付智能体 ======================
        graph.addNode("PayAgent", state -> {
            String res = chatClient.prompt()
                    .user("创建订单:%s,金额:%s".formatted(state.getGoodsName(), state.getAmount()))
                    .tools(ecommerceTool)
                    .call().content();
            state.setPayResult(res);
            // 抽取订单号到上下文
            if (res.contains("订单号:")) {
                state.setOrderNo(res.split("订单号:")[1].split("\n")[0]);
            }
        });

        // ====================== 节点5:物流智能体 ======================
        graph.addNode("LogisticsAgent", state -> {
            String res = chatClient.prompt()
                    .user("查询物流,订单号:" + state.getOrderNo())
                    .tools(ecommerceTool)
                    .call().content();
            state.setLogisticsResult(res);
        });

        // ====================== 节点6:汇总智能体 ======================
        graph.addNode("SummaryAgent", state -> {
            String all = """
                商品信息:%s
                库存状态:%s
                支付订单:%s
                物流说明:%s
                """.formatted(
                    state.getInfoResult(),
                    state.getStockResult(),
                    state.getPayResult(),
                    state.getLogisticsResult()
            );

            String summary = chatClient.prompt(
                    "整理成友好的购物结果回复给用户:" + all
            ).call().content();

            state.setFinalResponse(summary);
        });

        // ====================== 流程编排(完整版) ======================
        graph.startWith("RouterAgent")
                .then("InfoAgent")
                .then("StockAgent")
                .then("PayAgent")
                .then("LogisticsAgent")
                .then("SummaryAgent")
                .end();

        return graph.build();
    }
}


六、第四步:Controller 接口(对外提供访问)

import org.springframework.ai.graph.StateGraph;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EcommerceAgentController {

    private final StateGraph<EcommerceState> graph;

    public EcommerceAgentController(StateGraph<EcommerceState> graph) {
        this.graph = graph;
    }

    // 多智能体电商购物入口
    @GetMapping("/ai/shop")
    public String shop(@RequestParam String msg) {
        EcommerceState state = new EcommerceState();
        state.setUserQuery(msg);

        // 自动执行全流程
        EcommerceState result = graph.run(state);
        return result.getFinalResponse();
    }
}


七、测试

访问:

http://localhost:8080/ai/shop?msg=我想买年度会员

自动执行流程(AI 全自动完成)

  1. 路由智能体:抽取 商品 = 年度会员,金额 = 99 元

  2. 咨询智能体:返回商品介绍

  3. 库存智能体:校验库存充足

  4. 支付智能体:调用支付宝 Tool,生成订单 + 收银台

  5. 物流智能体:返回物流说明

  6. 汇总智能体:输出友好结果

返回结果示例

你好,你选择的商品是:年度会员
该商品为官方正版,永久有效,售后无忧。
当前库存充足(198件),可以正常购买。

已为你创建订单,订单号:ORD_xxxxxxx
点击即可进入支付宝收银台完成支付。

支付完成后24小时内发货,全程物流跟踪。

八、生产级增强(可选)

1. 分支判断:库存不足直接终止

graph.conditional("StockCheck", state -> {
    if (state.getStockResult().contains("不足")) {
        return "EndNode";
    } else {
        return "PayAgent";
    }
});

2. 接入 MCP 远程智能体

把支付 / 物流智能体部署为独立 MCP 服务,实现微服务多智能体。

3. 订单持久化

在 PayAgent 中把订单存入 MySQL。

4. 支付宝回调自动更新状态


九、总结

这是目前 Spring AI 官方标准的多智能体方案:

  • StateGraph = 多智能体编排引擎

  • @Tool = 智能体能力

  • State = 团队共享上下文

  • 全自动执行复杂业务流程(无需人工干预)

本案例可直接用于:

  • AI 电商

  • AI 付费会员

  • AI 付费咨询

  • AI 收银台

Logo

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

更多推荐