核心要点
Spring AI 定位偏「框架原语」:ChatClient、Tool Calling、Advisors、ChatMemory,而非现成的 Agent 黑盒
ReAct = 在这些原语上手写控制流:思考(Reason)→ 选工具(Act)→ 执行 → 观察(Observation)→ 回灌上下文 → 循环,直到模型判断完成
把工具用 @Tool/ToolCallback 注册给 ChatClient,每轮让模型决定下一步动作或给出最终答案,用 ChatMemory 维护推理与观察过程
防死循环是关键:设最大迭代次数、成本/时间预算,并明确终止判断(模型声明完成或无新动作),超限即终止或转人工
标准回答
Spring AI 的定位
Spring AI 没有把「自主 Agent」封成一键黑盒,而是提供一组 框架原语:ChatClient(统一对话入口)、Tool Calling(把方法暴露给模型调用)、Advisors(在请求/响应链上做拦截增强,如 RAG、日志)、ChatMemory(多轮记忆)。构建 ReAct Agent,本质是用这些原语自己拼出控制流,而不是期待框架替你做规划。
ReAct 循环的骨架
ReAct(Reason + Act)的核心是让模型显式「边想边做」:每一轮先 推理(Thought) 当前该干什么,再决定 动作(Action)——调用某个工具或直接给出最终答案;工具执行后把 观察(Observation) 结果回灌进上下文,进入下一轮。用 Spring AI 实现时,外层是一个由你掌控的 while 循环:调用 ChatClient → 若模型发起工具调用则执行并把结果加入记忆 → 否则视为产出最终答案、跳出循环。
用框架原语拼装
把可用工具通过 @Tool 注解或 ToolCallback 注册到 ChatClient;模型在每轮可自主选择调用哪个工具,框架负责 Function Calling 的参数解析与回填。用 ChatMemory 把每轮的 Thought、工具入参出参、Observation 累积为过程上下文,让模型基于完整历史决定下一步。可用 Advisor 注入系统提示(约束输出 ReAct 格式或要求每步声明是否完成)、做 RAG 增强或统一记录 trace。系统提示是关键:明确告诉模型「需要更多信息就调用工具,信息足够就直接回答」。
终止与防死循环
自主循环最大的风险是失控。必须设 最大迭代次数 与 成本/时间预算,达到上限即强制终止并降级(返回已有信息或转人工)。终止判断有两类信号:模型显式声明「已完成」并给出最终答案,或某轮不再产生新的工具调用。对重复或低收益的动作(反复调同一工具拿同样结果)做去重并提前结束。每步可校验工具结果是否有效,避免模型在错误观察上空转。
可观测与可靠性
把每轮的推理、动作、观察、耗时与成本落 trace,便于复盘 Agent 为何绕路或失控。工具失败做有限重试加退避,不可恢复则降级。评估上关注端到端任务完成率与平均迭代步数,而非单步工具成功率,才能真实反映这套手写 ReAct 控制流的可靠性。
常见误区
⚠️ 常见踩坑
把 Spring AI 当成自带「自主 Agent」的框架,期待一行配置就能规划——它给的是原语,控制流要自己写。另一个常见错误是只管让模型循环调用工具,却不设最大迭代、预算与明确终止判断,导致死循环、成本爆炸或在错误观察上空转。还有人忽视 ChatMemory,每轮丢失之前的 Thought/Observation,模型无法基于完整过程推进。最后,只看单步工具调用是否成功、不看端到端任务完成率,会高估 Agent 可靠性。
追问
追问 1:ChatMemory 在 ReAct 循环里具体维护什么,为什么不可省?
追问 2:如何在循环中可靠地判断「任务已完成」该退出?
主要有两类信号。其一是模型主动声明完成:在系统提示里约定输出格式,要求模型在信息足够时直接给出最终答案而非再发工具调用,框架检测到本轮无工具调用即视为结束。其二是结构化终止条件:要求模型每轮显式输出「是否完成」字段或特定结束标记,由外层循环解析判断。两者都应叠加硬性兜底——最大迭代次数与成本/时间预算,达到即强制终止,避免模型永远不声明完成而无限绕圈。
🔗 相似问题
同一考点的不同问法,面试官可能换着问,一起刷更稳
没找到想看的面试题?把你想看的告诉我们 →
延伸学习
按主题分类的相关资源,便于系统复习