Spring AI Alibaba实战:Java后端构建AI Agent完整指南 📅 发布时间:2026/9/8 5:30:25 👁 浏览次数: AI Agent 开发在 Java 后端领域已经不是概念讨论而是可以直接落到 Spring Boot 项目里的具体工程实践。所谓 Agent可以理解成一个“会使用工具、会拆解任务、会连续推理”的智能执行单元传统接口是固定流程请求进来走完一套代码就返回Agent 则把“下一步做什么”的决策权交给大模型在运行时动态选择该回答、查数据还是调用某个业务工具。Spring AI Alibaba 是阿里巴巴开源的 Spring AI 生态实现它通过 Spring Boot starter 把 DashScope通义千问等大模型接入、Prompt 管理、Function Calling、会话记忆和 Agent 执行框架统一封装起来。这篇文章面向已经具备 Spring Boot 基础的 Java 工程师从 0 到 1 构建一个可运行的 Java AI Agent 项目先讲清运行原理再完成环境配置、最小问答 Agent、工具调用、多轮记忆最后给出验证方式、高频排错路径和生产落地建议。学完后可以在现有骨架里继续注册自己的业务工具把“能聊天”升级成“能干活”。1. 先理解 Java AI Agent 的核心运行逻辑1.1 从固定流程到动态决策先看一个对比。传统订单查询接口的代码路径是确定的Controller 接收订单号Service 按固定 SQL 查库Repository 返回结果。这套流程在写代码时就已经定死用户输入不同也只是参数不同执行分支不会超出开发者预定义的范围。AI Agent 不一样。假设用户说“查一下订单 A123456 的物流如果已经签收就给客户发一条确认短信”传统实现需要开发者提前把这个分支写进去而 Agent 的做法是把这个任务原样交给大模型由模型判断先查订单状态拿到结果后判断是否满足“已签收”条件再决定要不要调用发短信工具。工具是否被调用、调用顺序如何都是运行时动态决定的。这里最本质的转变是控制权转移。传统编程中开发者写死所有分支Agent 编程中开发者定义能力和边界大模型在边界内做规划和执行。这也是为什么 Agent 更像“做事的人”而不只是“返回文本的接口”。1.2 Agent 的最小闭环推理、行动、观察一个最小可用的 Agent 通常运行在“推理-行动-观察”循环里这种模式来自 ReAct 论文提出的范式Spring AI Alibaba 的 ReActAgent 就是把这套范式封装成了开箱即用的组件。完整循环如下系统拿到了用户目标和当前上下文包括系统提示词、历史消息、工具描述。大模型判断当前状态可以直接回答还是需要调用某个工具。如果需要工具模型输出结构化的工具名和参数程序负责执行真实函数。工具执行结果作为“观察”数据回传给模型。模型根据观察继续推理可能再次调用工具也可能生成最终答案。循环一直持续到模型给出最终回答或达到开发者设置的最大迭代次数。可以这样理解大模型是“大脑”负责决策程序里注册的普通 Java 方法是“手脚”负责执行工具描述是大脑的“说明书”告诉它什么场景下该调用什么方法。1.3 Spring AI Alibaba Agent Framework 解决什么问题如果不使用框架直接通过 HTTP 调用大模型接口做 Agent开发者需要自己处理的细节非常多请求 JSON 组装、流式响应解析、工具调用的参数映射、历史消息管理、错误重试、不同模型提供商的协议差异。这些工作重复且容易出错。Spring AI Alibaba 基于 Spring AI 做了云厂商适配和 Agent 能力扩展核心作用可以归纳为三点模型接入统一通过 starter 引入 DashScope 能力一个ChatModel接口屏蔽不同模型提供商的差异。工具注册标准化用Tool、ToolParam注解把普通 Java 方法暴露给模型。Agent 编排内置提供 ReActAgent 等执行器开发者只需要把模型和工具列表交给它。对比项自己写 HTTP 调用大模型Spring AI Alibaba工具调用解析手动解析模型返回的 function call JSON框架自动映射到 Java 方法会话记忆自己维护消息列表并拼接提供 ChatMemory 和 Advisor多模型切换每个厂商写一套客户端换 starter 和配置即可流式输出手动处理 SSEChatClient 原生支持可观测性自己埋点可接入 token 用量和日志这里要澄清一个容易误解的地方Agent 并不等于“调用一次大模型”。一次问答是单次推理Agent 是多次推理加多次工具执行的组合过程框架的价值主要体现在对这个组合过程的编排和稳定性保障上。2. 环境与依赖配置2.1 推荐的版本组合实战项目最怕环境不一致同一个 Demo 在不同机器上表现不同多数是 JDK、Spring Boot、Spring AI Alibaba 的版本组合问题。下面给出推荐的基准环境组件推荐版本说明JDK17Spring Boot 3.x 的基线版本Spring Boot3.2.x 或 3.3.x与 Spring AI Alibaba 当前版本匹配Maven3.8构建工具IDEA 自带也可Lombok1.18.30使用 JDK 21 时旧版会有编译告警Spring AI Alibaba以官方发布版本为准版本更新快示例版本号落地前要确认IDE 推荐 IntelliJ IDEA社区版即可。另外需要准备一个 DashScope阿里云百炼账号开通模型服务后获取 API Key。这是整个链路里唯一需要外部账号的部分没有 Key后续所有请求都会在鉴权阶段失败。JDK 版本这里要特别提一句Spring Boot 3.x 必须使用 Java 17 及以上不要拿 Java 8 直接跑。而如果使用 Java 21 或更高版本要同步升级 Lombok 到较新版本否则会出现“you arent using a compiler supported by lombok”这类编译告警它不影响整体构建但会让人误以为环境坏了。2.2 创建 Spring Boot 项目并引入依赖使用 IDEA 或 start.spring.io 创建空项目后在pom.xml中加入 Spring AI Alibaba 的 DashScope starter 和 Agent 模块依赖properties java.version17/java.version spring-ai-alibaba.version1.0.0-M6.1/spring-ai-alibaba.version /properties dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-starter-dashscope/artifactId version${spring-ai-alibaba.version}/version /dependency dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-agent/artifactId version${spring-ai-alibaba.version}/version /dependency /dependencies这里说明一下两个依赖的分工starter-dashscope负责模型接入会自动装配ChatModel、ChatClient等核心对象spring-ai-alibaba-agent提供 ReActAgent 等执行器组件。如果你的项目使用其他兼容 OpenAI 协议的服务可以把 starter 换成对应实现并覆盖base-url框架的设计目标就是让上层代码尽量不感知模型提供商差异。版本号在写这篇文章时还在快速迭代1.0.0-M6.1只是示例。如果 Maven 拉取失败或类名对不上优先去 Spring AI Alibaba 官方仓库查看当前发布版本再回填到 properties 里。2.3 配置 DashScope API Key 和模型在src/main/resources/application.yml中写入spring: application: name: java-ai-agent-demo ai: dashscope: api-key: ${DASHSCOPE_API_KEY} chat: options: model: qwen-plus核心配置只有两个API Key 和模型名。API Key 不要硬编码在 yml 里推荐使用环境变量DASHSCOPE_API_KEY这样即使代码上传到仓库也不会泄露密钥。属性前缀在不同版本可能不同老版本可能使用spring.ai.alibaba.dashscope.api-key配置不生效时先确认当前版本的文档。模型名可以根据成本和效果切换模型适用场景说明qwen-turbo高频、低成本的简单问答速度快、价格低qwen-plus通用场景、工具调用均衡选择Agent Demo 最常用qwen-max复杂推理、长文本效果更强成本和延迟更高2.4 启动前检查清单在写代码之前花两分钟按这个顺序检查环境能避免后面一半的报错执行java -version确认是 17 或更高版本。执行mvn -v确认 Maven 可用且 JDK 配置正确。确认 IDEA 里 Project Structure 的 SDK 和 Language level 都是 17。确认DASHSCOPE_API_KEY环境变量已设置或 IDE 的运行配置里已添加。确认 pom 中 Spring AI Alibaba 版本存在于 Maven 仓库。先执行mvn dependency:tree看依赖是否完整解析。其中最容易忽略的是第 4 项。很多人代码没问题启动也没报错第一次调接口收到 401才知道是 API Key 没有加载进去。3. 跑通第一个最小 Agent3.1 先用 ChatClient 验证模型链路Agent 项目的第一步不是直接上复杂框架而是先验证“模型能不能通”。Spring AI Alibaba 自动装配了ChatModel和ChatClient.Builder最小演示只需要一个 ControllerRestController RequestMapping(/api/agent) public class AgentController { private final ChatClient chatClient; public AgentController(ChatModel chatModel) { this.chatClient ChatClient.builder(chatModel).build(); } PostMapping(/chat) public MapString, String chat(RequestBody MapString, String request) { String message request.get(message); String answer chatClient.prompt() .user(message) .call() .content(); return Map.of(answer, answer); } }这段代码做的事情是接收用户消息构建一个 Prompt调用大模型返回生成的文本。ChatClient是 Spring AI 提供的流式 APIprompt()负责组装消息user()设置用户输入call()发起同步调用content()取出文本结果。3.2 启动并测试接口启动方式mvn spring-boot:run启动日志中如果看到 DashScope 相关自动配置加载成功并且没有 API Key 相关异常就可以发起测试curl -X POST http://localhost:8080/api/agent/chat \ -H Content-Type: application/json \ -d {message:用一句话解释什么是 AI Agent}正常响应类似{ answer: AI Agent 是一个能感知环境、自主决策并执行任务完成目标的智能程序。 }到这里模型接入链路已经打通这是后面所有 Agent 能力的基础。如果这一步都过不去不要继续往下写功能先解决网络、Key、版本问题。3.3 当前代码为什么还不是 Agent很多教程到这里就宣称“Agent 开发完成”这是不严谨的。当前实现的本质是“普通问答接口”它缺少三个关键能力不能调用外部工具模型只能依靠自身知识回答无法查数据库、查订单、发消息。没有记忆每一轮请求都是独立会话上一轮内容完全不记得。没有决策循环模型只回答一次不会根据结果继续行动。从下一节开始补上这三个能力之后它才真正具备 Agent 的形态。4. 用 Function Calling 让 Agent 真正“动手”4.1 工具调用解决了什么大模型训练数据有截止日期也没有访问企业内部系统的权限。直接问模型“订单 A123456 到哪了”模型只能编造答案。Function Calling工具调用机制解决了这个问题模型不擅自从混沌中猜业务数据而是输出“我需要调用queryOrderStatus参数是 A123456”这样的结构化指令由程序真正执行查询再把查询结果交回给模型组织回答。换句话说工具调用让模型从“只会说”变成“能做事”业务数据的唯一来源是真实系统模型只负责决策和表达。4.2 用 Tool 注解注册一个业务工具Spring AI Alibaba 提供了基于注解的工具注册方式。定义一个普通 Spring Bean在方法上标注Tool方法就会被纳入模型的工具列表Component public class OrderTools { Tool(name queryOrderStatus, description 根据订单号查询订单当前状态和物流信息) public String queryOrderStatus( ToolParam(description 订单编号例如 A123456) String orderId) { // 真实项目中这里会查询数据库或调用订单服务 if (A123456.equals(orderId)) { return 订单 A123456 已发货承运商顺丰预计 2026-05-20 前送达; } return 订单 orderId 不存在或状态未知; } }这里的细节很重要。模型并不知道 Java 方法的实现逻辑它只能看到工具的名称、描述和参数描述然后根据这些信息决定“什么时候调用、传什么参数”。因此name要短且直观方便模型识别。description要说明什么场景下使用越明确模型选错的概率越低。ToolParam的description必须补充参数业务含义否则模型可能猜错参数值。如果使用 JDK 21 且启动时报工具类加载异常先确认 Spring AI Alibaba 版本是否支持当前 JDK必要时回退到 JDK 17。4.3 把工具装配进 Agent有了工具还需要一个执行器来承载“推理-行动-观察”循环。Spring AI Alibaba 的 Agent 模块提供了 ReActAgent装配方式如下Configuration public class AgentConfiguration { Bean public ReActAgent orderAgent(ChatModel chatModel, OrderTools orderTools) { return new ReActAgent.Builder() .model(chatModel) .tools(List.of(orderTools)) .build(); } }修改 Controller把之前的ChatClient替换为ReActAgentRestController RequestMapping(/api/agent) public class AgentController { private final ReActAgent orderAgent; public AgentController(ReActAgent orderAgent) { this.orderAgent orderAgent; } PostMapping(/chat) public String chat(RequestBody MapString, String request) { return orderAgent.chat(request.get(message)); } }注意ReActAgent 在不同版本的包名、Builder 方法可能有调整。写代码时如果 IDE 无法自动补全直接打开引入的 jar 包查看实际类结构比在网上搜索过时的示例更可靠。4.4 一次完整的工具调用链路当用户输入“帮我查一下订单 A123456 的物流”时内部实际发生的过程可以拆成四步第一步模型接收到任务判断需要查订单工具输出结构化调用指令{ name: queryOrderStatus, arguments: {\orderId\:\A123456\} }第二步框架解析这个结构调用OrderTools.queryOrderStatus(A123456)拿到返回字符串。第三步框架把工具结果作为观察数据追加到消息列表再次发给模型。第四步模型看到真实物流信息组织最终回答返回给用户。这就是“推理-行动-观察”的完整闭环。框架帮你完成了第一步到第三部之间的 JSON 解析和方法映射你要做的就是定义好工具并把工具列表交给 Agent。4.5 工具注册的常见问题工具调用看起来简单但实际调试中高频踩坑点都在工具定义上问题现象原因解决方式模型从不调用工具description写得太模糊模型不知道什么时候用写明触发场景和典型问题示例模型生成了错误参数ToolParam缺少描述模型猜错参数语义给每个参数补充业务含义工具调用后 Agent 报错方法返回类型不是字符串或可序列化对象统一返回 String 或简单 JSON多个工具名相近导致选择混乱工具职责重叠、命名不清晰减少工具数量每个工具职责单一Bean 方法没生效工具类没注册为 Spring Bean检查Component或手动装配对初学者来说最实用的调试手段是打开日志观察模型到底有没有输出工具调用指令后面第 6 节会专门讲日志配置。5. 多轮会话与记忆管理5.1 大模型天然无状态很多人在跑通单轮对话后会自然地问为什么第二轮请求时它不记得我第一轮说了什么原因是协议层面大模型就是无状态的。每一次 API 调用都只接收你当前发送的消息列表不会保存任何“上次会话”。所谓“记忆”本质上是开发者把历史消息手动带回给模型每轮请求都把之前的用户消息和模型回复拼接到上下文里模型看起来像是记得实际只是再次“读到了”之前的记录。5.2 用 ChatMemory 保存并携带历史消息Spring AI 提供了ChatMemory抽象MessageWindowChatMemory是其中最常用的实现它把消息保存在内存中并按最近消息数量限制窗口大小ChatMemory chatMemory MessageWindowChatMemory.builder() .maxMessages(20) .build(); ChatClient chatClient ChatClient.builder(chatModel) .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory)) .build();MessageChatMemoryAdvisor的作用是在每次请求前自动从ChatMemory中读取历史消息追加到当前 Prompt再在请求结束后把新的对话写入记忆。对多用户场景可以按会话 ID 隔离记忆避免不同用户互相污染上下文。需要明确的是上面展示的是 ChatClient 维度的记忆接入方式。如果使用 ReActAgent还要额外把记忆组件接入执行器或者在每次调用时把历史消息作为 Prompt 的一部分传入。不同版本接入方式不一致建议以当前版本的单元测试用例为参考。5.3 记忆策略如何选型记忆不是越多越好不同策略的取舍差异很大记忆策略实现方式优点缺点适用场景无记忆不保存历史实现简单、成本低无法多轮关联一次性问答滑动窗口记忆只保留最近 N 条消息实现简单、实时性好窗口外信息丢失客服对话、多数业务 Agent摘要记忆定期把旧消息总结成摘要保留长程信息摘要损失细节长时间多轮任务向量库长期记忆历史消息向量化存储并按需检索理论上无限扩展工程复杂度高知识库型 Agent业务型 Agent 的起步建议是直接使用滑动窗口窗口大小可以设置为 10 到 20 条消息。既能支持多轮连续对话又不会让上下文物极速膨胀。5.4 上下文窗口与成本控制每轮请求都会把历史消息重新发给模型因此 token 消耗随轮数线性增长。这里有几个实际建议不要无脑调大窗口20 条消息已经能覆盖大多数客服和查询类场景。对工具返回结果做截断超长结果只传关键摘要避免占据大量 token。在日志中记录每次请求的 token 用量用ChatResponse的元数据读取。低成本简单任务切换到 qwen-turbo复杂推理再使用 qwen-plus 或 qwen-max。上下文超长是最常见的 Agent 生产事故之一现象是请求报错或模型开始“忘记”上下文。它的根因不是模型能力变差而是开发者没有控制窗口大小。6. 运行验证、日志与高频问题排查6.1 Agent 功能测试不能只看“能返回”Agent 项目验证比普通接口复杂因为同样的输入可能产生不同的内部流程。推荐按下面三类场景设计测试用例测试场景请求示例预期表现普通问答“什么是 Java 反射”直接回答不调用任何工具工具调用“帮我查订单 A123456 的物流”模型调用 queryOrderStatus 并返回真实状态多轮记忆先问“我的订单是 A123456”再问“它到哪了”第二问能关联第一轮的订单号验证工具是否真的被调用不能只看最终文本要看日志中是否出现工具调用记录和工具返回结果。6.2 打开 Agent 决策日志在application.yml中增加日志级别logging: level: org.springframework.ai: DEBUG com.alibaba.cloud.ai: DEBUG开启后日志会显示类似下面的关键节点[Agent] user input: 帮我查订单 A123456 的物流 [Agent] calling tool: queryOrderStatus, args: {orderId:A123456} [Agent] tool result: 订单 A123456 已发货承运商顺丰 [Agent] final answer: 您的订单 A123456 已发货承运商顺丰预计 05-20 前送达。看到calling tool和tool result两行才能确认工具调用链路真的走通了。如果只有模型回答、没有工具节点问题大概率出在工具注册或描述上。6.3 高频问题排查表问题现象常见原因检查方式处理建议启动报java.lang.NoClassDefFoundError: java/applet/Applet依赖或代码基于旧 JDK 编译与当前 JDK 不兼容执行java -version用mvn dependency:tree查可疑依赖统一使用 JDK 17排除旧版本依赖Lombok 报 “you arent using a compiler supported by lombok”JDK 版本高于 Lombok 支持范围查看 Lombok 版本和 JDK 版本升级 Lombok 到 1.18.30或退回 JDK 17接口返回 401 UnauthorizedAPI Key 缺失或错误检查环境变量DASHSCOPE_API_KEY重新设置 Key 并重启应用接口返回 404 或超时base-url 配置错误或网络不通检查配置文件中的 endpoint确认使用官方 DashScope endpoint模型不调用工具工具未注册或描述不清晰打开 DEBUG 日志看工具列表检查 Tool 方法、Bean 注册、description工具参数生成错误ToolParam 缺少描述打印模型生成的 tool 调用 JSON补全参数业务描述上下文超长报错消息历史过多超出模型窗口统计每轮 token 用量减小记忆窗口压缩工具返回结果请求频繁失败或 429触发供应商限流查看响应状态码和限流错误增加重试退避和熔断降低并发6.4 排查顺序建议遇到 Agent 项目问题按下面的优先级排查能少走弯路输入是否正确报文格式、参数名、URL。API Key 是否配置环境变量和配置文件的加载。版本是否匹配JDK、Spring Boot、Lombok、Spring AI Alibaba。配置是否生效模型名、base-url、日志级别。依赖是否完整mvn dependency:tree检查是否有版本冲突。日志具体报错以第一条明确异常为准不要看后续连带错误。工具是否注册确认Tool方法被 Spring 容器管理。这套顺序的核心逻辑是先排除外部环境再检查框架配置最后才怀疑业务代码。7. 生产环境落地与最佳实践7.1 配置、密钥与版本管理Demo 阶段可以把 API Key 写在环境变量里生产环境建议进一步提升API Key 放入密钥管理服务应用启动时动态拉取不要出现在环境变量或配置仓库里。固定依赖版本Spring AI Alibaba 迭代快生产环境不要用 SNAPSHOT 版本。配置外置到 Nacos 或配置中心模型名、提示词、工具开关都可以动态调整而不重启。每次升级框架版本先跑一遍完整的工具调用测试用例确认函数调用行为没有变化。7.2 可观测性、限流与成本控制Agent 比普通接口多了一层维度除了常规日志还要关注大模型调用本身记录每次请求的模型名、token 输入数、输出数、耗时和费用。对工具调用耗时单独埋点避免某个慢数据库查询拖垮整体响应。对模型调用做超时控制和重试退避超时时间比普通接口要放宽但必须有上限。在接入层做并发限流防止用户把 Agent 接口当作无限免费的文本生成器。设置成本告警当单日 token 费用超过阈值时通知负责人。生产环境最怕的不是模型回答错误而是错误发生后没有日志、没有指标、无法定位是模型问题、工具问题还是输入问题。7.3 工具权限与人工确认工具是 Agent 的能力边界也是安全边界。注册工具时遵循最小权限原则只暴露当前业务真正需要的方法不要顺手把ProductService整个类注册进去。工具方法内部必须做参数校验和权限校验模型也会生成错误参数。删除、支付、发送通知等高风险操作工具内部增加人工确认机制比如返回待审批状态而不是直接执行。对模型输出做基本合规检查不要在业务正文里展示未经处理的敏感信息。7.4 发布前检查清单新 Agent 服务上线前逐项确认API Key 已从代码仓库移除由密钥服务注入。固定了 Spring AI Alibaba 和 Spring Boot 版本号。工具类清单已确认没有多余的高危方法暴露给模型。每个工具都补充了测试用例包含成功和失败分支。记忆窗口已设置上限并验证过窗口超限时的行为。日志中能观察到工具调用和 token 用量。已配置超时、重试、限流和熔断。已准备回滚方案框架版本升级失败时能快速还原。已建立成本监控和告警。已用真实生产数据做过一轮回归测试。7.5 扩展方向与实践建议这篇文章完成的是单个 Agent 的最小闭环后续可以沿着几个方向继续深入接入更多业务工具把查询、计算、消息发送都变成 Agent 的可调用能力。加入 RAG 检索让 Agent 基于企业知识库回答而不是只依赖模型内部知识。探索多 Agent 协作把一个复杂任务拆分给多个专职 Agent 处理。学习图编排和图流引擎把 Agent 执行过程固化为可编排的工作流。建立 Agent 评测集用固定问题集回归测试每次升级后的目标达成率。对刚入门的开发者建议先从一个小场景做透一个查订单的 Agent、一个查天气的 Agent、一个能写周报的 Agent。关键不在于功能多复杂而在于完整走通模型接入、工具注册、多轮记忆、日志验证这套链路。把这条路走通再去看多 Agent、RAG、流程编排这些上层能力时理解成本会低很多。