
你接触 Agent 类项目的时候“ReAct 循环”“先规划再执行”“自我反思”这三个词几乎避不开。它们不是某个框架的专利而是大模型和环境交互之后社区里反复沉淀出来的三类基础执行套路。ReAct 关心的是“怎么边想边干”Plan-and-Execute 关心的是“长任务怎么拆着干”Reflection 关心的是“干完怎么知道行不行”。这篇文章就用工程视角把三者各自的核心优势、解决了什么痛点、怎么选型、怎么组合落地拆开讲清楚。1. 三套模式的设计出发点与基础定位1.1 ReAct 的本质把推理和行动绑成一条闭环ReAct 是“推理 行动”的组合核心是一个反复执行的循环先让模型根据当前目标生成一段推理reasoning再从推理里挑出下一步动作action调完工具拿到观察结果observation之后继续回到推理环节。简单说它不要求模型一次性给出完整答案而是让模型像一个在陌生环境里探路的人走一步看一眼再想下一步。很多人第一次实现 Agent 时习惯把“生成计划”和“执行计划”分成两次大调用试过之后才发现现实任务的干扰因素太多提前写好的计划根本跟不上真实反馈。ReAct 最妙的地方在于它把“想”和“做”的自然语言痕迹留在了上下文里工具返回什么下一步推理就接着什么生长天然适合那些需要根据实时反馈不断调整的任务。比如查资料的时候搜出来的结果和预期相反ReAct 能立刻察觉然后换个关键词再搜而不是死守原来写的搜索方案。不过 ReAct 也有显而易见的短板每一步都要模型决策一次步骤一多模型调用次数和 token 消耗都会涨得很厉害。长任务执行到中段早期计划早就淡出上下文视野了执行逻辑很容易被中间某一步的噪声带偏。1.2 Plan-and-Execute 的本质先有地图再出门Plan-and-Execute 是对 ReAct 那种“每步都要现想”的修正思路。它分成两个模块Plan规划模块和 Execute执行模块。规划模块先把大目标拆成有序的小步骤通常是以 markdown 列表或结构化 JSON 输出的子任务清单执行模块再按清单一项项完成而不是每一步都回头问大模型“下一步干嘛”。这个模式解决的是任务执行的“整体感”问题。ReAct 适合沿途随机应变但路径一旦长它很容易走着走着就忘了最初这次任务要解决什么问题最后收在一个局部最优的策略上。Plan-and-Execute 相当于提前把地图铺开执行的人手里拿着清单不会因为中途一个岔路口就跑到完全不相干的地方去。它在工程上的实现对计算资源也更友好。清单里的每一步都不需要重新对全局做高代价推理执行模块只做当前子任务的细节处理。代价是灵活性下降如果执行过程中发现步骤 A 根本不需要或者出现了完全没预料到的新信息原始计划就很难快速调整。所以很多工程实现会给它配备动态更新计划的机制而不是让计划彻底“死掉”。1.3 Reflection 的本质给 Agent 配一个质检员Reflection反思不只是让它回头看看自己的输出而是把“生成”和“评价”拆成两个阶段的结构化循环。第一轮让生成器交出初稿第二轮让评估器从目标契合度、事实准确性、约束满足程度等维度挑毛病再把毛病连同初稿一起喂回给生成器去重写循环往复直到评估器认为合格。这个思路的源头其实很朴素让一个模型直接“一次写对”是很难的但如果让模型在已知评估标准下自查质量上限会提高不少。Reflection 可以有两种落地形态一种是用两个不同的模型分别扮演生成器和评判器另一种是同一个模型通过不同提示词在两个角色间切换。前者效果通常更稳但成本高后者实现简单适合预算有限的中小项目。这套模式解决的核心问题是模型输出的“自以为是”。LLM 单次生成往往不会主动质疑自己的答案是否符合约束条件也不会反复检查计算过程。Reflection 把“检查”从隐性的自我修正变成了显式动作等于强行给模型装了一道质检闸门。缺陷是如果评判标准不清晰或者反思轮数不受控容易陷入重复修改同一处错误、甚至把本来没错的地方越改越糟的死循环。2. 三套模式各自解决了什么核心痛点2.1 ReAct 解决的核心痛点工具调用场景下的反馈断裂在没有 ReAct 这类机制之前让模型调用外部工具通常走的是“一次性指令”路线用户说“查一下天气”模型生成一条函数调用工具返回结果模型再把结果整理成回答。这个流程在单次工具调用时很顺一旦任务需要连续调用多个工具就出现一个明显问题工具返回的中间结果没有地方被“消化”和“再思考”。举一个检索场景的例子。你的任务是了解某个开源库的报废接口如何迁移理想路径是先看官网文档、再查 GitHub 里的迁移说明、再去社区帖子确认兼容性。没有 ReAct 时模型很可能只调了官网文档就回答用户因为它并不理解“一份文档对问题的解释还不够需要横向对比其他信息源”。ReAct 把推理轨迹显式地写进对话历史模型看到官网文档只讲了旧接口的替换方式却没说明边界情况下一步自然会把“查迁移 issue”当作新的 action 继续执行。所以 ReAct 解决的核心痛点是“反馈断裂”——工具返回的数据没有被推理层继续利用导致 Agent 只能做单回合工具调用做不了多回合深度调研。它把工具调用串成了有上下文记忆的对话让模型可以看见自己之前每一步做了什么、结果如何、为什么还要继续做。2.2 Plan-and-Execute 解决的核心痛点长任务的计划丢失与成本失控ReAct 在多步骤任务里有一个致命伤它的“计划”散落在对话历史的每一步推理里而不是集中存在一个统一结构里。这意味着每一步都要大模型重新从历史中理解“现在在哪、还剩哪些事”推理负担重token 消耗也高。步骤一多前面的计划信息会被后续内容挤占注意力模型慢慢就只关注最近几步了俗称“计划丢失”。Plan-and-Execute 等于把“规划”这件事从执行流里显式拎了出来。计划存在于一个独立的数据结构里每一步执行器只需要读取当前子任务完成即可不需要全局回想。这极大降低了执行步骤对上下文窗口的占用让 Agent 面对 30 步、50 步的长流程也不会因上下文太长而忘了初始目标。成本也是很现实的考量。ReAct 每步都得完整调用一遍强模型让它基于全量历史做决策调用Plan-and-Execute 只有规划阶段需要全局模型参与后续执行阶段可以换成轻量模型或固定流程处理。很多生产级系统最终把长流程收敛成“规划 工具执行 人工兜底”预算能压到一个很舒服的水平核心原因就是这个。2.3 Reflection 解决的核心痛点一次性输出的质量不稳定和不可控正常用 LLM 的流程是“输入提示词得到输出交付用户”这只在任务简单、容错率高的情况下成立。一旦输出质量直接影响后续工序比如自动生成代码、生成测试用例、写产品方案初稿直接输出就会有风险。模型可能在回答中遗漏前置约束、引用不存在的 API或者给出了自洽但事实错误的结论。Reflection 把这类风险显式地变成可控流程初稿出来后评估器根据 check-list 检查“是否覆盖所有需求点”“是否有事实错误”“代码风格是否一致”发现一处就标记一处再带着标记返回重写。某开发者曾分享过一个很直观的数据在某个模拟知识库问答项目里不加反思时回答中“看似合理但实际检索无结果”的比例约 8%加了单轮 Reflection 后这个比例降到 2% 以下。这套机制解决的核心痛点是 LLM 输出质量的“黑盒性”。普通调用你永远不知道这次生成是质量好还是坏只能抽查或靠人工回头改。Reflection 相当于把“质量门禁”前置到了生成循环里让系统对输出的最低质量有了一个可量化的兜底。3. 三者的对比、选型逻辑和常用组合3.1 一张表看清差异对比维度ReActPlan-and-ExecuteReflection核心思想推理与行动交替推进先规划后执行生成后自我评估与重写核心动作推理 - 工具/行动 - 观察拆解计划 - 按序执行初稿 - 评估 - 修正对上下文占用较高每步都写推理痕迹较低执行阶段只读局部任务中需要保留初稿和修改记录模型调用次数与步骤数几乎成正比一次规划 每步执行生成轮数 x 2生成评估适合任务探索型、强交互型任务长流程、步骤清晰的任务质量要求高、可check的任务主要风险长任务规划丢失、成本高计划僵化、应对变化弱反思循环不收敛、误改正确内容这张表是选型时的速查基准但实际工程里很少有人只用其中一种基本都是两两组合。3.2 按任务类型选型别盲目往上堆模式我见过不少团队在刚接触这三种概念时恨不得把三个全塞进 Agent 里结果系统变得又慢又贵。选型的正确顺序不是“先进程度”而是“痛点来源”。如果你的任务属于探索型比如别让用户提问时并不清楚答案在哪个数据源里也可能要连续试好几轮才能找到那优先选 ReAct。因为它天然适合在不确定环境里通过观察结果逐步逼近目标。反过来如果任务本身就是确定的多阶段流程比如“取数据 - 清洗 - 做表 - 写总结”就适合 Plan-and-Execute 起步直接把阶段拆清楚每一步的处理逻辑写实一点反而少掉很多不必要的模型调用。只有一种情况必须加 Reflection输出将被下游继续处理或直接交付用户质量事故会影响后续链路。代码提交前、报告生成、测试用例编写、结构化数据抽取这类场景加反思是低成本提高稳定性的办法。但如果是闲聊型任务、或只需要快速一个可行答案的场景单轮生成往往更合适不要为了用而用。3.3 工程里最常用的组合ReAct Reflection 与 Plan-and-Execute Reflection单纯的 ReAct 或者 Plan-and-Execute 都缺少对输出质量的显式校验所以业内最常看到的组合其实是在前两者之上叠一层 Reflection。在 ReAct 循环里加反思一般有两种插法。第一种是插在整轮循环结束后把最终答案连同完整的观察记录交给评价器检查第二种是插在关键子任务之间比如工具返回了金额相关的数据先让一个校验逻辑确认数字相加对得上再继续下一步。第二种更像“阶段质检”适合数据敏感型项目。在 Plan-and-Execute 里加反思我建议放在两个位置计划阶段结束后先让反思模块审查一遍计划本身的合理性看看有没有漏步骤、顺序是否颠倒执行阶段结束后再对整体产出做一次最终评价。计划级的反思能防止“计划本身就有问题却硬着头皮执行下去”结果级的反思则保证最终输出达到交付标准。这样一套组合下来长任务的稳定性会明显高于单模式方案。4. 关键实现细节与实操记录4.1 定义清晰的反思评估标准Reflection 最容易被低估的地方在于评估标准。如果你只是给模型一句“请检查一下答案是否正确”它大概率会给出模糊评价——比如“整体看来可以”或者“建议补充一些细节”这种评价对重写毫无帮助。实践中我会用可验证的 check-list 替代模糊指令。比如在做数据抽取任务时反思提示词里会写明“检查抽取结果是否覆盖原文中全部价格字段检查总金额字段是否等于所有分项之和检查时间格式是否统一为 YYYY-MM-DD检查是否有任何字段值是凭空生成的”。每条都是可判定的评估器能给出明确“过/不过”的结论而不是模棱两可的意见。如果评估结果是“不过”给生成器的修正提示不能只是把评价原文粘回去最好是结构化成“错误定位 依据 期望修正方向”三段式。这样生成器才知道具体改哪里而不是在整篇重写时又自我发挥一遍。4.2 给 Reflexion 设置轮次上限和防抖机制Reflection 的循环在真实系统里很容易陷入不收敛评估器总能在输出里挑出点小毛病生成器每改一遍引入新问题结果两边循环到天荒地老。工程上必须设置硬性轮次上限一般 2 到 3 轮就够了。超过上限还不满意就把当前版本和评估意见一起走人工兜底而不是继续烧 token。更精细的做法是防抖记录每一轮具体的修改点如果第 3 轮提出修改的地方在第 1 轮已经被考虑过并且第 2 轮还被改回来过就说明评估器逻辑不稳定应立即终止。这个逻辑写起来不复杂但能省下大量无效计算。我实际跑某代码修复类模拟项目单轮反思的效果提升最大第二轮只增加了约 10% 的通过率耗时却翻倍第三轮基本是负收益。所以反思轮数不是越多越好两轮通常就是收益与成本的平衡点。4.3 组合模式下一个最小可复现的流程骨架这里给一个简化版的组合思路把 Plan Execute Reflection 串在一个循环里。用伪代码表达方便你迁移到自己的 Agent 框架里def run_agent(task, planner, executor, evaluator): # 阶段一规划 plan planner.generate(task, formatjson) assert_valid_plan(plan) # 阶段二计划级反思发现明显缺失立即回滚重规划 plan_review evaluator.review_plan(plan, task) if plan_review.has_issue: plan planner.revise(task, plan, plan_review.feedback) # 阶段三按计划执行当前子任务结果放在子上下文里 results [] for step in plan[steps]: step_result executor.run(step, contextresults[-3:]) results.append(step_result) # 阶段四输出级反思与重写 output compose_final_answer(results) for _ in range(2): # 硬上限轮次 review evaluator.review(output, task, results) if review.passed: break output writer.revise(output, review.feedback) return output这段流程骨架的关键点在于规划模块和执行器不在同一个上下文里共享全部消息执行器只看得见自己的子任务和前两步结果避免上下文膨胀评价器独立读取完整输出和原始任务要求给出结构化意见。凡是重规划、反思这类“判断型”工作都交给强模型执行器在模型能力足够时可以换成小参数模型处理简单工具调用。4.4 上下文设计与工具定义的实操细节执行阶段最大的工程隐患是上下文污染。ReAct 模式把推理和行动杂糅在同一段历史里一旦某个工具返回了超长数据后面几步的推理质量都会被带垮。我的做法是把“观察数据”按类型做裁剪结构化数据保留字段摘要而不是完整原样塞进对话长文本用检索后的 top-k 片段替代全文。工具定义也直接影响模式效果。工具描述一定要写清楚“这个工具能做什么、不能做什么、输入参数的限制是什么”。尤其要写明边界比如一个搜索工具的作用范围只覆盖 2023 年之后的文档如果描述里没写规划器很可能把它放进一个需要历史数据的任务里。工具调用参数名最好使用稳定的语义命名别用 a、b 这种无意义缩写否则模型容易在推理时混淆参数用途。5. 高频问题与排查技巧实录5.1 反思永远说“没问题”但输出确实有错这是 Reflection 落地最常见的坑。排查方向基本是评估提示词约束不足。评估器和生成器共用同一个模型的权重时它会存在同样的盲区让它挑自己盲区里的错自然挑不出来。试着换一个不同风格的模型当评估器或者用对比视角触发自查“请找出回答中与原文事实冲突的句子逐个引用原文说明”。另外一个实用技巧是把反思结果从“好不好”改成“怎么做会更好”。给出改进方向的任务里模型更容易输出具体修改点而不是抽象的“整体可以”。5.2 计划执行到一半发现前提变了Plan-and-Execute 的经典困境是计划刚生成时信息不全执行到后续步骤时发现某个前置条件已经违反整个计划报废。别把计划视为不可变的铁律把它当“阶段性路线图”。排查优先做两件事第一在执行器的输出里加入状态检查字段每次子任务完成后返回一个“此步骤结果是否符合预期”的布尔值第二规划模块接收所有步骤的状态快照一旦某两步连续异常就触发重新规划。重新规划不是全部重来而是从当前进度处保持已完成步骤的结果只对剩余步骤重新排期这样能大幅减少重执行成本。5.3 执行轮数太多上下文窗口塞满了上下文超限往往出现在 ReAct 或 Reflection 这种多轮交互型实现里。根本原因是历史信息是全量保留没有做阶梯式归档。建议把上下文分为三层执念层目标、约束、用户原始意图、滚动层最近 3 到 5 轮的推理与工具结果、归档层更早记录的摘要信息。每轮结束时把超过滚动窗口的旧轮次压缩成一段“已完成动作摘要”摘要要保留动作结论和关键数值丢弃完整推理文字与工具返回原文。下轮模型既能看到全局进展又不会被无关细节刷掉注意力。5.4 评估器总是漏掉“隐含约束”有种反直觉的情况Reflection 评估器会把用户明说的要求全部打勾但漏掉隐含的“应该做但没明说”的约束。比如生成 SQL 的任务明说要求是找出销量最高的商品隐含要求是该查询必须在不超过 N 秒内返回评估器只检查了 SQL 逻辑正确没检查有没有做无效的全表笛卡尔积。应对办法是把这类隐含约束显式化成评估 checklist 的固定项并在规划阶段就提示规划器如果任务描述里出现性能、安全、格式相关字眼必须在计划中单独列出对应执行步骤。不要指望模型无中生有地发现你心里想但没说出来的规则。5.5 生产中为了对输出负责要保留“反思轨迹”一旦 Agent 进入生产链路反思循环往往也要被审计。别只保留最终输出把初稿、每轮反思意见、每轮修改差异都写到日志里。这样输出的质量评估不再是黑盒出问题时也能快速定位是生成环节出了幻觉还是评估环节漏了标准。我在实际操作中发现把反思轨迹暴露在调试面板里还有一个好处人能很清楚地看到“Agent 改对了几次、误改了几次”这比单纯看一个通过率更能判断模型是否真正理解任务。最后再分享一个实用建议如果你正在设计一个新的 Agent 系统不要一开始就想“要用哪种模式”。先把任务拆开看哪部分是探索型、需要试错哪部分是流程型、步骤固定哪部分是交付型、质量要求高。探索部分给 ReAct流程部分做 Plan-and-Execute交付前加 Reflection。三者的边界清楚之后你的系统不是“用了哪些模式”而是把每种模式放到了它最擅长解决的那类痛点上整体会稳定很多。