绝大多数 Agent 教程讲循环引擎,到 ReAct 就停了。
Thought → Action → Observation,再回到 Thought,循环往复——这个模式在论文里很优雅。但拿这个循环跑生产环境,你会发现它有三个致命缺陷,每一个都能让你的 Agent 在线上翻车。
本文从一个 7000+ 行 Rust 代码的真实 Agent 循环引擎出发,拆解生产级循环引擎到底怎么设计。所有机制、参数和链路均来自真实运行的生产系统,不是伪代码,不是框架文档里的概念图。
读完这篇,你会明白一个看起来简单的"循环调用 LLM"为什么需要 7000 行防护代码。
ReAct 的三个致命缺陷
ReAct 模式——Thought → Action → Observation——本质上是一个无限循环。它没有回答三个生产环境必须回答的问题。
第一,怎么判断 Agent 做完了?ReAct 循环里没有一个确定的退出条件。LLM 说"I’m done"就真的 done 了?在生产环境,“我完成了"不算完成——你得拿出证据。Anthropic 在 2024 年 12 月发布的"Building Effective Agents"中明确指出:Agent 在执行过程中,关键是从环境获取"地面真相”(ground truth)来评估进度——比如工具调用的结果、代码执行的输出——而不是依赖 LLM 的自我宣称。
第二,怎么防止 Agent 跑偏?用户在循环进行到第 5 轮时突然说了一句"算了,改成 XXX"。这个新输入是旧任务的补充,还是一个全新任务?ReAct 循环完全没有处理这种情况的机制。
第三,怎么防止 Agent 空转烧钱?一个没有退出条件的无限循环,如果 LLM 一直不产出有效结果,就会无限重试,烧光 API 额度。Anthropic 也警告:Agent 的自主性意味着更高的成本和误差累积的风险。
这三个问题的共同根因是:ReAct 循环里没有确定性约束。整个循环的行为完全依赖 LLM 的判断,而 LLM 是不确定的。
生产级循环引擎的核心设计理念就是:在 LLM 的不确定性之上,叠加一层又一层的确定性约束。
下面逐层拆解。
确定性预门禁:每轮循环前的工单机制
这是整个循环引擎的第一道防线,也是最关键的创新。
每轮 Agent 循环开始之前,循环引擎用纯 Rust 代码——不经过 LLM——生成一段执行契约,注入到 Agent 的输入前面。这个机制叫 Pre-AL Gate(Pre-Agent-Loop Gate)。
它注入的内容相当于一张"任务工单",上面写着:
你现在在第几轮循环(比如 3/20,意思是最多跑 20 轮,当前是第 3 轮);当前锁定的阶段是什么(比如"初稿撰写"阶段);哪些验收检查还没通过(比如"校验脚本未运行"和"初稿文件尚未生成");以及一组硬规则——不能在阶段未完成时宣称整体完成、不能跳过验收检查、必须返回具体证据。
为什么这层约束不能用 LLM?因为确定性约束的作用恰恰是限制 LLM 的自由度。如果用 LLM 来生成约束,就等于让被约束的对象自己制定规则——这在工程上没有意义。Pre-AL Gate 是纯代码逻辑,每次执行结果都完全确定,不受温度参数或随机种子影响。
注意那个迭代计数器——“3/20”。这不是建议,是硬约束。循环引擎里有一个写死的常量,叫EXPLICIT_MAX_ITERATIONS,值为 20。当一个 Agent 任务跑到第 20 轮还没完成时,循环引擎会强制把状态改成"paused",并写明暂停原因:“loop engine iteration budget reached after 20 iterations”(循环引擎迭代预算在 20 轮后耗尽)。一个 Agent 任务最多跑 20 轮循环,烧不到无限重试。
LLM-as-Judge:不是听 Agent 怎么说,是看 Agent 做了什么
预门禁解决了"每轮做什么"的问题。接下来要解决的是"做完了吗"。
ReAct 循环里,Agent 自己说 done 就是 done。生产级循环引擎不能这么干。这里的设计是引入一个独立的 LLM-as-Judge 评估器。
每轮 Agent 循环结束后,循环引擎做三件事:第一,用纯代码收集本轮的观察结果——包括助手输出的文本、工具调用记录、错误信息,打包成一个结构化的"观察包"。第二,把这个观察包发给一个独立的 LLM 调用做评估。第三,评估器返回一段结构化 JSON,循环引擎根据 JSON 里的字段决定下一步动作。
这里有一个关键设计决策:评估器的温度参数设为 0.0。
温度参数控制 LLM 输出的随机性。温度越高,输出越发散;温度为 0,LLM 在每一步都选择概率最高的 token,输出几乎完全确定。评估器的工作不是创造性写作,是判断——同一个输入,评估结果必须尽可能一致。所以温度必须是 0.0。同时,评估器的最大输出 token 数被限制在 4096,足够写出详细判断,又不会拖慢循环。
评估器返回的 JSON 包含几个核心字段:done(整体是否完成)、phase_done(当前阶段是否完成)、reason(判断理由)、evidence(证据列表)、next_action(下一步动作建议)、failure_type(失败类型分类)。其中evidence字段要求列出本轮具体做了什么——比如哪个脚本成功执行了、哪个文件生成了、哪个检查通过了。
评估器的 system prompt 里有一条铁律:像"完成了"“搞定了”"所有需求都满足了"这种话,没有证据就是空话。换句话说——你以为你做完了?拿出证据来。
Anthropic 把这种模式称为 Evaluator-Optimizer:一个 LLM 调用生成响应,另一个在循环中提供评估和反馈。Anthropic 明确说这种模式在有明确评估标准时特别有效。
但生产级系统比 Anthropic 描述的多了一层:确定性评估优先。
确定性优先:80% 的异常用代码秒判
在调用 LLM 评估器之前,循环引擎先用纯代码做一轮快速判断。这一步叫"确定性评估",它扫描 Agent 本轮的输出文本,用关键词匹配来检测三种情况。
第一种,阻塞标记。如果 Agent 输出里出现了"blocked"“无法继续”“需要你提供”“需要凭据”“需要授权"这类词,代码直接判定为"被阻塞”,下一步动作设为"暂停"。不需要调用 LLM 来判断 Agent 是否被阻塞——Agent 自己都说了无法继续,还花一次 API 调用来确认就是浪费钱。
第二种,用户决策请求。如果 Agent 输出里出现了"请选择"“请确认”“是否继续”“你想怎么推进"这类词,代码直接判定为"等待用户确认”,下一步动作设为"暂停"。循环引擎不应该替用户做决定——如果 Agent 在请求用户选择,循环必须停下来。
第三种,基础设施错误。如果 Agent 输出里出现了"LLM error"“operation timed out”“provider error"这类词,代码直接判定为"基础设施故障”,同样暂停。重复调用一个正在报错的 LLM 服务商毫无意义。
这三条规则覆盖了生产环境里大约 80% 的异常情况。Agent 说"无法继续"了,代码扫一眼就知道该暂停。Agent 碰到 API 超时了,代码直接标记基础设施故障。只有正常推进的情况下——也就是三条规则都没命中——才需要调用 LLM 评估器来做 nuanced 判断。
这意味着每轮循环的评估成本被大幅压缩:正常情况下花一次 LLM 调用,异常情况下一次都不用花。
阶段验收门禁:代码可以否决 LLM 的判断
评估器说 done 就是 done 了吗?还不是。
这是整个循环引擎里最精妙的设计——阶段验收门禁(Phase Gate)可以否决 LLM 评估器的判断。
假设 LLM 评估器看了 Agent 的输出,认为"这个阶段做完了"。循环引擎不会直接相信它。在决策阶段,引擎会检查:如果当前任务有结构化的阶段(phases),并且 LLM 说 done 或 phase_done,那就用纯代码再做一轮检查。
这一轮检查叫 Phase Gate。它的工作方式是:遍历当前阶段定义的所有验收检查项,逐个用代码验证是否通过。如果有任何一项没通过,引擎会直接把评估器的 done 改成 false,phase_done 改成 false,并写明原因:“验收门禁阻止了阶段完成,缺失项是 XXX”。
这就是"代码否决 LLM"的机制。LLM 的判断是建议性的,代码的检查是决定性的。
Phase Gate 支持四种验收检查类型,全部用代码执行,全部检查客观事实,全部不依赖 LLM 的主观判断:
脚本检查(script):检查工具调用日志里有没有成功执行过指定脚本。具体做法是把脚本命令标准化后,在工具调用记录的 tool_name、arguments、result 字段里搜索匹配。比如阶段要求"运行 validate_draft_outputs.py",引擎就在本轮工具调用日志里找:有没有一次 terminal 调用包含这个脚本名,而且 exit_code 是 0。没有就标记为"缺失"。
文件存在检查(file_exists):直接调用操作系统的路径存在检查。如果配置了 workspace_root(工作区根目录),相对路径会在工作区下查找;绝对路径直接检查。文件在磁盘上就是通过,不在就是不通过。没有任何"模糊判断"的余地。
文件数量检查(file_glob_count):用目录遍历工具按照通配符模式搜索文件,数一下匹配的文件个数够不够。比如阶段要求"至少生成 3 个 markdown 文件",引擎就会遍历指定目录,数 .md 文件的数量是否达到阈值。
用户确认检查(user_confirmation):检查有没有结构化的用户确认记录。每个确认记录绑定着阶段 ID 和检查项 ID,只有两个 ID 都匹配才算通过。这防止了用户对某个操作的确认被错误地应用到另一个操作上。
这四种检查的共同特征是:全部用代码执行,全部检查客观事实,全部不依赖 LLM 的主观判断。这套机制的核心思想是——把"任务完成"从 LLM 的自我宣称变成了可验证的客观事实。
决策状态机:10 条优先级链路
评估完了,门禁过了,接下来该干什么?这需要一个决策状态机。
循环引擎的核心决策函数叫advance_loop_state,它实现了一个 10 条路径的优先级决策链。每一轮循环结束后,引擎从第 1 条开始往下检查,命中第一条就执行对应动作,后面的不再检查。
优先级从高到低依次是:全部完成就最终输出(finalize);当前阶段完成就推进到下一阶段(advance_phase);被阻塞就暂停等待外部输入(pause_blocked);基础设施错误就暂停避免烧钱(pause_infrastructure);等待用户确认就暂停不替用户做决定(await_confirmation);评估器请求暂停就暂停(pause);连续解析失败就暂停别烧预算;达到迭代上限(20 轮)就暂停;无进展就计数加一继续推进;一切正常就继续(continue)。
这个优先级链路里有两个特别值得注意的设计。
第一,连续解析失败保护。如果 LLM 评估器连续好几轮返回的不是有效 JSON——比如返回了一段乱码或者截断的文本——循环引擎会触发暂停。暂停原因写得很直白:“paused to avoid burning the entire loop budget with a weak evaluator”——暂停以避免用一个坏掉的评估器烧光整个循环预算。与其让一个返回垃圾的评估器指导 20 轮循环,不如早点停下来排查问题。
第二,无进展计数器。即使循环没有被暂停,引擎也在持续追踪 Agent 是否真的在推进任务。每轮结束后,引擎调用一个叫made_observable_progress的函数,检查本轮是否有成功的工具调用、是否产生了新的证据项、评估器的 progress 字段是否不是"none"。如果有进展,计数器清零;如果没有,计数器加一。当计数器连续累加到一定值时,引擎的策略会从"继续"切换到"换策略"或"委派给子代理"——不再用同样的方法反复尝试。
这两个机制解决的是同一个问题:Agent 卡住了但不自知。ReAct 循环里 Agent 可以无限地"思考-行动-观察"而不产生任何实际进展,每次都觉得自己在做有用的事。生产级循环引擎用计数器和策略切换来打破这种自欺欺人的循环。
目标连续性裁决:用户中途插嘴怎么办?
循环跑到第 5 轮,用户突然说了一句新话。这句话是当前任务的补充,还是一个全新的任务?
这个问题在生产环境极其常见,但 ReAct 循环完全没有处理机制。循环引擎的做法是两级裁决:先用纯代码做确定性判断,搞不定才调用 LLM。
第一级是确定性判断,按七条规则依次检查。空输入,保持当前任务。用户明确说了"继续"“确认”“补充"这类词,判定为同一任务。用户明确说了"算了”“重新开始”"换一个"这类词,判定为新任务。如果当前任务没有被用户中断过,新输入就按当前任务的补充来处理。
如果任务确实被中断了,那就进入词汇重叠度评分。引擎把用户新输入和当前任务目标做一轮词汇比对,计算出一个重叠分数。这个分数有两个阈值:高于 0.24(即 24% 的词汇重叠),判定为同一任务。这意味着即使用户中断了当前任务,只要新输入还在谈同一件事,就继续推进。低于 0.08(即 8% 以下的词汇重叠),而且新输入看起来像一个完整的新需求,判定为新任务。语义上几乎没有重叠,说明用户是真的要换方向了。
如果重叠度落在 0.08 到 0.24 之间——不确定区域——就进入第二级:调用 LLM 做最终裁决。但 LLM 裁决器也有约束:温度参数设为 0.0,置信度低于 0.72 就强制判定为"模糊",让用户来做最终决定。
这个设计的精髓是:80% 的情况用代码秒判,20% 的边缘情况才花一次 LLM 调用。既保证了速度和确定性,又不会在复杂场景里做出错误判断。
那两个阈值——0.24 和 0.08——不是随便填的。它们是在大量真实对话样本上调试出来的平衡点。太高会把用户的合理补充误判为新任务,太低会把真正的新任务误判为旧任务的延续。
一次完整的循环执行链路
把上面所有组件串起来,一次完整的循环执行是这样的。
假设用户说"帮我写一篇关于循环引擎的技术文章"。循环引擎首先注入 Pre-AL Gate 执行契约——这是纯代码操作,告诉 Agent 当前是第 1 轮(共 20 轮),锁定在"研究素材收集"阶段,还没有通过的验收检查是"校验脚本"和"研究简报文件"。这段契约被拼接到用户输入前面,一起发给 Agent LLM。
Agent LLM 收到带约束的输入后开始执行。它可能调用了浏览器搜索资料,调用了文件写入保存研究素材,调用了终端运行校验脚本。这一轮结束时,这些操作全部被纯代码收集成一个"观察包"——里面记录了助手输出的文本、调用了几个工具、有没有错误、每个工具的执行结果。
接下来进入确定性快速判断。引擎扫描 Agent 输出,检查有没有命中阻塞标记、用户决策请求、基础设施错误。这次没命中——Agent 正常推进了——所以进入 LLM 评估。
LLM 评估器在温度 0.0 下运行,收到观察包后返回判断:整体没完成,但当前阶段完成了。理由是"研究素材已收集,校验脚本通过"。证据列表里列出了"校验脚本 exit_code=0"。这个判断看起来合理,但还不能信——要过验收门禁。
Phase Gate 检查当前阶段的两项验收:脚本检查在工具调用日志里搜索校验脚本的名字,找到了,exit_code 是 0,通过。文件存在检查直接在磁盘上找研究简报文件,找到了,通过。门禁全部通过。
决策状态机启动。phase_done 是 true,门禁通过了,当前阶段后面还有后续阶段,所以决策是"推进到下一阶段"。引擎标记当前阶段为已完成,激活下一阶段"初稿撰写",然后生成下一轮的 continuation prompt——里面会包含更新后的 Pre-AL Gate 工单:现在是第 2 轮了,阶段变成了"初稿撰写",新的验收检查项出现了。
下一轮循环开始,Pre-AL Gate 再次注入。
注意这条链路里的确定性层次:Pre-AL Gate 是确定的(纯代码),观察包收集是确定的(纯代码),确定性快速判断是确定的(纯代码),Phase Gate 是确定的(纯代码)。LLM 只参与两个环节:执行任务和评估进展。而且评估进展的 LLM 用温度 0.0,进一步压缩不确定性。
整个循环里,LLM 的不确定性被确定性约束包围着:预门禁约束不跳步,评估器约束不撒谎,验收门禁约束不放过。
评估器的反馈学习:失败也要留下教训
循环引擎还有一个容易被忽略的设计——每轮评估都会产生反馈记录。
评估器返回的 JSON 里有一个 feedback 字段。当这个字段标记了"应该记录"(should_record 为 true)时,循环引擎会把这次评估的反馈信息写入一个反馈日志。每条记录包含:第几轮循环、评估理由、进度评估、以及反馈详情——具体包括:
这次失败的模式是什么(mistake_pattern)
下次应该避免什么(avoid_next_time)
建议的下一步策略(suggested_next_strategy)
反馈日志最多保留 20 条,超过就丢弃最早的。这些记录会在后续的会话经验审查中被用来提取可复用的知识——哪些错误模式反复出现、哪些策略调整有效、哪些工具调用容易出问题。这就是记忆和进化系统的输入。
这意味着:循环引擎不仅在执行任务,还在从每次失败中学习。
行业共识 vs 生产实现
把循环引擎的设计和行业主流认知做个对比。
Anthropic 在"Building Effective Agents"里建议的三个原则:保持简单、优先透明(明确展示 planning steps)、精心设计 Agent-Computer Interface(ACI)。
生产级循环引擎的实现完全对应了这三条。简单——核心循环就是一个 while 循环加三层确定性约束,没有复杂的框架嵌套。透明——Pre-AL Gate 把当前状态、缺失项、硬规则全部注入到 prompt 里,用户和开发者随时可见。ACI——验收门禁把"完成"定义为可验证的客观事实,而不是依赖 LLM 的主观判断。
但生产实现比 Anthropic 的建议多了一层关键设计:确定性否决权。Anthropic 说"keep it simple",生产系统说"simple but with hard guardrails"——LLM 的判断可以被代码否决,而且代码否决优先级最高。
这就是为什么一个看起来简单的"循环调用 LLM"需要 7000+ 行 Rust 代码。不是因为循环本身复杂,而是因为在 LLM 的不确定性之上叠加足够多的确定性约束,需要大量的边界处理。每一条阻塞检测规则、每一个验收检查类型、每一次词汇重叠度评分、每一层优先级决策——都是一行行代码写出来的硬约束。
写在最后:循环引擎的本质
ReAct 论文告诉你循环是 Thought → Action → Observation。这是对的,但只对了一半。
另一半是:在生产环境里,每一次循环都需要确定性约束来保证 Agent 不会跑飞。Pre-AL Gate 保证不跳步,评估器保证不撒谎,验收门禁保证不放过,目标连续性裁决保证不跑偏,迭代上限保证不烧钱,解析失败保护保证不空转。
这六层确定性约束,每一层都是在为 LLM 的不确定性兜底。没有它们,你的 Agent 就是一个 fancy 的 demo。有了它们,你的 Agent 才有可能跑在生产环境里。
下次看到 Agent demo 时,问自己一个问题:它的循环引擎有确定性约束吗?如果 Agent 说"我做完了",代码会验证这个说法吗?
如果答案是否定的,那它离生产环境还有很远的距离。
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋
📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~