Spring AI Alibaba Agent Framework 从入门到实战
本文基于 Spring AI Alibaba 1.1.2.0,从零开始搭建一个基于 ReAct 模式的智能 Agent,涵盖核心概念、API 详解、完整代码示例及常见问题排查。
一、Agent Framework 是什么?
Spring AI Alibaba Agent Framework 是在 Graph 引擎之上构建的高级抽象,它封装了 ReAct(Reasoning + Acting)循环,让开发者能够快速创建具有推理和工具调用能力的智能 Agent。
1.1 ReAct 模式
ReAct 是一种将推理和行动相结合的 Agent 范式:
| 阶段 | 说明 |
|---|---|
| 思考(Reasoning) | Agent 分析当前情况,决定下一步做什么 |
| 行动(Acting) | 执行工具调用或生成最终答案 |
| 观察(Observation) | 接收工具执行的结果 |
| 迭代 | 基于观察结果继续思考和行动,直到完成任务 |
这个循环使 Agent 能够:
- 将复杂问题分解为多个步骤
- 动态调整策略基于中间结果
- 处理需要多次工具调用的任务
- 在不确定的环境中做出决策
1.2 ReactAgent 工作原理
ReactAgent 基于 Graph 运行时构建,在以下节点间移动:
- Model Node:调用 LLM 进行推理和决策
- Tool Node:执行工具调用
- Hook Nodes:在关键位置插入自定义逻辑
二、核心 API 详解
2.1 Model(模型配置)
Model 是 Agent 的推理引擎。使用 ChatModel 实例配置。
java
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.defaultOptions(DashScopeChatOptions.builder()
.withModel("deepseek-v4-flash")
.withTemperature(0.7)
.withMaxToken(2000)
.build())
.build();
2.2 Tools(工具定义)
工具赋予 Agent 执行操作的能力。使用 @Tool 注解定义。
java
@Component
public class AgentTools {
@Tool(description = "获取指定城市的当前天气信息")
public String getWeather(@ToolParam(description = "城市名称") String city) {
// 实现逻辑
return "北京:晴,25°C";
}
}
2.3 工具注册方式
在 ReactAgent.builder() 中,正确注册工具的方式是使用 .tools(ToolCallback...):
java
ToolCallback[] toolCallbacks = MethodToolCallbackProvider.builder()
.toolObjects(agentTools)
.build()
.getToolCallbacks();
ReactAgent agent = ReactAgent.builder()
.name("assistant_agent")
.model(chatModel)
.tools(toolCallbacks) // 传入 ToolCallback 数组
.build();
2.4 System Prompt
System Prompt 塑造 Agent 的行为方式。
java
ReactAgent agent = ReactAgent.builder()
.name("my_agent")
.model(chatModel)
.systemPrompt("""
你是一个智能助手,可以帮助用户完成各种任务。
你有以下能力:
1. 查询城市天气
2. 获取当前时间
3. 进行数学计算
请根据用户的问题,选择合适的工具来解决问题。
""")
.build();
2.5 调用 Agent
java
// 基础调用
AssistantMessage response = agent.call("北京今天天气怎么样?");
System.out.println(response.getText());
2.6 Memory(记忆)
使用 MemorySaver 维护对话上下文。
java
import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver;
import com.alibaba.cloud.ai.graph.RunnableConfig;
ReactAgent agent = ReactAgent.builder()
.name("chat_agent")
.model(chatModel)
.saver(new MemorySaver())
.build();
// 使用 threadId 维护对话上下文
RunnableConfig config = RunnableConfig.builder()
.threadId("user_123")
.build();
agent.call("我叫张三", config);
agent.call("我叫什么名字?", config); // 输出: "你叫张三"
2.7 迭代控制
使用 ModelCallLimitHook 限制 Agent 的迭代次数,防止无限循环。
java
import com.alibaba.cloud.ai.graph.agent.hook.modelcalllimit.ModelCallLimitHook;
ReactAgent agent = ReactAgent.builder()
.name("my_agent")
.model(chatModel)
.hooks(ModelCallLimitHook.builder().runLimit(5).build())
.build();
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
三、环境搭建
3.1 依赖配置(pom.xml)
xml
<properties>
<java.version>17</java.version>
<spring-ai-alibaba.version>1.1.2.0</spring-ai-alibaba.version>
<jackson.version>2.16.2</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Agent Framework 核心 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-agent-framework</artifactId>
<version>${spring-ai-alibaba.version}</version>
</dependency>
<!-- DashScope 模型接入 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
<version>${spring-ai-alibaba.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
3.2 配置文件(application.yml)
yaml
server:
port: 885
spring:
ai:
dashscope:
api-key: ${DASHSCOPE_API_KEY} # 从环境变量读取
chat:
options:
model: deepseek-v4-flash # 或 qwen-max
logging:
level:
com.alibaba.cloud.ai: debug
四、完整代码示例
4.1 工具类定义
java
package com.badao.ai.tools;
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;
import java.util.HashMap;
import java.util.Map;
@Component
public class AgentTools {
@Tool(description = "获取指定城市的当前天气信息")
public String getWeather(@ToolParam(description = "城市名称,如:北京、上海") String city) {
Map<String, String> weatherData = new HashMap<>();
weatherData.put("北京", "晴,25°C,湿度45%");
weatherData.put("上海", "多云,28°C,湿度60%");
weatherData.put("杭州", "小雨,22°C,湿度75%");
weatherData.put("深圳", "晴,30°C,湿度50%");
return weatherData.getOrDefault(city, city + "的天气信息暂不可用");
}
@Tool(description = "获取当前日期和时间")
public String getCurrentTime() {
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
@Tool(description = "计算两个数字的和")
public double add(@ToolParam(description = "第一个数字") double a,
@ToolParam(description = "第二个数字") double b) {
return a + b;
}
}
4.2 Agent 配置类
java
package com.badao.ai.config;
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
import com.alibaba.cloud.ai.graph.agent.hook.modelcalllimit.ModelCallLimitHook;
import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver;
import com.badao.ai.tools.AgentTools;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AgentConfig {
@Value("${spring.ai.dashscope.api-key}")
private String apiKey;
@Bean
public ChatModel chatModel() {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(apiKey)
.build();
return DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.defaultOptions(DashScopeChatOptions.builder()
.withModel("deepseek-v4-flash")
.withTemperature(0.7)
.withMaxToken(2000)
.build())
.build();
}
@Bean
public ReactAgent assistantAgent(ChatModel chatModel, AgentTools agentTools) {
// 将 @Tool 注解的对象转换为 ToolCallback 数组
ToolCallback[] toolCallbacks = MethodToolCallbackProvider.builder()
.toolObjects(agentTools)
.build()
.getToolCallbacks();
return ReactAgent.builder()
.name("assistant_agent")
.model(chatModel)
.tools(toolCallbacks) // 传入 ToolCallback 数组
.systemPrompt("""
你是一个智能助手,可以帮助用户完成各种任务。
你有以下能力:
1. 查询城市天气
2. 获取当前时间
3. 进行数学计算
请根据用户的问题,选择合适的工具来解决问题。
""")
.hooks(ModelCallLimitHook.builder().runLimit(5).build())
.saver(new MemorySaver())
.build();
}
}
4.3 Service 层
java
package com.badao.ai.service;
import com.alibaba.cloud.ai.graph.RunnableConfig;
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
import com.alibaba.cloud.ai.graph.exception.GraphRunnerException;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class AgentService {
private final ReactAgent agent;
public AgentService(ReactAgent agent) {
this.agent = agent;
}
public String chat(String userMessage) throws GraphRunnerException {
AssistantMessage response = agent.call(userMessage);
return response.getText();
}
public String chatWithMemory(String userMessage, String sessionId) throws GraphRunnerException {
RunnableConfig config = RunnableConfig.builder()
.threadId(sessionId)
.build();
AssistantMessage response = agent.call(userMessage, config);
return response.getText();
}
}
4.4 Controller 层
java
package com.badao.ai.controller;
import com.alibaba.cloud.ai.graph.exception.GraphRunnerException;
import com.badao.ai.service.AgentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.UUID;
@RestController
@RequestMapping("/api/agent")
public class AgentController {
private static final Logger log = LoggerFactory.getLogger(AgentController.class);
private final AgentService agentService;
public AgentController(AgentService agentService) {
this.agentService = agentService;
}
@PostMapping("/chat")
public Map<String, Object> chat(@RequestBody Map<String, String> request) {
String message = request.get("message");
try {
String response = agentService.chat(message);
return Map.of("success", true, "response", response);
} catch (GraphRunnerException e) {
log.error("Agent 执行失败", e);
return Map.of("success", false, "error", "Agent 执行失败: " + e.getMessage());
}
}
@PostMapping("/chat/session")
public Map<String, Object> chatWithSession(@RequestBody Map<String, String> request) {
String message = request.get("message");
String sessionId = request.getOrDefault("sessionId", UUID.randomUUID().toString());
try {
String response = agentService.chatWithMemory(message, sessionId);
return Map.of("success", true, "sessionId", sessionId, "response", response);
} catch (GraphRunnerException e) {
log.error("Agent 执行失败", e);
return Map.of("success", false, "error", "Agent 执行失败: " + e.getMessage());
}
}
}
4.5 启动类
java
package com.badao.ai;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringAiDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAiDemoApplication.class, args);
}
}
五、测试与验证
5.1 测试命令
bash
# 基础对话
curl -X POST http://localhost:885/api/agent/chat \
-H "Content-Type: application/json" \
-d '{"message": "北京今天天气怎么样?"}'
# 带会话记忆的对话
curl -X POST http://localhost:885/api/agent/chat/session \
-H "Content-Type: application/json" \
-d '{"message": "我叫张三", "sessionId": "test-001"}'
curl -X POST http://localhost:885/api/agent/chat/session \
-H "Content-Type: application/json" \
-d '{"message": "我叫什么名字?", "sessionId": "test-001"}'
5.2 预期输出
json
{
"success": true,
"response": "北京今天的天气是晴,25°C,湿度45%。"
}

测试记忆功能:

六、常见问题与解决方案
6.1 GraphRunnerException 未处理
错误 :Unhandled exception: com.alibaba.cloud.ai.graph.exception.GraphRunnerException
原因 :agent.call() 方法声明抛出受检异常,调用方必须处理。
解决方案:
在 Service 方法上声明抛出,由 Controller 统一捕获处理:
java
public String chat(String userMessage) throws GraphRunnerException {
AssistantMessage response = agent.call(userMessage);
return response.getText();
}
或在 Service 内部捕获并转换为运行时异常:
java
public String chat(String userMessage) {
try {
AssistantMessage response = agent.call(userMessage);
return response.getText();
} catch (GraphRunnerException e) {
throw new RuntimeException("Agent 执行失败", e);
}
}
6.2 工具注册方法不正确
错误 :Cannot resolve method 'tools(AgentTools)' 或 Cannot resolve method 'methodTools(AgentTools)'
原因 :ReactAgent.builder() 的正确工具注册方式是 .tools(ToolCallback...)。
解决方案:
java
// 使用 MethodToolCallbackProvider 转换
ToolCallback[] toolCallbacks = MethodToolCallbackProvider.builder()
.toolObjects(agentTools)
.build()
.getToolCallbacks();
return ReactAgent.builder()
.name("assistant_agent")
.model(chatModel)
.tools(toolCallbacks) // 传入 ToolCallback 数组
.build();
6.3 Agent 无限循环
问题:Agent 不断调用工具而不产生最终答案,消耗大量 Token。
解决方案 :使用 ModelCallLimitHook 限制迭代次数。
java
ReactAgent agent = ReactAgent.builder()
.name("my_agent")
.model(chatModel)
.hooks(ModelCallLimitHook.builder().runLimit(5).build())
.build();
6.4 工具调用失败
问题:工具执行时抛出异常,导致 Agent 中断。
解决方案:在工具方法中添加 try-catch,返回友好的错误信息。
java
@Tool(description = "获取天气")
public String getWeather(String city) {
try {
// 调用外部 API
return weatherApi.get(city);
} catch (Exception e) {
return "获取天气信息失败,请稍后重试。";
}
}
6.5 多轮对话上下文丢失
问题:后续请求无法记住之前的对话内容。
解决方案 :使用 MemorySaver 和 threadId。
java
// 创建 Agent 时配置 MemorySaver
.saver(new MemorySaver())
// 调用时传入 threadId
RunnableConfig config = RunnableConfig.builder()
.threadId("user_123")
.build();
agent.call(userMessage, config);
6.6 导入包路径错误
常见包路径对照表:
| 类 | 正确导入路径 |
|---|---|
ReactAgent |
com.alibaba.cloud.ai.graph.agent.ReactAgent |
MemorySaver |
com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver |
RunnableConfig |
com.alibaba.cloud.ai.graph.RunnableConfig |
GraphRunnerException |
com.alibaba.cloud.ai.graph.exception.GraphRunnerException |
ModelCallLimitHook |
com.alibaba.cloud.ai.graph.agent.hook.modelcalllimit.ModelCallLimitHook |
ToolCallback |
org.springframework.ai.tool.ToolCallback |
MethodToolCallbackProvider |
org.springframework.ai.tool.method.MethodToolCallbackProvider |
七、总结
通过本文,你完整学习了 Spring AI Alibaba Agent Framework 的:
| 知识点 | 核心内容 |
|---|---|
| ReAct 模式 | Reasoning + Acting 循环 |
| ReactAgent | 基于 Graph 的 Agent 实现 |
| Model 配置 | ChatModel + ChatOptions |
| Tool 定义 | @Tool 注解声明式定义 |
| Tool 注册 | MethodToolCallbackProvider → ToolCallback\[\] |
| System Prompt | 塑造 Agent 行为 |
| Memory | MemorySaver + threadId |
| 迭代控制 | ModelCallLimitHook |
| 异常处理 | GraphRunnerException 统一处理 |
你可以基于这个完整的示例,进一步扩展 Agent 的能力,例如接入更多工具、实现多 Agent 协作、或集成 RAG 等高级功能。
📎 参考资源:Spring AI Alibaba GitHub | 官方文档