✅Alibaba-React Agent 核心组件
基础组件 Model Model 就是大模型,作为 Agent 的大脑,负责推理、生成文本、决定下一步行动 (是否调用工具/输出答案)。
Spring-AI-Alibaba 的底层核心实现就是基于 Spring AI Apache,可以理解为Alibaba是增强版的 Spring AI。和之前的做法一样,你只需实现了 ChatModel 接口的类来作为模型即可。同时也可以通过配置 ChatOptions 来控制 temperature、maxTokens、topP 等参数。
使用示例 :
1 2 3 DashScopeApi dashScopeApi = DashScopeApi.builder() .apiKey("sk-XXXXXXXXXXXXXXXXXXXX" ) .build();ReactAgent agent = ReactAgent.builder() .name("my_agent" ) .model(chatModel) .build();
工具就是给 Agent “行动 (Acting)” 的能力,即当模型决定它需要做某些外部操作 (比如搜索、调用 API、数据库操作、计算等) 时,工具能实际执行这些操作。
ReactAgent 同样支持多个工具,tools 参数传入多个即可,Agent 会根据 LLM 输出决定调用哪个工具。
使用示例 :
1 2 3 ReactAgent agent = ReactAgent.builder() .name("search_agent" ) .model(chatModel) .tools(searchTool) .systemPrompt("你是一个有外部搜索能力的助手。" ) .build();AssistantMessage resp = agent.call("帮我查一下今天南京的天气" ); System.out.println(resp.getText());
ToolContext的基本用法 在Spring AI Alibaba中,ToolContext 是工具执行时的数据中心,统一管理参数、状态、memory、config 并封装返回值,是 ReActAgent 工具链的核心,这样工具能根据当前对话 / 状态做出合理操作。
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package cn.hollis.llm.mentor.tools;import com.alibaba.cloud.ai.graph.OverAllState;import com.alibaba.cloud.ai.graph.RunnableConfig;import org.springframework.ai.chat.messages.Message;import org.springframework.ai.chat.model.ToolContext;import java.util.List;import java.util.Map;import java.util.Optional;public class WeatherQueryTool implements java .util.function.BiFunction<String, ToolContext, String> { @Override public String apply (String city, ToolContext toolContext) { long userCnt = messages.stream().filter(m -> m.getMessageType().getValue().equals("user" )).count(); long aiCnt = messages.stream().filter(m -> m.getMessageType().getValue().equals("assistant" )).count(); long toolCnt = messages.stream().filter(m -> m.getMessageType().getValue().equals("tool" )).count(); ---- 调试信息(ToolContext)---- 历史消息数:user=%d, assistant=%d, tool=%d """, city, weather, userCnt, aiCnt, toolCnt ); } }
System Prompt 这个前面的课程中已经详细的介绍过了,这边简单讲下,就是 ReactAgent 提供了一个入口参数,可以方便我们自定义系统提示词,Agent 的身份 / 行为规范 /风格 /角色设定。
支持2种配置方式:
**systemPrompt(“…”)**:简单字符串提示词。
**instruction(“…多行指令…”)**:适合更复杂或结构化的提示 (可以使用我们前面课程介绍的提示词框架来编写)。
使用示例 :
1 2 3 String instruction = """ 你是一个经验丰富的软件架构师。 请在回答中: 1. 先理解用户需求 2. 分析可能的技术方案 3. 提供清晰建议和理由 4. 如果信息不够,主动询问 用专业且友好的语气。""" ;ReactAgent agent = ReactAgent.builder() .name("architect_agent" ) .model(chatModel) AssistantMessage resp = agent.call("我想搭一个微服务系统,用 Java + Spring,怎么设计?" );System.out.println(resp.getText());
结构化输出 ReactAgent 同样也支持通过Structured Output,把文本进行结构化输出,要求模型严格按结构输出 JSON。如果是集合类型,需要自己再次封装一层 record。
使用示例:
1 2 3 4 public static record Book (String name,String description) {}public record BookListResult (List<Book> books) {}ReactAgent agent = ReactAgent.builder() .name("poem_agent" ) .model(chatModel) .outputType(BookListResult.class) .build();String res = agent.call("推荐5本java相关的书籍" ).getText();System.out.println(res);
Memory ReactAgent 也支持会话记忆能力,支持将对话状态维护在 Agent 内部状态中,并可以持久化到存储层。开启记忆后,每次 Agent 调用时都会读取和写入这些状态,从而让多轮交互更连贯。
短期记忆是 会话级别的历史追踪 ,适合保存当前对话的上下文;在生产环境中,你也可以结合像 RedisSaver、MongoSaver 等持久化存储,实现长期记忆。
使用示例:
1 2 3 4 RunnableConfig config = RunnableConfig.builder() .threadId("user_123" ) .build(); agent.call("你好!我叫 bigchui。" , config); AssistantMessage resp = agent.call("我叫什么名字?" , config); System.out.println(resp.getText());
Hooks Hooks 就是 ReactAgent 执行过程中的“生命周期钩子”。 当 ReactAgent 从接收输入、调用 LLM、执行工具,到最终返回结果时,框架在这些关键阶段预留了 Hooks,你可以在不改变 Prompt、不干扰推理逻辑 的前提下,插入自己的自定义代码逻辑。
在实践中,Hooks 主要解决的是可观测性与控制问题。 日志记录、执行链路追踪、上下文增强、结果二次加工、审计与限流,这些都不应该写进 Prompt,也不适合做成 Tool,而是天然属于 Hooks 的职责。可以理解为:Tool 决定 Agent 能做什么,Hooks 决定你如何在每一步监督它怎么做。
Hook 执行位置 :
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package cn.hollis.llm.menter.hooks;import com.alibaba.cloud.ai.graph.OverAllState;import com.alibaba.cloud.ai.graph.RunnableConfig;import com.alibaba.cloud.ai.graph.agent.hook.*;import java.util.List;import java.util.Map;import java.util.concurrent.CompletableFuture; @Override public HookType getHookType () { return null ; } @Override public List<JumpTo> canJumpTo () { return null ; } @Override public CompletableFuture<Map<String, Object>> beforeAgent (OverAllState state, RunnableConfig config) { System.out.println("Agent 开始执行" ); return CompletableFuture.completedFuture(Map.of()); } @Override public CompletableFuture<Map<String, Object>> afterAgent (OverAllState state, RunnableConfig config) { System.out.println("Agent 执行完成" ); return CompletableFuture.completedFuture(Map.of()); } }
Interceptors Interceptors 顾名思义就是拦截器 ,用于在 模型调用(Model)和工具执行(Tool) 这两个具体操作层面上进行拦截、修改和增强。它们的核心职责是:
与 Hooks 的区别 Hooks 和 Interceptors 都是在 Agent 执行流程中“插脚”的扩展机制,但它们关注的层级完全不同。Hooks 属于生命周期级别的插入点 ,作用于 Agent 的整体执行阶段,例如开始与结束、每一轮模型调用前后等,更适合承担可观测性、执行流程控制、上下文增强、审计与限流等职责。Hooks 关注的是 Agent 作为一个整体是如何被执行的,通常不会直接改写模型调用或工具执行的具体行为。
Interceptors 则是调用级别的拦截器 ,只关注单次模型调用或单次工具执行本身,能够对请求和响应进行直接干预,例如参数改写、结果修改、重试、降级、缓存或工具选择等,就是一次调用的拦截器。
Hooks 控制 Agent 的执行节奏和流程,Interceptors 控制具体的调用行为;Hooks 在生命周期节点插入,Interceptors 在调用边界拦截。
敏感词防控 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package cn.hollis.llm.mentor.hooks;import com.alibaba.cloud.ai.graph.agent.interceptor.ModelCallHandler;import com.alibaba.cloud.ai.graph.agent.interceptor.ModelInterceptor;import com.alibaba.cloud.ai.graph.agent.interceptor.ModelRequest;import com.alibaba.cloud.ai.graph.agent.interceptor.ModelResponse;import org.springframework.ai.chat.messages.AssistantMessage;import org.springframework.ai.chat.messages.Message;import java.util.List;public class GuardrailInterceptor extends ModelInterceptor { @Override public ModelResponse interceptModel (ModelRequest request, ModelCallHandler handler) { ModelResponse response = handler.call(request); return response; } private boolean containsSensitiveContent (List<Message> messages) { if (messages == null ) { return false ; } for (Message msg : messages) { String content = msg.getText(); if (content == null ) { continue ; } if (content.contains("暴力" ) || content.contains("违法" ) || content.contains("敏感词" )) { return true ; } } return false ; } @Override public String getName () { return "GuardrailInterceptor" ; } }
1 2 ReactAgent agent = ReactAgent.builder() .name("poem_agent" ) .model(chatModel) .interceptors(new GuardrailInterceptor ()) .outputType(BookListResult.class) .build(); String res = agent.call("推荐5本暴力相关的书籍" ).getText(); System.out.println(res);
动态提示词 ReactAgent 支持使用 ModelInterceptor 实现基于上下文的动态提示词:(Interceptor你理解为就是我们前面介绍的Advisor机制,一种拦截器,可以在调用模型前做一些特殊处理 )
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package cn.hollis.llm.mentor.tools;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.RunnableConfig;import com.alibaba.cloud.ai.graph.agent.ReactAgent;import com.alibaba.cloud.ai.graph.agent.interceptor.ModelInterceptor;import com.alibaba.cloud.ai.graph.agent.interceptor.ModelRequest;import com.alibaba.cloud.ai.graph.agent.interceptor.ModelResponse;import com.alibaba.cloud.ai.graph.agent.interceptor.ModelCallHandler;import org.springframework.ai.chat.messages.SystemMessage;import org.springframework.ai.chat.model.ChatModel;public class DynamicPromptInterceptor extends ModelInterceptor { @Override public ModelResponse interceptModel (ModelRequest request, ModelCallHandler handler) { SystemMessage enhancedSystemMessage; if (request.getSystemMessage() == null ) { enhancedSystemMessage = new SystemMessage (dynamicPrompt); } else { enhancedSystemMessage = new SystemMessage (request.getSystemMessage().getText() + " " + dynamicPrompt); } ModelRequest modified = ModelRequest.builder(request) .systemMessage(enhancedSystemMessage) .build(); return handler.call(modified); } @Override public String getName () { return "DynamicPromptInterceptor" ; } public static void main (String[] args) throws Exception { ReactAgent agent = ReactAgent.builder() .name("adaptive_agent" ) .model(chatModel) .interceptors(new DynamicPromptInterceptor ()) .build(); RunnableConfig runnableConfig = RunnableConfig.builder() .addMetadata("user_role" , "beginner" ) .build(); System.out.println(agent.call("你好,你是谁" , runnableConfig).getText()); } }