Agent 的决策与规划说白了就是让大模型从“会聊天”进化到“会办事”的那层骨架。我接触过不少团队模型接口调得飞起Prompt 写得花里胡哨但一到多步骤任务就露馅——要么中途跑偏要么反复绕圈要么做完一步不知道下一步该干嘛。问题往往不在模型本身而在于缺少一套明确的决策与规划机制。ReAct、Plan-and-Execute、Reflexion、Tree of Thoughts 这四个范式基本覆盖了当前 Agent 规划能力的主流思路搞懂它们的差异和适用边界比盲目堆工具链有用得多。这篇内容适合正在做 Agent 落地、被多步任务折磨过的开发者也适合想系统理解 Agent 决策层设计的产品和技术负责人。1. 四个范式的整体定位与选型逻辑1.1 先搞清楚它们各自解决什么问题很多人把这四个概念混在一起谈其实它们处在不同的抽象层级。我用一个生活化的类比来说明假设你要装修一套房子。ReAct 像是边干边想的施工队——刷墙的时候发现墙面不平停下来想想怎么处理处理完继续刷。它的核心是“推理”和“行动”交替进行每一步都基于当前观察做决策。Plan-and-Execute 像是先出图纸再施工——先把整个装修方案定下来拆成水电、泥瓦、木工、油漆几个阶段然后按计划逐个执行。它的核心是先规划后执行规划阶段和执行阶段分离。Reflexion 像是完工后复盘——装完之后发现某个插座位置不对反思一下为什么当初没考虑到把教训记下来下次装修避免。它的核心是自我反思与经验积累。Tree of Thoughts 像是同时出好几套方案做对比——客厅隔断是做开放式还是半开放式还是砌墙每种方案往下推演几步评估哪条路最优再定。它的核心是探索多条推理路径并择优。这四个范式不是互斥的实际项目里经常组合使用。比如用 Plan-and-Execute 做顶层规划每个子任务内部用 ReAct 执行关键节点用 Reflexion 做质量把关遇到需要创意决策的环节用 Tree of Thoughts 展开探索。1.2 选型的三个关键判断维度选哪个范式我一般看三个维度任务复杂度。单步能搞定的任务不需要规划框架直接调模型就行。2-5步的任务用 ReAct 足够。5步以上、有依赖关系的任务考虑 Plan-and-Execute。需要探索多种可能性的开放性问题才上 Tree of Thoughts。容错要求。如果一步错步步错、代价很高那 Reflexion 的反思机制就很有必要。如果任务本身容错率高、重试成本低可以省掉反思环节直接用 ReAct 快速迭代。Token 预算。这是最容易被忽视的。Tree of Thoughts 因为要展开多条路径Token 消耗可能是 ReAct 的 5-10 倍。Plan-and-Execute 的规划阶段也要额外消耗。如果预算紧张优先考虑 ReAct 这种轻量方案。下面这张表是我自己总结的选型对照可以直接参考范式核心机制适用任务类型相对Token消耗实现复杂度ReAct推理-行动交替中等复杂度、需外部工具1x低Plan-and-Execute先规划后执行多步骤、有依赖关系1.5-2x中Reflexion执行后反思迭代高质量要求、可重试2-3x中Tree of Thoughts多路径探索择优开放性问题、需创意5-10x高注意这张表的 Token 倍数是基于我实际项目中的粗略统计具体数值会因任务类型、模型能力、Prompt 设计差异很大不要当成精确基准只作为量级参考。1.3 为什么不能只用一种范式打天下我见过一些团队学了 ReAct 之后所有 Agent 都用 ReAct结果遇到需要长程规划的任务就崩。也见过一上来就上 Tree of Thoughts 的Token 账单直接爆炸效果还不一定好。核心原因是不同任务的决策结构本质不同。有些任务是线性的做完A做B有些是树状的从A出发有多个分支有些是循环的做A→检查→不达标→重做A。用同一种范式去套所有结构就像用一把螺丝刀拧所有螺丝能拧但效率低。我的建议是先把 ReAct 吃透它是基础。然后在实际项目中识别出 ReAct 搞不定的场景再针对性引入其他范式。不要为了用而用。2. ReAct 范式的核心机制与实操要点2.1 ReAct 到底在做什么ReAct 这个名字来自 Reasoning Acting核心思想是让模型在每一步都先输出一段推理Thought然后决定采取什么行动Action执行后获得观察结果Observation再进入下一轮推理。这个循环一直持续到任务完成。它的 Prompt 结构通常长这样你可以使用以下工具 - search(query): 搜索信息 - calculate(expression): 计算表达式 - finish(answer): 提交最终答案 请按以下格式回应 Thought: 你的推理过程 Action: 工具名(参数) Observation: 工具返回结果 ...重复 Thought: 我现在知道最终答案了 Action: finish(答案)这个格式的关键在于强制模型显式输出推理过程。不输出推理直接给答案模型容易跳步输出了推理相当于让它“把草稿纸摊开”错误率会明显下降。2.2 工具设计是 ReAct 的命门ReAct 的效果一半取决于模型能力一半取决于工具设计。我踩过最大的坑就是工具粒度没把握好。工具太粗比如只给一个do_everything(task)那模型没法精细控制等于没给工具。工具太细比如给二十个原子操作模型选择困难容易选错。我的经验是工具数量控制在 3-7 个每个工具职责单一但有一定抽象层级。比如做数据分析 Agent工具可以是query_database、run_python、plot_chart、finish。不要细到add_column、filter_rows这种也不要粗到analyze_data这种。工具的描述也极其重要。模型靠描述来判断什么时候用哪个工具。描述要写清楚这个工具做什么、什么时候用、参数是什么格式、返回什么。我一般会这样写run_python(code: str) - str 执行一段 Python 代码并返回输出。 适用场景需要进行数值计算、数据处理、字符串操作时。 不适用场景需要查询数据库时请用 query_database。 参数 code 必须是完整的可执行 Python 代码不要包含 markdown 代码块标记。2.3 ReAct 的循环控制与终止条件ReAct 最容易出的问题是死循环——模型反复调用同一个工具或者在一个错误方向上打转。必须设置硬性终止条件。我一般设三重保险最大步数限制。根据任务复杂度设 10-20 步超过就强制终止并返回当前最优结果。重复检测。如果连续 3 步的 Action 和参数完全相同判定为循环强制中断。无进展检测。如果连续若干步的 Observation 没有带来新信息比如搜索结果一直是同样的内容触发终止。代码层面大概是这样max_steps 15 repeat_threshold 3 history [] for step in range(max_steps): thought, action model.predict(history) # 重复检测 if len(history) repeat_threshold: recent [h[action] for h in history[-repeat_threshold:]] if all(a action for a in recent): return 检测到循环终止执行 observation execute_action(action) history.append({thought: thought, action: action, observation: observation}) if action.startswith(finish): return observation实操心得最大步数不要设太大。我试过设 30 步结果模型在第 25 步还在瞎折腾白白烧 Token。后来改成 12 步反而逼着模型更高效地利用每一步。步数限制本身就是一种“压力”能让模型更珍惜每次决策机会。2.4 ReAct 的 Prompt 调优细节几个我实测有效的技巧在系统提示里给一两个完整示例。Few-shot 对 ReAct 效果提升很明显尤其是格式遵循度。示例要覆盖“正常完成”和“遇到错误后调整”两种情况。明确禁止某些行为。比如“不要在没有调用工具的情况下直接给出最终答案”、“不要在 Thought 里编造 Observation”。这些负面约束能减少很多奇怪输出。Thought 部分引导模型做结构化思考。不要只说“请推理”而是说“请分析当前已知什么、还缺什么、下一步最该做什么”。这样推理质量会高很多。3. Plan-and-Execute 的规划层设计3.1 为什么需要把规划和执行分开ReAct 是“走一步看一步”短任务没问题但长任务容易迷失。Plan-and-Execute 的思路是先让模型站在全局视角把任务拆解成步骤列表然后逐步执行执行时可以参考全局计划。这个分离带来两个好处一是规划时模型能看到完整任务拆解更合理二是执行时可以针对单个步骤优化不用每步都重新理解整个任务。但代价是计划可能过时。执行到第三步发现实际情况和规划时假设的不一样原计划就不适用了。所以 Plan-and-Execute 必须配套一个重规划机制。3.2 规划 Prompt 的设计要点规划阶段的目标是产出一个可执行的步骤列表。我的 Prompt 模板大概是这样你是一个任务规划器。请将以下任务拆解为可执行的步骤列表。 任务{task} 要求 1. 每个步骤必须是一个明确的、可独立执行的动作 2. 步骤之间如果有依赖关系请标注 3. 步骤数量控制在 3-8 个不要过细也不要过粗 4. 输出格式为 JSON 数组每个元素包含 step_id, description, depends_on 请输出规划结果这里有几个细节值得说步骤数量限制。不限制的话模型可能拆出 20 步执行起来又慢又容易出错。3-8 步是个比较舒服的区间。依赖关系标注。有些步骤可以并行有些必须串行。标注了依赖关系执行器就能做并行优化。JSON 格式约束。自然语言的计划不好程序化处理强制 JSON 能让后续执行更稳定。但要注意有些模型 JSON 输出不稳定需要加校验和重试。3.3 执行器的设计拿到计划后执行器逐个执行步骤。每个步骤的执行可以是一个独立的 ReAct 循环也可以是一次简单的模型调用取决于步骤复杂度。执行器需要处理几种情况步骤成功。记录结果继续下一步。步骤失败。重试若干次如果还失败触发重规划。步骤结果与预期不符。比如规划时假设能查到某个数据实际查不到。这也触发重规划。重规划的 Prompt 要把已完成步骤、当前失败情况、原计划都带上让模型基于新信息调整后续步骤原任务{task} 原计划{original_plan} 已完成步骤及结果{completed_steps} 当前遇到的问题{problem} 请基于以上信息重新规划剩余步骤。已完成且成功的步骤不要重复。3.4 Plan-and-Execute 的常见坑坑一规划过于理想化。模型规划时不知道实际工具的能力边界可能规划出无法执行的步骤。解决办法是在规划 Prompt 里把可用工具及其限制说清楚。坑二步骤粒度过细。拆成十几个微步骤每步都要调一次模型成本和延迟都上去了。我的经验是如果一个步骤用一次工具调用就能完成那它就是一个合适的粒度。坑三重规划过于频繁。一遇到小问题就重规划导致计划反复变动执行不稳定。应该设置重规划阈值比如只有连续失败 2 次或关键步骤失败才触发。实操心得我习惯在规划完成后加一个“计划校验”环节用一个独立的模型调用检查计划是否合理——步骤是否完整、依赖是否有环、是否有无法执行的步骤。这个校验环节成本很低但能拦掉不少低级错误。4. Reflexion 的反思机制与迭代策略4.1 Reflexion 的核心把失败变成经验Reflexion 的思路很直观任务执行失败后让模型反思失败原因把反思结果存起来下次执行时作为参考。它模仿的是人类“吃一堑长一智”的学习方式。一个完整的 Reflexion 循环包含三个阶段执行用当前策略尝试完成任务评估判断任务是否成功如果失败分析失败原因反思生成一段自然语言的反思存入记忆重试带着反思重新执行关键在于反思的质量。如果反思只是“我失败了下次要更努力”这种废话那毫无价值。好的反思应该是具体的、可操作的比如“我在第二步调用搜索工具时查询词太宽泛导致返回结果不相关下次应该用更具体的关键词”。4.2 反思 Prompt 的设计反思 Prompt 要引导模型做具体归因而不是泛泛而谈任务{task} 执行过程{trajectory} 执行结果{result} 评估任务失败原因是 {failure_reason} 请分析这次失败 1. 具体是哪一步出了问题 2. 为什么会出这个问题是理解错误、工具使用不当、还是策略问题 3. 下次遇到类似情况应该怎么做 请给出具体、可操作的改进建议不要泛泛而谈。我实测下来加上“不要泛泛而谈”这句约束反思质量会明显提升。模型有时候会偷懒给一些正确的废话明确要求具体化能逼它深入分析。4.3 反思记忆的管理反思结果不能无限堆积否则会污染上下文。我一般这样管理按任务类型分类存储。相似任务的反思放在一起执行新任务时只检索相关的反思。设置有效期。反思不是永久有效的模型能力升级或工具变更后旧反思可能不再适用。我一般给反思设一个“使用次数上限”用了几次还没帮助就淘汰。反思要精简。每条反思控制在一两句话太长会占用宝贵上下文。如果反思很多只取最相关的 3-5 条注入。4.4 Reflexion 的适用边界Reflexion 不是万能的。它适合可重试、有明确成功标准的任务。如果任务本身没法判断成功与否或者重试成本极高那 Reflexion 就不适用。另外Reflexion 对随机性失败效果有限。如果失败是因为模型随机性导致的偶发错误反思帮助不大多试几次可能就过了。它真正擅长的是系统性失败——模型在某个环节有稳定的认知偏差通过反思能纠正。注意Reflexion 的迭代次数不要太多。我见过设置 10 次重试的结果模型在反思里越陷越深反而偏离了正确方向。一般 2-3 次迭代就够了超过还没成功说明任务本身可能超出了模型能力该考虑换方案或人工介入。5. Tree of Thoughts 的探索与评估机制5.1 Tree of Thoughts 的本质把推理变成搜索Tree of ThoughtsToT的核心洞察是复杂问题的解决过程不是线性的而是一棵树——每个决策点有多个可能的方向需要探索、评估、回溯。它把推理过程显式地建模为树搜索每个节点是一个“思维”thought代表部分解决方案从节点出发可以生成多个子节点下一步的多个可能用一个评估函数给每个节点打分用搜索算法BFS/DFS决定探索顺序。这跟人类解决难题的方式很像——想几个方案推演一下觉得不行就退回来换一个。5.2 ToT 的四个关键组件思维生成器。给定当前状态生成多个可能的下一步。Prompt 大概是“基于当前进展请提出 3 个不同的下一步方向”。状态评估器。给每个候选状态打分判断它有多大希望通向最终解。可以是模型打分“这个方向有多大可能成功1-10分”也可以是规则判断。搜索策略。BFS 适合宽度优先、需要比较多个方案的情况DFS 适合深度优先、一条路走到底的情况。实际用 BFS 比较多因为能及时剪枝。回溯机制。当某条路径评估分数低于阈值或者走到死胡同就回溯到上一个分支点换一条路走。5.3 ToT 的 Prompt 实现示例一个简化的 ToT 实现大概是这样def tree_of_thoughts(task, max_depth3, branch3): root {state: task, thoughts: [], score: None} frontier [root] for depth in range(max_depth): next_frontier [] for node in frontier: # 生成多个候选 candidates generate_thoughts(node, branch) for cand in candidates: # 评估 score evaluate(cand) cand[score] score if is_solution(cand): return cand next_frontier.append(cand) # 保留得分最高的若干节点 next_frontier.sort(keylambda x: x[score], reverseTrue) frontier next_frontier[:branch] return best_of(frontier)generate_thoughts的 Prompt当前任务{task} 当前进展{current_state} 请提出 {branch} 个不同的下一步方向。每个方向要具体、可执行且彼此有实质差异。 输出格式 方向1... 方向2... 方向3...evaluate的 Prompt任务{task} 当前进展{state} 请评估这个进展方向通向最终解的可能性打分 1-10。 考虑因素方向是否正确、是否可执行、是否有明显障碍。 只输出分数和一句话理由。5.4 ToT 的成本控制ToT 最大的问题是成本。每层展开 branch 个分支深度 d 层总节点数是 branch^d。branch3、depth3 就是 27 个节点每个节点至少两次模型调用生成评估就是 50 次调用。这在生产环境里很难接受。我的控制策略限制分支数和深度。branch 不超过 3depth 不超过 3。超过这个规模收益递减而成本剧增。早停。一旦某个节点评估分数超过阈值比如 9 分直接返回不再探索其他分支。剪枝。评估分数低于阈值的节点直接丢弃不往下展开。只在关键决策点用 ToT。不是整个任务都用 ToT而是在几个关键分叉点用其他环节用 ReAct 或直接执行。实操心得ToT 最适合的场景是“方案设计”类任务——需要从多个角度思考、比较不同方案。对于有明确步骤的任务用 ToT 是杀鸡用牛刀。我一般把 ToT 用在任务开始前的方案探索阶段确定方向后再用 Plan-and-Execute 执行。6. 四种范式的组合与工程落地6.1 一个组合架构的实例实际项目里我常用的组合方式是顶层用 Plan-and-Execute。先把任务拆成阶段。每个阶段内部用 ReAct。阶段内的具体执行走 ReAct 循环。关键决策点用 ToT。遇到需要方案选择的环节展开 ToT 探索。整体用 Reflexion 兜底。如果最终结果不达标触发反思和重试。这个架构的伪代码def agent(task): reflections load_relevant_reflections(task) plan plan_and_execute_planner(task, reflections) for step in plan: if step.requires_exploration: result tree_of_thoughts(step, reflections) else: result react_loop(step, reflections) step.result result final aggregate(plan) if not evaluate(final): reflection reflect(task, plan, final) save_reflection(reflection) return agent(task) # 带反思重试 return final6.2 状态管理与上下文控制多范式组合最大的工程挑战是状态管理。每个范式都有自己的中间状态怎么组织、怎么传递、怎么控制上下文长度都需要仔细设计。我的做法是维护一个统一的状态对象包含任务描述、当前计划、已完成步骤及结果、反思列表、当前执行轨迹。每次调用模型时从这个状态对象里抽取必要信息组装 Prompt而不是把所有历史都塞进去。上下文控制的关键是摘要。执行轨迹太长时把早期步骤压缩成摘要只保留最近几步的详细内容。摘要用模型生成Prompt 是“请用一句话总结这一步做了什么、结果是什么”。6.3 评估与监控Agent 上线后必须有一套评估机制否则你不知道它到底行不行。我一般监控这几个指标指标含义健康范围任务成功率端到端完成的比例因任务而异一般 80%平均步数完成任务的平均步数越少越好突增说明有问题重试率触发 Reflexion 的比例20%平均Token消耗单任务 Token 用量设预算上限超了告警循环检测触发率死循环比例5%这些指标要持续监控一旦异常就排查。比如成功率突然下降可能是模型接口变了也可能是某个工具挂了。6.4 常见问题速查问题Agent 反复调用同一个工具。排查检查工具描述是否清晰、是否设置了循环检测、最大步数是否合理。问题规划出来的步骤无法执行。排查规划 Prompt 里是否说明了工具能力边界、是否加了计划校验环节。问题反思没有效果重试还是失败。排查反思是否太泛、是否检索到了相关反思、任务是否超出模型能力。问题Token 消耗失控。排查是否用了 ToT 但没控制分支数、上下文是否无限增长、是否缺少摘要机制。问题执行结果不稳定同样任务有时成功有时失败。排查模型温度是否过高、是否有随机性环节、是否需要加 Reflexion 兜底。6.5 从简单到复杂的演进路径最后说说落地节奏。我的建议是分阶段演进第一阶段只用 ReAct把工具设计和 Prompt 调优做好。这个阶段能解决大部分中等复杂度任务。第二阶段引入 Plan-and-Execute解决长程任务。重点做好规划 Prompt 和重规划机制。第三阶段加入 Reflexion提升稳定性。重点做好反思质量和记忆管理。第四阶段在关键场景引入 ToT解决开放性问题。严格控制成本。不要跳阶段。我见过直接上 ToT 的团队成本高效果差最后退回 ReAct 重新打基础。每一步都踩实了再往上走反而更快。这套东西我自己也是踩了不少坑才理清楚。最开始觉得 ReAct 万能后来发现长任务不行上了 Plan-and-Execute 又发现计划老过时加了 Reflexion 又发现反思质量参差不齐。每个范式都有它的脾气得在实际项目里慢慢磨。如果你刚开始做 Agent先把 ReAct 的工具设计和循环控制做扎实这一层的收益最大也最不容易翻车。