用 Spring AI 搭建你的第一个 Agent:从零开始的详细实战指南
1. 什么是 Agent?为什么需要 Spring AI?
在深入了解代码之前,我们先弄清楚一个概念:Agent 到底是什么?
简单来说,Agent 是一种能够自主调用工具、多步推理并完成复杂任务的 AI 应用形态。它和普通的“一问一答”聊天机器人最大的区别在于:
- 普通聊天机器人:你问它答,只依赖模型自身知识;
- Agent:模型可以调用外部工具(如搜索网页、查询数据库、调用本地函数),并根据工具返回的结果继续推理,直到完成任务。
Spring AI 是 Spring 官方推出的 AI 应用开发框架。它的核心价值在于:
- 统一的 AI 接口抽象:一套 API 适配 OpenAI、Ollama、通义千问、智谱等多种大模型;
- 原生支持 Agent 与 Tool Calling:把 Spring 的 Bean 轻松变成模型可调用的工具;
- 融入 Spring 生态:自动配置、依赖注入、可观测性等都和 Spring Boot 无缝集成。
下面我们就从零开始,搭建一个真正能调用工具、能“干活”的 Spring AI Agent。
2. 环境准备与项目初始化
在开始编码前,请准备好以下环境:
| 环境 | 版本要求 | 说明 |
|---|---|---|
| JDK | 17 及以上 | Spring Boot 3.x 要求 JDK 17+ |
| Maven | 3.6+ | 用于构建项目 |
| IDE | 任意 | 推荐 IntelliJ IDEA |
| 大模型 API Key | OpenAI / 通义千问 / Ollama 等 | 本教程以 OpenAI 兼容接口为例 |
2.1 创建 Spring Boot 项目
可以通过 Spring Initializr 创建项目,也可以使用 IDEA 新建 Spring Boot 项目。这里推荐手动创建一个最简 Maven 项目,便于你理解每一处配置。
首先创建 pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-ai-agent-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-ai-agent-demo</name>
<description>我的第一个 Spring AI Agent</description>
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0-M3</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI OpenAI 支持,如果你用其他模型请选择对应 starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
说明:Spring AI 目前仍在快速迭代中,
1.0.0-M3是里程碑版本。实际使用时请根据官方文档选择最新稳定版本。如果你使用的是 Ollama 本地模型,只需把spring-ai-openai-spring-boot-starter换成spring-ai-ollama-spring-boot-starter。
3. 添加配置并连接大模型
创建主启动类:
package com.example.agentdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AgentDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AgentDemoApplication.class, args);
}
}
随后在 src/main/resources/application.yml 中配置模型连接信息:
spring:
application:
name: spring-ai-agent-demo
ai:
openai:
api-key: ${OPENAI_API_KEY}
base-url: https://api.openai.com
chat:
options:
model: gpt-4o-mini
temperature: 0.7
如果你使用的是国内兼容 OpenAI 协议的模型服务,只需要修改 base-url 和 api-key 即可,例如:
spring:
ai:
openai:
api-key: ${DASHSCOPE_API_KEY}
base-url: https://dashscope.aliyuncs.com/compatible-mode
chat:
options:
model: qwen-plus
这样配置完成后,Spring AI 就会自动创建 ChatModel Bean,供后续使用。
4. 定义你的第一个工具(Tool)
Agent 的能力来自工具。在 Spring AI 中,把一个普通 Java 方法变成模型可调用的工具非常简单:只需要在方法上添加 @Tool 注解。
下面我们定义两个实用工具:查询天气 和 数学计算。
4.1 创建天气服务工具
package com.example.agentdemo.tool;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;
@Service
public class WeatherTool {
@Tool(description = "根据城市名称查询该城市当前的天气情况")
public String getWeather(
@ToolParam(description = "要查询天气的城市名称,例如:北京") String city) {
// 这里模拟查询天气,实际项目中可以替换为调用第三方天气 API
return city + "当前天气晴朗,气温 22 摄氏度,空气质量良好。";
}
@Tool(description = "计算两个浮点数的加减乘除结果")
public double calculate(
@ToolParam(description = "第一个数字") double a,
@ToolParam(description = "第二个数字") double b,
@ToolParam(description = "运算类型:add 表示加,subtract 表示减," +
"multiply 表示乘,divide 表示除") String operation) {
return switch (operation) {
case "add" -> a + b;
case "subtract" -> a - b;
case "multiply" -> a * b;
case "divide" -> {
if (b == 0) {
throw new IllegalArgumentException("除数不能为 0");
}
yield a / b;
}
default -> throw new IllegalArgumentException("不支持的运算类型:" + operation);
};
}
}
要点解释:
@Tool(description = "..."):这个描述非常重要,模型会根据描述判断“什么时候该调用这个工具”。描述越清晰,调用越准确;@ToolParam(description = "..."):参数描述同样关键,它帮助模型正确填充参数;- 方法本身可以是任意业务逻辑,Agent 只关心方法的签名和返回值。
5. 创建 Agent 并注入工具
接下来创建 Agent。Spring AI 提供了 ChatClient 作为统一入口,我们可以通过 Builder 模式把工具注册进去。
5.1 编写 Agent 服务类
package com.example.agentdemo.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.stereotype.Service;
@Service
public class AgentService {
private final ChatClient chatClient;
public AgentService(ChatModel chatModel, WeatherTool weatherTool) {
this.chatClient = ChatClient.builder(chatModel)
// 注册工具:这里可以连续注册多个工具
.defaultTools(weatherTool)
// 添加日志 Advisor,便于观察 Agent 的调用链路
.defaultAdvisors(new SimpleLoggerAdvisor())
.build();
}
public String chat(String userMessage) {
return this.chatClient.prompt()
.system("你是一个乐于助人的智能助手。遇到需要查询天气或计算的任务时," +
"请优先使用提供的工具,并根据工具返回结果如实回答。")
.user(userMessage)
.call()
.content();
}
}
5.2 核心代码解析
ChatClient.builder(chatModel):以注入的ChatModel为基础构建客户端;.defaultTools(weatherTool):把包含@Tool方法的 Bean 注册为 Agent 可用工具。Spring AI 会自动扫描被@Tool注解的方法并生成模型可识别的工具描述;.defaultAdvisors(new SimpleLoggerAdvisor()):添加简易日志,方便在控制台观察模型的每次工具调用;.call().content():发送请求并返回最终文本结果。
6. 添加 Controller 并启动调试
为了让 Agent 可以被访问,我们添加一个简单的 REST 接口:
package com.example.agentdemo.controller;
import com.example.agentdemo.service.AgentService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AgentController {
private final AgentService agentService;
public AgentController(AgentService agentService) {
this.agentService = agentService;
}
@GetMapping("/chat")
public String chat(@RequestParam String message) {
return agentService.chat(message);
}
}
启动项目后,打开浏览器或使用 curl 测试:
curl "http://localhost:8080/chat?message=北京现在天气怎么样?"
控制台会输出类似以下的工具调用日志:
>>> system: 你是一个乐于助人的智能助手...
>>> user: 北京现在天气怎么样?
>>> function: getWeather(city=北京)
>>> function result: 北京当前天气晴朗,气温 22 摄氏度...
>>> assistant: 根据查询结果,北京当前天气晴朗,气温 22 摄氏度,空气质量良好。
再测试一个需要多步推理的例子:
curl "http://localhost:8080/chat?message=如果明天北京气温下降 10 度,大概是多少度?"
这个请求会先触发天气查询工具,再触发数学计算工具,体现 Agent 的多步工具调用能力。
7. 进阶:让 Agent 具备记忆能力
默认情况下,Agent 是不带记忆的,每次请求都是独立会话。我们可以通过 MessageChatMemoryAdvisor 轻松加上对话记忆。
7.1 注入记忆组件
首先确保项目中已有内存聊天记忆依赖(Spring AI 自带,无需额外依赖),然后修改 AgentService:
package com.example.agentdemo.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.stereotype.Service;
@Service
public class AgentService {
private final ChatClient chatClient;
public AgentService(ChatModel chatModel, WeatherTool weatherTool) {
this.chatClient = ChatClient.builder(chatModel)
.defaultTools(weatherTool)
.defaultAdvisors(
// 关键:加上内存记忆 Advisor
new MessageChatMemoryAdvisor(new InMemoryChatMemory()),
new SimpleLoggerAdvisor()
)
.build();
}
public String chat(String conversationId, String userMessage) {
return this.chatClient.prompt()
.system("你是一个乐于助人的智能助手。遇到需要查询天气或计算的任务时," +
"请优先使用提供的工具,并根据工具返回结果如实回答。")
.user(userMessage)
// 使用会话 ID 区分不同用户/会话
.advisors(a -> a.param("chat_memory_conversation_id", conversationId))
.call()
.content();
}
}
同时修改 Controller 接收会话 ID:
@GetMapping("/chat")
public String chat(@RequestParam String message,
@RequestParam(defaultValue = "default") String sessionId) {
return agentService.chat(sessionId, message);
}
现在 Agent 就能记住同一会话中的上下文了。例如:
# 第一轮
curl "http://localhost:8080/chat?sessionId=user001&message=我叫小明,帮我查一下北京的天气"
# 第二轮:模型会记得你叫小明
curl "http://localhost:8080/chat?sessionId=user001&message=我刚刚问的是哪个城市?"
注意:
InMemoryChatMemory只适合开发和测试环境。生产环境建议使用CassandraChatMemoryRepository、JdbcChatMemoryRepository或 Redis 等方式持久化记忆。
8. 常见问题与排错
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
启动报 api-key 相关错误 | 环境变量未设置 | 在 IDEA 运行配置或终端 export OPENAI_API_KEY |
| 模型不调用工具 | 工具描述不清晰 | 优化 @Tool 和 @ToolParam 的 description |
| 工具返回后模型“答非所问” | 系统提示词不够明确 | 在 system 提示中强调“基于工具结果回答” |
| 连接超时 | 网络问题或 base-url 不正确 | 检查代理和 base-url 配置 |
| JDK 版本报错 | 使用了 JDK 8 或 11 | 升级到 JDK 17+ |
9. 总结与下一步
通过这篇文章,你应该已经完成了一个最小但完整的 Spring AI Agent:
- 创建了 Spring Boot 项目并引入 Spring AI 依赖;
- 配置了大模型连接信息;
- 用
@Tool注解定义了天气查询和数学计算工具; - 通过
ChatClient构建 Agent 并注册工具; - 添加了 REST 接口并成功验证多步工具调用;
- 使用
MessageChatMemoryAdvisor为 Agent 添加了会话记忆。
下一步你可以尝试:
- 接入真实业务工具,例如订单查询、数据库操作、文件处理;
- 使用
QuestionAnswerAdvisor结合向量数据库实现 RAG Agent; - 通过 Spring AI 的
ToolCallingManager管理更复杂的工具调用场景; - 部署到生产环境并配置持久化会话记忆与可观测性。
Spring AI 让 Java 开发者构建 Agent 的门槛大大降低。希望这篇文章能帮你迈出第一步,祝你玩得开心!
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)