spring ai alibab agent之ReactAgent
一、什么是 Agent 模式
在大模型(LLM, Large Language Model)应用中,Agent 指的是:
能够自主规划、推理、调用工具并与外部环境交互的智能体。
与普通对话模型不同,Agent 不仅能"回答问题",还可以:
- 理解目标(Goal)
- 制定计划(Planning)
- 调用外部工具(Tool / API)
- 处理结果(Observation)
- 生成最终答案(Final Answer)
二、ReAct 模式简介
ReAct 是 "Reason + Act" 的缩写,来自论文:
ReAct: Synergizing Reasoning and Acting in Language Models
(Harvard & Google Research, 2022)
其核心思想是:
让模型在"思考(Reason)"与"行动(Act)"之间交替循环,直至完成任务。
这是一种通用的 Agent 推理与执行框架。
三、ReAct 的核心流程
| 组件 | 说明 |
|---|---|
| LLM | 语言模型本体,负责生成 Thought 与 Action |
| Memory | 存储上下文、历史交互和工具调用结果 |
| Tools | 可被调用的外部函数、API、数据库、插件等 |
| Parser | 解析 LLM 输出,识别 Thought/Action/Final Answer |
| Loop Controller | 控制 Reason-Act 循环,防止无限循环 |
| Environment | Agent 作用的外部环境(系统、文件、用户等) |
一个典型的 ReAct Agent 执行过程如下:
text
Thought: 我需要了解用户账户余额。
Action: 调用函数 get_balance(user_id=123)
Observation: 返回结果是 500 元。
Thought: 用户账户余额足够,我可以继续下单。
Action: 调用函数 place_order(item="电脑", price=400)
Observation: 下单成功。
Thought: 任务完成。
Final Answer: 用户已成功购买电脑。
四、spring ai alibaba是如何实现ReactAgent
ReactAgent是基于组件graph构建的应用层组件,它是一个内置单agent的实现,muti-agent基数也是在这个基础之上的。ReactAgent 实现依赖内置的graph Node节点,LlmNode和ToolNode,这个两个是关键点,ReactAgentLoop Controller 通过在这两个节点循环实现的。

这里边有一个重要提示,spring ai实现mcp时使用的模型的functioncall功能,而且封装的工具执行器,默认模型返回function call方法会自动执行,所以在配置ReactAgent model client时,需要注意需要改变这个默认值,不要自动执行。这是ToolNode节点能够执行的关键。就像使用下面的方式:
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultToolNames("getWeatherFunction")
.defaultAdvisors(new SimpleLoggerAdvisor())
.defaultOptions(OpenAiChatOptions.builder().internalToolExecutionEnabled(false).build())
.build();
在整个ReactAgent流转状态OverAllState 中有一个key名为messages的状态值,这个是ReactAgent默认的输入
ReactAgent.builder()
.name("React Agent Demo")
.chatClient(chatClient)
.resolver(resolver)
.maxIterations(10)
.build();
这个是代码中的备注:
// For graph built from ReactAgent, the only legal key used inside must be
// messages.
// if (outputKey != null && !outputKey.isEmpty()) {
// llmNodeBuilder.outputKey(outputKey);
// }
也就是说使用LlmNode唯一合法输入key OverAllState key必须是messages, 要不然LlmNode和ToolNode循环,两个节点的信息没有办法做交互,他们采用追加策略,最新的消息在最后一条。这个是ReactAgent使用前提。
核心think代码:
java
private String think(OverAllState state) {
//迭代次数
if (iterations > max_iterations) {
return "end";
}
// 这个是中断函数,什么时候直接中断
if (shouldContinueFunc != null && !shouldContinueFunc.apply(state)) {
return "end";
}
// 这是一个关键,模型节点执行后,返回结果,如果返回结果最后一条信息,LlmNode执行完会将结果追加到队列尾部,如果结果有function call信息,就到tool节点,tool执行完会把结果追加到messages,模型会取 messages作为大模型的上下文,给模型,让模型判断是否执行完,还是接着选中tool执行。
List<Message> messages = (List<Message>) state.value("messages").orElseThrow();
AssistantMessage message = (AssistantMessage) messages.get(messages.size() - 1);
if (message.hasToolCalls()) {
return "continue";
}
return "end";
}