☰
Agent决策规划四范式全解析:ReAct、Plan-and-Execute、Reflexion与ToT
2026/10/26 6:21:53 网站建设 项目流程

最近不少人在折腾 Agent 开发,问得最多的不是“怎么调 API”,而是“我的 Agent 遇到岔路口到底该怎么决策、怎么规划”。这个问题不解决,模型再强也会在两步之后开始绕圈,或者反复执行同一个无效动作。这篇就把目前工程上最常碰到的四种决策与规划思路——ReAct、Plan-and-Execute、Reflexion、Tree of Thoughts——掰开揉碎讲清楚,包括它们各自解决什么问题、实现套路是什么、什么时候用哪个、有哪些我实测下来会翻车的细节。

这篇文章适合正在搭建 Agent、或者准备 Agent 面试的朋友,也适合想知道“不同 Agent 框架里那些节点到底在干啥”的开发者。

1. 四种范式,先搞明白它们到底在解决什么

1.1 决策规划问题的根源不在模型,而在流程

先说一个容易被忽略的事实:单一 LLM 调用本身没有“规划”能力,它只是在生成概率上最合理的下一段文本。你让它写“去超市买牛奶再回家”,它可以把步骤列得井井有条,但那是语言模式的复现,不是真正的规划。真正让 Agent 具备规划能力的,是我们围绕模型调用搭建的流程:什么时候推理、什么时候行动、什么时候停下来反思、如何比较多条路径。

这四种范式的本质差异,就是流程结构不同。ReAct 把推理与行动交错在一起,每一步想一点、做一点;Plan-and-Execute 把“想”和“做”拆到两个阶段,先全盘想清楚再逐步执行;Reflexion 在流程之外加了一个“事后总结”的缓存机制,让 Agent 能从错误里学习;Tree of Thoughts 则干脆把整个推理过程变成一棵搜索树,用搜索策略替代单线条推理。所以,选哪种范式,本质上是在回答一个问题:你的任务允许 Agent 在什么粒度上停下来思考。

我见过很多项目一上来就直接套 ReAct,其实策略不匹配是 Agent 效果差的头号原因。任务步骤少、反馈频繁的场景,ReAct 没问题;任务需要多阶段推进、中间不能频繁打断的场景,Plan-and-Execute 更合适。这一点下面会详细拆。

1.2 四种范式的核心差异一眼看懂

先用一张表把它们的核心思路和适用场景摆出来,后面再逐个深入。这张表格我建议你收藏,因为后面面试或者做技术选型的时候你一定会用到。

范式核心思路流程结构典型适用场景主要风险
ReAct推理与行动交替,边想边做单线程循环工具调用、信息查询、多步操作上下文膨胀、长任务失控
Plan-and-Execute先规划后执行,计划显式维护两阶段流水线长任务、多子任务编排计划僵化、无法应对动态变化
Reflexion在 ReAct 基础上增加反思记忆循环 + 反思缓存需要从失败中学习的任务反思质量不稳定
Tree of Thoughts多路径树状搜索,评估后择优树形搜索高难度推理、多种可能路径计算成本极高

从架构角度看,这四种不是互斥关系。实际项目里往往是把它们嵌套起来用的——比如用 Plan-and-Execute 做外层规划,内层每个执行步骤再用 ReAct 跑,同时给整个循环加上 Reflexion 的反思缓存。Tree of Thoughts 因为是搜索框架,反而更像一个独立的推理内核,可以嵌入到另外三种流程的一个节点里。理解到这个层面,你对 Agent 架构的理解就已经超过大多数只会调框架的人了。

2. ReAct:最经典也是最容易跑偏的思考-行动循环

2.1 ReAct 的原理拆解:Thought 不是废话,是推理锚点

ReAct 这个名字是从 Reasoning and Acting 拼出来的,核心思想是在模型的每一步输出里同时包含“思考”(Thought)和“行动”(Action),然后观察行动结果,再进入下一轮思考。这个循环直到 Agent 认为任务完成,输出 Final Answer。

在很多现有的 Agent 框架里(比如 LangChain 的 Agent 模块),你看到的 prompt 模板里通常会这样组织:

Answer the following questions as best you can. You have access to the following tools: ... Use the following format: Question: the input question you must answer Thought: you should always think about what to do Action: the action to take, should be one of [tool names] Action Input: the input to the action Observation: the result of the action ... (this Thought/Action/Action Input/Observation can repeat N times) Thought: I now know the final answer Final Answer: the final answer to the original input question

这里有一个新手最容易忽略的细节:Thought 字段并不是给模型“走神”用的,而是强制模型在文本层面先推理当前状态,再决定下一步动作。这个强制性的文本推理,实际上把模型的内部推理过程暴露到了输出空间,让它能够更好地利用上下文中的信息,尤其是能把自己上一轮的 Observation 和最初的问题之间建立逻辑连接。

我从工程效果的角度给你一个判断标准:如果你跑起来发现 Agent 老是重复调用同一个工具,或者明明答案已经在 Observation 里了还在继续调工具,问题十有八九出在 Thought 的质量上。Thought 写得太敷衍,模型就没有足够的“锚点”来修正自己的行为,最后陷入死循环。

2.2 ReAct 的实现要点:停止条件与最大迭代次数

实现 ReAct 的时候,最关键的参数不是模型温度,而是最大迭代次数和停止条件。为什么要特别强调这个?因为 ReAct 的循环本质是一个 while 循环,只要没输出 Final Answer 就会继续跑。一旦模型陷入了循环,就是白花 token 和时间。

我常用的做法是给循环设一个硬上限,比如 8 到 10 轮。超过这个次数直接终止,返回当前已有的信息,而不是等到超时。这个值不是拍脑袋定的,我一般会先分析任务的最短操作链:比如“查天气再决定穿什么”最短需要两轮,那上限至少要有 4 轮才够模型做纠偏;而一个“查资料→写代码→跑测试→改代码”的任务链,最少要 6 轮。实际操作中,把“最短轮数乘以 2 再加 2”作为最大迭代次数,是一个比较实用的公式。

另外,还有一个大家容易忽略的停止条件:Observation 返回了明确的错误信息,比如工具名不存在、参数格式不对。遇到这种情况,最好在下一轮 prompt 里直接提醒模型:上一个 Action 因为什么原因失败了,请分析原因后重新选择。如果不做这个特殊处理,模型很可能会基于那条错误的 Observation 继续“合理”地推理下去,而且会越推越偏。

2.3 实操心得:ReAct 里最常见的两个坑

第一个坑是上下文膨胀。ReAct 每一步都会把 Thought/Action/Observation 拼到 prompt 里,多轮之后上下文会越来越长,模型的注意力和指令遵循能力会明显下降。我实测下来,对话超过 8 轮后,模型开始出现“忘掉最初问题”的概率显著增加。解法有两个:任务太长的场景不要硬用 ReAct,拆成 Plan-and-Execute;如果一定要用,可以在中间的某几轮做一个“信息摘要”,把已经获得的关键信息压缩之后再继续。

第二个坑是工具结果太长。有的工具会把整份 JSON 或大段文本塞回 Observation 里,这会在两三轮之内就把上下文窗口吃光。我一般会在工具层做一个后处理:只截取前几百个字符,或者提取关键字段拼成摘要,再放进 Observation。这样既保留了必要的执行信息,又不会导致 prompt 过长。很多框架自带这个压缩机制,但如果你是自己实现的,一定要加这一层。

3. Plan-and-Execute:把所有问题在前置规划里想清楚

3.1 思路来源:把程序里的“分而治之”,搬给 LLM

Plan-and-Execute 的思路非常眼熟,完全就是工程领域经典的“先设计,后编码”流程。它把整个运行过程分成两个独立阶段:Planner 负责生成一个完整的、多步骤的计划;Executor 只负责把每一步计划具体执行掉。两个阶段各自用独立的 Prompt 和独立的模型调用来实现,互不干扰。

这个决策在当时是我踩过 ReAct 的坑之后做出的关键调整。那时候我做一个多阶段的调研类 Agent,用 ReAct 跑,模型经常在中后期忘掉了前面已经确认的事实,导致最后结论和已采集的信息对不上。换成 Plan-and-Execute 之后,整个任务的推进变得非常可控。因为每一步执行之前,模型都要重新看一眼最初生成的计划,就像是带着一张地图去走路,而不是走一步看一步。

在主流框架(尤其是 LangChain 0.x 之后)里,这种模式有一个现成的抽象:Plan-and-Execute Agent。它的核心组成是两个 LLMChain,一个是 PlanChain,只负责根据目标生成步骤列表;另一个是 ExecutionChain,负责执行单步任务并产出结果。这里有一个工程上的关键细节:步骤列表不只是时间上的先后排序,更应该是一个有逻辑依赖关系的任务分解,这样后续某一步失败时,你能清楚地知道哪些步骤要重跑。

3.2 计划再执行的经典案例:多步骤调研任务

我把一个实际跑过的例子简化一下,给你展示一个 Planner 输出的计划结构。目标是“调研量子计算在金融风控领域的最新应用”。Planner 生成的计划大致是这样的:

1. 搜索关键词:量子计算与金融风控,汇总近两年的行业报告 2. 对报告中的核心技术方案(QUBO、量子退火、混合计算)进行归纳 3. 搜索这些技术方案的落地案例,至少找到 3 个金融机构的实际应用 4. 对比案例中的优势和不足,形成结论 5. 按照【背景、技术、案例、总结】的结构输出调研报告

注意,这个计划里每一条都是可以独立执行、独立验证的。这非常重要。如果计划里包含“深入思考量子计算的本质”这种没法直接执行的任务,Executor 就会不知道该调用什么工具、产出什么格式的结果。判断计划好坏的标准,就是把它交给一个完全没有“计划上下文”的执行者,它能不能直接开干。

3.3 动态修正:计划不许改,但可以“重新计划”

Plan-and-Execute 一个最受争议的缺点就是计划僵化。实际任务里常有意外:某个信息源没有权限、某个工具临时不可用、某一步的产出和预期不符。如果计划是死的,整个 Agent 就直接卡死了。

解决这个问题的主流做法是给 Planner 增加一个“重新规划”的触发机制。比如在 Executor 的每一步执行结果后加一个判断器,如果发现当前步骤无法执行、或执行失败超过一定次数,就把失败原因作为额外上下文传回 Planner,让它重新生成后面的计划。这个机制,在很多开源框架里叫 Replan,也是 Plan-and-Execute 和 Reflect 模式结合的常见入口。

这个触发机制设计时有一个细节要特别注意:重规划不是从头再来,而是聚焦在“受到影响的后续步骤”上。如果前面步骤的结果只影响第三步而第四步不受影响,那重规划的产出应该尽量保留第四步,只修正第三步。我在实现的时候会在 replan 的 prompt 里明确要求“只修改受影响的步骤,其余保持原样”,这样能显著减少因为重规划而丢失已有进度的情况。

4. Reflexion:把“自己反思自己的错误”做成缓存

4.1 反思不只是“再来一次”,它需要被记录

Reflexion 这个范式最早是 Shinn 等人提出的,它的核心贡献是引入了“语言反馈”(linguistic feedback)这个概念,让 Agent 可以把失败的原因和教训用自然语言表达出来,并在下一轮尝试中参考这些教训。这和单纯地重新跑一遍是本质不同的——普通的重试只是在不同的随机序列下再试,而 Reflexion 是在“知道自己上次为什么错”的前提下再试。

这里最容易产生误解的地方是:Reflexion 并不是独立于 ReAct 或 Plan-and-Execute 之外的一种决策策略,它更像是一个“元策略”,是叠加在基础流程之上的增强机制。你可以把它理解成一个独立的 Reflection 模块,基础流程每跑完一轮,这个模块会根据完整的轨迹输出几条“经验教训”,然后存到一个跨会话的缓存里。下一轮开始前,这些教训会和初始 prompt 一起注入模型,相当于让 Agent 带着上次踩坑的记忆重新出发。

4.2 记忆如何存、如何取:Reflexion 的工程实现

实现 Reflexion 时,最核心的问题就是“教训怎么存、怎么取”。我在实践中最常用的做法是把它存成一个专门的经验库,也就是一组“教训文本”的列表。每次任务失败后,把反思结果 prepend 到新一轮的 prompt 里,而不是拼接在长期对话历史里。拼接在历史里会让模型越来越困惑,因为历史里既有失败的动作,也有成功的思路。prepend 则是把反射结论作为最高优先级指令,跟初始系统提示放在一起,让模型明确知道“之前踩过这些坑,别踩了”。

我用一个简化的 Python 伪代码来说明这个思路,你一看就明白:

class ReflexionAgent: def __init__(self): self.memory = [] # 存储教训列表 def run(self, task): prompt = self.base_prompt() if self.memory: # 把教训作为最高优先级提示,插在开头 prompt = self.format_lessons(self.memory) + prompt result = self.execute(prompt) if not result.success: lesson = self.reflect(task, result.trace) self.memory.append(lesson) return result

注意一个容易被忽略的设计点:这节课存下来之后,应该在什么时候“忘掉”?如果一个教训在新的任务里反复出现但已经不再适用,它反而会干扰后续决策。我常用的策略是给教训加一个“适用次数”计数,连续几次新任务都没触发使用就自动降权或者清除。这不是严格的记忆机制,但对于大多数工程场景足够用,而且实现成本很低。

4.3 反思质量不稳定,这套机制就废了

Reflexion 的效果完全取决于反思模块的输出质量。如果反思总结出来的教训是“下次要更小心”,那就等于什么都没说;如果教训是“第三步不能用 XX 工具,因为它的返回结果不包含时间字段”,那下一轮就有明确指导意义。

要让反思输出高质量,我建议在反思模块的 prompt 里规定三段式结构:当前目标的达成状态、失败的直接原因、下一轮尝试的具体修改策略。其中第三段最关键,因为它必须是一个可执行的动作——比如“修改搜索关键词为...”或者“先调用 B 工具获取时间戳再调用 A 工具”。光说不做式的反思,不会带来任何收益。

我在实际项目里的体会是:与其设计复杂的反思模型,不如先把反思 prompt 写清楚。大多数开源框架自带的反思模块,反思效果其实都一般,因为它的输出太模糊。你如果不满意,优先去改反思 prompt,让它必须输出可以执行的修改建议,而不是停留在复述失败经过。

5. Tree of Thoughts:把“思考”变成一次搜索

5.1 为什么要树状搜索:单线条思考的致命缺陷

Tree of Thoughts(ToT)的核心动机,是针对复杂推理任务里单线条思考的致命缺陷——一旦在某一步选错了方向,后续所有推理都会被带偏,而且这种错误是很难中途发现的。ToT 的思路是:不把一个思考过程限制为一条线,而是同时维护多个不同的思考分支,让模型在每个决策点生成多个候选的下一步,然后用评估手段筛选出最有希望的方向,最后用 BFS 或者 DFS 在整棵树上搜索最终解答。

要理解这个事情,你可以把它类比成下棋。一个不会树状搜索的棋手,只能看到当前这一步怎么走最舒服,但看不到几步之后的局势变化;会搜索的棋手会在脑子里快速推演多条走法,每条走法往后想几步,选择胜率最高的那条。ToT 本质上就是把这个过程交给了 LLM 和多轮评估。

5.2 ToT 的四个关键环节:分解、生成、评估、搜索

ToT 不是一套具体的模型,而是一个搜索框架。它的实现包含四个关键环节,每个环节都是可以单独调优的。

第一是问题分解,也是最关键的环节。不是所有任务都适合 ToT,只有那些“可以分步、每步有多个可行方向、且方向优劣能评估”的任务才适合。比如数学题、逻辑推理题、生成长文本的篇章规划。如果一个问题无法分解,或者每步只有一个确定的方向,那 ToT 就是杀了鸡用了牛刀。

第二是候选生成,每个决策点要生成多个不同的候选。这里最容易犯的错误是让模型生成“同质化”的候选——看起来是三个选项,其实只是换了一种说法。我通常会在 prompt 里明确要求“给出三种思路差异明显的方案”,甚至给候选编号并要求模型说明每个候选的核心区别。

第三是评估,也就是对候选分支的打分。评估方式有两种:给分法和投票法。给分法是让模型对每个候选输出一个 1 到 10 的分数,适合可以用确定性标准衡量的任务;投票法是让模型从若干候选中选出最优,适合主观性更强的任务。我在实际项目里发现,给分法往往会受到模型“平均化倾向”影响——所有候选都打到 6 到 7 分,区分度不足。这时候把给分法改成让模型先给出两个方向的优劣比较,再输出选择,效果会好很多。

第四是搜索算法,BFS 还是 DFS,取决于问题的深度和宽度。如果每个决策点有 3 个候选、最多走 5 步,那全量搜索就是 3 的 5 次方,243 条路径。对 LLM 来说这个成本已经很高,所以实际中必须依赖评估剪枝,每层只保留 top-k 个分支。这个 k 就是你要平衡质量和成本的旋钮。k 越大结果越好但成本越高,通常从 2 到 3 开始试。

5.3 ToT 的 token 成本实在太高,怎么降

说实话,ToT 是最“贵”的决策范式。原因在于:每个候选节点都要调用一次模型进行评估,而且树越深,评估次数呈指数级增长。一个只走 4 层、每层 2 个候选、评估 1 次的简单 ToT,也要产生大概 10 次以上的模型调用。这还不算候选生成本身的成本。

要把成本降下来,我常用的手段有三种。第一种是混合策略,只在任务的关键决策点使用 ToT,其他步骤用 ReAct 快速带过,这个下文专门讲。第二种是批量评估,把多个候选放在一次模型调用里评估,省掉多次调用的系统开销。比如一次调用让模型把 3 个候选的分数都打出来。第三种是提前终止,如果某个候选节点的评估分数超过了阈值,就不再展开其他分支,直接沿着这条路径走到底。这三种方案叠加之后,我实测能省掉超过一半的 token 调用。

6. 选型与组合:真实场景到底该用哪一个

6.1 决策树:按任务特征快速选型

没有一种范式是银弹。我给你整理一个自己在项目里常用选择流程,你可以当成规则来用。先回答三个问题:

  • 任务能不能预先拆成明确的步骤?如果能,优先考虑 Plan-and-Execute;如果不能,说明任务本身就是探索性的,先用 ReAct。
  • 任务执行过程中错误之后需不需要修正策略?如果需要,在 ReAct 或 Plan-and-Execute 的外层叠加 Reflexion。
  • 任务的关键环节是否存在多条路径且路径质量差异很大?如果存在,就在对应环节换成 Tree of Thoughts。

这三个问题问完,你基本能定位到自己的主循环范式。剩下的是把范式组合起来。

6.2 混合范式:最务实的组合模式

我实际生产环境里最常用的一套组合是:外层用 Plan-and-Execute 把控全局,内层每个执行节点用 ReAct 处理具体的工具调用,然后在主循环外加 Reflexion 做失败自我修正,最后只在少数高难度决策点用 Tree of Thoughts。

举一个电商 Agent 的例子。外层的计划是:理解需求→检索候选商品→对比参数→推荐结论。执行“检索候选商品”这一步时,内层 ReAct 会反复调用搜索和筛选工具。如果这一步的结果不稳定(比如搜索返回空结果),Reflexion 会把“该品类的搜索词要加上规格词”记录为教训。而“对比参数”如果面临多个商品维度差异很大、难以直接判断的情况,就用 ToT 生成多种对比维度组合并选优。

这样组合的好处是成本和效果达到了较好的平衡。ToT 只用在少数关键节点上,Reflexion 只在失败时损耗额外 token,Plan-and-Execute 保证了流程的可控性,ReAct 保证了每步的灵活性。这套组合说穿了其实就是“用合适的工具解决合适的问题”,但在 Agent 场景下,很多人因为偷懒或者对单一范式的依赖,硬是把它做成了“一个 ReAct 循环走天下”。

6.3 参数与约束速查表

为了让你在落地时可以快速起步,我再整理一个简单的参数速查表。这是我在调试了多个项目之后沉淀下来的经验值,你可以以它为起点再针对自己的任务调整。

范式关键参数建议初始值调整信号
ReAct最大迭代次数最短操作链×2+2经常超限但接近答案:加 2 轮
Plan-and-Execute计划细粒度每步可独立执行执行频繁失败:加粗步骤描述
Reflexion教训注入位置prompt 最前教训被忽略:把教训改写成更强的命令式语气
ToTtop-k 分支数2结果质量不足:加到 3,再留意成本
ToT评估方式投票法候选分数拉不开差距:换优劣比较

这里要特别说一句:表格里的数值不是真理,是起点。每个任务的语义复杂度、每类模型的推理能力都不同,所以调参的核心思路是“先跑通,再定点优化”,不要一上来就去追求最完美的参数组合。

7. 常见问题与排查技巧实录

7.1 模型陷入反复调用工具的循环里

这是 ReAct 类 Agent 最经典的故障,我看到过几十次。现象是模型不断调用同一个工具、用同一个参数,即使 Observation 明确显示结果没变化,它还是“执着”地重试。

排查思路从三个层面展开:先看是不是工具结果没有进入后续 prompt,也就是上下文拼装环节出了问题;再看是不是最大迭代次数设得太高,让模型有足够的空间原地打转;最后看 Thought 部分是不是缺乏有效的新信息,导致模型只能重复之前的决策。如果是最后一种情况,我会在 prompt 里显式加一句“如果一个新的行动无法带来任何新信息,请直接基于已有信息给出最终回答”。

7.2 反思教训注入后反而干扰了后续决策

Reflexion 的一个隐藏风险是:上一轮的教训在当前任务阶段并不适用。比如一个任务前几步要求“快速尝试多种解法”,后几步要求“收敛到最优解”,如果你在一开始就把“不要再尝试新方法”的教训注入,反而会压制探索。这种情况我遇到过不止一次。

解决办法是给教训打上“阶段标签”,在注入时根据当前执行阶段过滤教训。具体做法是:在反思生成时要求它输出“适用于什么类型步骤”,比如“信息收集”或者“最终验证”。新一轮执行时,只有当当前步骤类型匹配时才会注入对应教训。这个过滤逻辑实现成本不高,但对效果提升很明显。

7.3 成本失控的排查顺序

如果你的 Agent 每天跑完一看账单想离职,先别急着换模型或者压 max token,按照这个顺序排查:第一,是否是 ToT 的搜索分支太多,压缩 top-k;第二,是否是 ReAct 循环次数太多,调低最大迭代次数;第三,是否每轮都把全部历史纪录塞进 prompt,该做信息压缩了;最后,才是考虑换更便宜的模型。我见过很多团队在“换模型”上花了大把精力,结果回头一查,是历史纪录无限膨胀导致的 token 浪费。

7.4 面试和复盘时的高频问题

最后附带回答一个技术选型复盘常被问的问题:“既然 Reflexion 能反思,为什么不所有任务都加上?”我的答案是:反思也是有成本的。一次失败的执行,意味着一次完整的 ReAct 轨迹从头跑断了,再加上反思是一次模型调用,下一轮重新执行又是一次完整调用。整个失败重试链的成本,是成功路径的 3 倍左右。如果任务本身成功率不低,反思的边际收益会迅速递减。所以我的经验是:只有当任务失败率超过 30% 时,Reflexion 的投入才明显划算。低于这个阈值,不如先去优化工具本身和提示词。

这个阈值来自我实测项目的统计,不同领域有差异,但思路可以复用:用“失败率”“重跑成本”和“反思成功率”三个指标来量化分析,而不是凭感觉决定要不要上反思机制。

这套决策与规划的框架,说到底是把一个模糊的“让 Agent 更聪明”的目标,拆成了流程结构、记忆机制、搜索策略几个具象的工程问题。顺着这条线往后走,你会发现它还能继续扩展出很多变体——比如多 Agent 之间的规划协作、带工具反馈闭环的自我纠错、甚至是模型对自身规划的置信度评估。这些扩展的核心,其实都离不开本文里反复出现的那几个关键词:清晰的目标分解、让模型有足够的信息做决策、以及让失败能被结构化地记住。希望这篇能帮你把 Agent 里最抽象的那部分变成可以动手调的东西。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询