让 Agent 从“单次思考”升级为“多轮推理”,真正具备自主决策能力
01 引子
在实战十二中,我们完成了 Agent 的工程化落地——错误处理、优雅降级、可观测性。Agent 在理想场景下表现得稳定可靠。
但有一个核心能力仍然缺失:循环推理。
当前的 Agent 是这样的:
用户提问 → 调用一次 AI → 调用工具 → 返回结果
这是“一次性的”。用户问什么,AI 就回答什么。但如果用户问的是复杂任务呢?
“帮我规划一个上海2日游,查查天气,推荐景点,安排行程”
这时候 Agent 需要做多件事:查天气 → 推荐景点 → 规划行程。每一步都需要根据上一步的结果来决定下一步做什么。这就需要循环推理。
这一篇的目标:让 Agent 具备多轮思考能力,能够像人类一样分步解决问题。
02 什么是循环推理?
2.1 当前 Agent 的局限
| 对比 | 当前 Agent | 循环推理 Agent |
|---|---|---|
| 推理轮次 | 1 轮 | 多轮(直到任务完成) |
| 决策方式 | 一次决策 | 根据中间结果动态决策 |
| 工具调用 | 最多 1-2 个 | 可调用多个,按顺序执行 |
| 任务复杂度 | 简单任务 | 复杂任务 |
2.2 ReAct 模式
ReAct =Reasoning(推理)+Acting(行动)
2.3 核心思想
循环推理不是“一次性回答”,而是“思考 → 行动 → 观察 → 再思考”的循环,直到任务完成。
03 代码实现
3.1 整体架构
3.2 完整代码
ReActAgentService.java
3.3 Controller 接口
ReActAgentController.java
04 测试验证
场景一:简单问题(无需工具)
请求:
分析:Agent 判断为简单问题,直接回答,没有调用工具。✅
场景二:单工具调用
请求:
分析:Agent 识别需要查询天气,调用getWeather("北京")。✅
场景三:多工具协作
请求:
分析:Agent 分别查询了两个城市的天气。✅
05 踩坑记录
坑一:AI 不按格式输出,导致循环空转
现象:请求后返回"抱歉,经过 6 轮思考,我无法完整回答您的问题。"
原因:AI 没有输出Action:或Final Answer:格式,导致parseOutput无法识别,循环空转 6 次后超时。
解决:
在
parseOutput中添加兜底逻辑:如果 AI 直接回复了自然语言(无 Action 标记),直接当作最终答案。优化 System Prompt,明确告诉 AI:简单问题直接回答,复杂问题用
Action:格式。
// 兜底逻辑 if (response != null && response.length() > 5) { parsed.isFinal = true; parsed.finalAnswer = response.trim(); }坑二:参数解析失败
现象:工具调用返回“参数不足”。
原因:parseParams方法在解析带多个参数的工具调用时出错。
解决:完善参数解析逻辑,支持双引号和逗号分隔。
private String[] parseParams(String paramsStr) { // 支持 "北京", "上海" 格式 // 支持 "G123", "二等座" 格式 }坑三:observability注入失败
现象:启动报错Bean not found。
原因:AgentObservability类没有添加@Component注解。
解决:确保AgentObservability类上有@Component注解。
06 成果总结
经过这一篇,你的 Agent 现在具备:
| 能力 | 状态 |
|---|---|
| 单工具调用 | ✅ |
| 多工具协作 | ✅ |
| 简单问题直接回答 | ✅ |
| 循环推理框架 | ✅ |
| 任务完成判断 | ✅ |
| 超时降级 | ✅ |
| 可观测性 | ✅ |
07 下期预告
循环推理完成后,Agent 系列的核心能力已经全部就绪。下一步,我们将把这些能力整合成一个完整的“智能助手”应用,涵盖:
多工具协作(天气 + 时间 + 订票)
循环推理(复杂任务拆解)
可观测性(调试模式)
错误处理(优雅降级)
下一篇:实战项目整合——构建完整的智能助手应用。
📌 我是超超不吵吵,10年Java全栈,正在转型AI应用开发。
每周一篇实战笔记,不贩卖焦虑,只分享能落地的技术。
全网同名,欢迎关注。