全书目录

第四编 系统层

第 20 章 决策循环:ReAct、Plan-then-execute、Reflexion 与代码编排

9 分钟 3,678 字 第 21 / 161 个阅读单元

任何 Agent 系统的核心,都是它的决策循环。

一个系统到底怎么从“看见世界”走到“采取动作”,再从“动作结果”走回下一轮判断,这件事从来不是自然而然发生的。它一定依赖某种显式或隐式的控制逻辑。没有控制逻辑,就没有真正意义上的 Agent,只有一段看起来很聪明的输出。

所以,理解决策循环,本质上是在理解 Agent 的运行时控制策略。

很多人第一次接触 Agent 时,会把注意力放在 prompt、tool list 或模型选型上。但这些都还不是核心。真正决定系统表现的,往往是这一层:模型什么时候该想,什么时候该做,做完之后系统拿什么反馈给它,失败时谁来决定是否重试,出现分支时是否先规划,规划失效后是否允许重排,运行到什么条件时必须停下。这些问题加在一起,构成了 Agent 的 loop。

因此,本章首先要建立一个判断:

text
Agent 的质量,往往不只由单步能力决定,而由它的循环设计决定。

同样一个模型、同样一组工具,放进不同循环里,结果可能完全不同。因为 Agent 从来不是只做一次决策,它做的是一连串互相影响的决策。只要任务超过一步,系统就已经进入了控制问题,而不是纯粹的语言生成问题。

从工程实践和研究文献看,常见循环大致可以分成四种主形态。

第一种,是边想边做。

这类循环最典型的代表就是 ReAct。系统并不要求模型先把整件事规划清楚,而是让它在当前信息下做一步判断、发起一个动作、观察结果、再继续下一步。它的优点是灵活,能快速适应环境反馈;缺点是容易局部合理、全局漂移。因为模型每一步都可能看起来说得通,但整条轨迹不一定收敛到正确目标。

第二种,是先规划后执行。

这类循环会先要求模型把任务拆成若干步骤,再进入执行阶段。它适合目标清楚、任务较长、每一步成本较高的场景,因为前置规划能减少无谓探索和随机试错。但它也有天然缺陷:计划是在不完全观察下提前生成的,一旦环境变化或前提判断错误,后续执行就可能沿着错误的高层结构一路推进。于是,好的 plan-then-execute 系统通常还必须带上 replanning,而不是只允许“先列计划,再机械执行”。

第三种,是执行中反思。

这类循环不满足于“做一步再做下一步”,它会把中间反馈拿回来,要求系统判断自己是否偏航、是否应该修正策略、是否要总结失败经验。Reflexion、Self-Refine、Reflective Memory Management 之所以重要,恰恰因为它们说明:Agent 的提升不只来自更好的下一步选择,也来自把过往失败显式变成后续决策的输入。换句话说,反思循环不是附加美化,而是一种减少重复错误的控制机制。

第四种,是代码编排。

这一类在企业场景尤其重要。它的基本思想是:循环的大结构不交给模型自由生成,而是由代码、工作流引擎或状态机先写死。模型只在某些节点负责判断,例如分类、摘要、参数填写、异常解释、候选方案生成。这样做牺牲了一部分开放性,却换来了更强的可测性、可预测性和治理能力。很多真正落地的系统最终都会往这一侧靠,因为业务方通常更关心系统能不能稳定跑,而不是它是否显得特别“自主”。

只要把这四类循环摆在一起,就会发现一个经常被误解的问题:不同循环并不是审美偏好,而是问题结构的匹配关系。

如果任务很短、工具很少、环境反馈直接,边想边做可能已经足够;如果任务很长、步骤之间依赖明显、试错成本很高,先规划后执行通常更稳;如果任务特别容易在中途偏航,或者系统会不断犯同一类错误,带反思的循环更有价值;如果每一步都带副作用、审批要求或强合规约束,代码编排往往更可控。

因此,现代 Agent 设计真正重要的,不是问“哪种范式最先进”,而是问三件事。

第一,这个任务到底需要几层决策。

第二,这些决策里哪些必须依赖环境反馈。

第三,哪些部分应由模型承担,哪些部分必须交给代码和工作流引擎承担。

这三件事一旦答错,循环就会设计错。循环一错,后面再怎么调 prompt,都只能是局部修补。

从经典控制与规划理论看,这个结论也完全成立。无论是 observe-decide-act 的反应式架构,还是先构造计划再监控执行的 deliberative 架构,还是带层级结构的 options 和 hierarchical control,本质上都在讨论同一个问题:什么时候局部反应足够,什么时候需要高层计划,什么时候要在执行中持续监控和重规划。今天 LLM Agent 的术语看起来更新,但底层问题没有变。

所以,第 20 章真正要讲的,不是几种流行名字,而是几个循环设计原则。

第一个原则,是每个循环都必须有清晰的进入条件和退出条件。

系统为什么进入下一轮?是因为拿到了新观察,还是因为上一步失败,还是因为还没有达到目标?系统为什么停止?是因为拿到了最终结构化输出,还是因为没有新工具可调,还是因为达到预算上限,还是因为触发了人工接管?如果这些条件不显式,Agent 很容易进入无意义重试、低质量自我对话或表面忙碌的空转。

第二个原则,是每个循环都必须知道自己基于什么状态做决策。

ReAct 不是看着空气做动作,它基于最新 observation 做动作;plan-then-execute 不是无条件执行计划,它应该基于执行进度和现实偏差不断检查计划是否仍有效;反思循环也不是随便写总结,它应该基于失败轨迹、验证结果和策略偏差提炼经验。决策循环如果和状态系统脱钩,就会变成无根推理。

第三个原则,是每个循环都必须明确失败回路。

失败后怎么办,是 Agent 设计最容易被低估的部分。失败到底意味着重试、换工具、回退一步、重做规划、升级给人工,还是直接终止?如果系统没有失败策略,它看起来像能运行,实际上只是在顺利时工作。一旦进入复杂环境,就会暴露出两个极端:要么一失败就全盘中断,要么明明已经偏航还继续执行。

第四个原则,是每个循环都必须可回放、可评测。

因为 Agent 的错误通常不是单步错误,而是轨迹错误。也许最终答案错了,但根因可能是第一步观察遗漏、第二步规划偏差、第三步工具参数错误、第四步没有根据测试结果调整路线。如果没有过程日志、trace grading、trajectory eval 和多轮评测,你能看到结果差,却看不到循环到底在哪里坏掉。

这也解释了为什么近两年的 benchmark 会越来越强调“轨迹正确性”。从 WebArena、ToolSandbox、AppWorld 到 SWE-bench 这类环境,真正考验的都不是一句答案,而是一整条执行路径能否连续、纠错、验证、收敛。模型如果只会在单轮上显得聪明,却不会在循环中稳定推进,最终就很难在真实世界里可靠工作。

代码 agent 尤其能把这个问题放大。

因为编码任务天然是长链条任务:读仓库、理解结构、复现 bug、修改代码、运行测试、分析失败、继续修正、生成说明。这里几乎每一步都会反过来改变下一步的输入。如果系统仍然使用“单轮聪明回答”的心智模型,就会很快失效。编码 Agent 真正依赖的是运行时循环:何时读文件、何时编辑、何时测试、何时验证、何时在失败后回滚或改路、何时停下来给用户一个可审查结果。

因此,代码编排不是第 20 章里一个狭窄例子,而是最能说明循环本质的场景。因为在这里,循环必须真正执行、真正验证、真正迭代,不能靠语言表演蒙混过去。

这一点在 OpenAI 的 Codex loop、Anthropic 的 agent loop、SWE-agent 的 ACI 设计,以及各类 coding agents 的 verify-and-repeat 结构里都表现得很清楚。它们共同说明:在复杂任务中,一个有效循环往往不是“多想一点”,而是“想一次,做一次,验一次,再决定是否继续”。没有验证的循环,只是高置信度试错;没有停止条件的循环,只是自动化漂移。

所以,决策循环最终不是一个模型问题,而是一个系统分工问题。

哪些判断交给模型,哪些判断交给规则;哪些环节允许探索,哪些环节必须确定;哪些步骤需要人批准,哪些步骤可自动推进;哪些失败可重试,哪些失败必须终止;哪些经验应写入反思记忆,哪些错误只能局部丢弃。循环设计,正是在这些边界之间做工程取舍。

用一个简单任务来看,也许差异不明显。如果任务只是“根据日志给出可能原因”,单次推理或简单 ReAct 已经足够。但如果任务是“读仓库 -> 复现 bug -> 改代码 -> 跑测试 -> 根据失败修正 -> 生成最终说明”,那它天然要求更复杂的 loop:需要规划,需要执行,需要验证,需要在失败后重排路径,也需要明确何时停。

因此,第 20 章最终要建立的结论是:

text
决策循环不是 Agent 的外壳,而是 Agent 的控制中枢。

ReAct、plan-then-execute、Reflexion 和代码编排,并不是彼此排斥的风格标签,而是不同问题结构下的控制策略组合。真正成熟的 Agent,不是执着于某一种循环最“高级”,而是知道在什么任务里该反应、什么时候该先计划、什么时候该反思、什么时候该把结构写进代码。只有这样,系统才不会在复杂任务里把聪明变成失控。