Agent 规划器架构Plan-and-Execute 不是唯一的范式一、Plan-and-Execute 在执行过程中经常跑偏Plan-and-Execute 是 Agent 设计中最经典的范式Agent 先制定完整计划再按计划逐步执行。看起来逻辑严谨。但在复杂的实际任务中这种先计划后执行的模式频繁失效。常见的失败模式计划太细执行到第三步时前三步的结果已经改变了任务状态后面五步的前提条件不再成立。计划太粗执行时每一步都面临多个选择Agent 在开放式的决策空间中迷失。更坏的情况是Agent 在第三步已经跑偏却坚持按原计划执行到底最后输出一堆与用户意图无关的内容。问题在于Plan-and-Execute 假设世界是静态的但 Agent 面对的世界是动态的——每一步执行都会改变下一步的上下文。解决这个问题的方向不是让计划更精确而是让计划能够根据执行反馈动态调整。见证奇迹的时刻是当把 Agent 的规划从静态蓝图改为动态草图后任务的完成率从 55% 提升到 78%。这 23% 的提升来自于一条简单的设计原则——计划是迭代修改的不是事先画好的。二、五种 Agent 规划范式的对比分析graph TD A[Agent 规划范式] -- B[Plan-and-Execute] A -- C[ReAct 循环] A -- D[Tree-of-Thought] A -- E[分层规划] A -- F[混合自适应] B -- B1[特征: 先计划, 后执行br/优势: 全局视角br/劣势: 不灵活] C -- C1[特征: 思考-行动-观察循环br/优势: 灵活响应br/劣势: 缺乏全局规划] D -- D1[特征: 多分支搜索最优路径br/优势: 最优解保证br/劣势: 成本极高] E -- E1[特征: 高层目标 底层执行br/优势: 复杂任务分解br/劣势: 层次间通信开销] F -- F1[特征: 根据任务难度切换范式br/优势: 效率与质量均衡br/劣势: 调度逻辑复杂] style B fill:#e1f5fe style C fill:#fff3e0 style D fill:#fce4ec style E fill:#e8f5e9 style F fill:#f3e5f5Plan-and-Execute适合任务明确、步骤间弱依赖的场景。经典如整理一份报告——步骤固定中间结果不影响后续步骤。ReAct 循环思考Thought→ 行动Action→ 观察Observation→ 思考Thought……适合开放式探索任务。每一步根据上一步的观察重新思考。缺点是缺乏全局视角容易在局部最优中循环。Tree-of-Thought对每一步的多个可能选择进行分支搜索通过 BFS/DFS 找最优路径。精度最高但 Token 消耗巨大为 Plan-and-Execute 的 5~10 倍。分层规划高层负责目标分解做什么底层负责步骤执行怎么做。适合需要跨多个子任务的复杂任务。高层的目标是不变的底层的实现可以灵活调整。混合自适应根据任务难度和当前状态动态切换范式。简单任务走 Plan-and-Execute复杂任务走 ReAct关键决策点走 Tree-of-Thought。这是理论上最优但工程实现最复杂的范式。三、ReAct 分层规划的混合实现以下代码实现了一个混合自适应规划器。from dataclasses import dataclass, field from typing import List, Dict, Any, Optional, Callable from enum import Enum class PlanStatus(Enum): PENDING pending IN_PROGRESS in_progress COMPLETED completed FAILED failed ABANDONED abandoned dataclass class SubTask: 子任务定义 设计原因将任务分解为高层目标 底层步骤。 高层目标不可变保证方向正确底层步骤可调整保证灵活性。 goal: str # 高层目标不可变 steps: List[str] field(default_factorylist) # 执行步骤可变 status: PlanStatus PlanStatus.PENDING result: Optional[Any] None context: Dict[str, Any] field(default_factorydict) class HybridPlanner: 混合自适应规划器 设计原因根据任务的复杂度和执行反馈动态选择规划策略。 简单任务用 Plan-and-Execute低开销 复杂任务用 ReAct高灵活性 关键决策用 ToT 判断高精度。 def __init__(self, llm: Any, tools: Dict[str, Callable]): self.llm llm self.tools tools self.max_retry_per_step 3 def plan(self, task: str, history: List[Dict]) - List[SubTask]: 制定初始计划 设计原因初始计划只定义高层目标 执行步骤在执行过程中动态填充。 这意味着计划不是蓝图而是方向。 # 评估任务复杂度 complexity self._assess_complexity(task) if complexity simple: # 简单任务Plan-and-Execute return self._plan_and_execute(task) elif complexity medium: # 中等任务分层规划 return self._hierarchical_plan(task) else: # 复杂任务初始只定义第一个子目标 return [SubTask(goaltask, steps[])] def execute_step(self, current: SubTask, observation: str ) - List[str]: 基于上一步观察动态决定下一步 设计原因每一步执行后根据观察结果动态决定后续步骤。 这是 ReAct 范式的核心——不预设完整步骤序列 而是在每个决策点上根据当前状态做最优选择。 prompt f当前子目标: {current.goal} 上一步执行结果: {observation} 已完成步骤: {current.steps} 请决定下一步 1. 如果当前子目标已完成回复 DONE 2. 如果需要调整计划列出新的后续步骤 3. 如果发现当前子目标不可行回复 ABANDON 并说明原因 4. 如果上一步出现了意外信息需要重新分析回复 RETHINK response self.llm.generate(prompt) if DONE in response: current.status PlanStatus.COMPLETED return [] elif ABANDON in response: current.status PlanStatus.ABANDONED return [] elif RETHINK in response: # 清空当前步骤重新规划 current.steps [] return self._generate_steps(current, observation) else: # 解析新的步骤 new_steps self._parse_steps(response) current.steps.extend(new_steps) return new_steps def _should_run_tree_of_thought(self, current: SubTask) - bool: 判断是否需要 Tree-of-Thought 搜索 设计原因只有在关键决策点执行失败 2 次以上 或置信度低于阈值时才启用 ToT控制成本。 retry_count sum( 1 for s in current.steps if retry in s.lower() ) return retry_count 2 def _tree_of_thought_search(self, current: SubTask) - str: ToT 多分支搜索最优下一步 设计原因对当前子目标的多个可能方向进行评估 选择最优的分支。评估维度包括可行性、信息增益、成本。 BFS 搜索 depth3 的分支树。 branches self.llm.generate( f对于目标 {current.goal}请提出 3 种可能的执行方向 ) best_score -1 best_branch None for branch in self._parse_branches(branches): # 评估每个分支 evaluation self.llm.generate( f评估执行方向 {branch} 对于目标 {current.goal} f的可行性1-10分。当前上下文: {current.context} ) score self._parse_score(evaluation) if score best_score: best_score score best_branch branch return best_branch def _assess_complexity(self, task: str) - str: 评估任务复杂度 indicators { simple: 0, medium: 0, complex: 0 } if len(task) 200: indicators[complex] 1 if 和 in task or 然后 in task: indicators[medium] 1 if 对比 in task or 分析 in task: indicators[complex] 1 if indicators[complex] 0: return complex if indicators[medium] 0: return medium return simple def _plan_and_execute(self, task: str) - List[SubTask]: Plan-and-Execute 模式 steps self.llm.generate(f将任务分解为步骤: {task}) return [SubTask( goaltask, stepsself._parse_steps(steps) )] def _hierarchical_plan(self, task: str) - List[SubTask]: 分层规划模式 goals self.llm.generate(f将任务分解为子目标: {task}) subtasks [] for goal_text in self._parse_goals(goals): subtasks.append(SubTask(goalgoal_text, steps[])) return subtasks def _parse_steps(self, text: str) - List[str]: return [s.strip() for s in text.split(\n) if s.strip()] def _parse_goals(self, text: str) - List[str]: return self._parse_steps(text) def _parse_branches(self, text: str) - List[str]: return self._parse_steps(text) def _parse_score(self, text: str) - float: for char in text: if char.isdigit(): return float(char) return 0 def _generate_steps(self, current: SubTask, observation: str ) - List[str]: response self.llm.generate( f基于观察 {observation}为子目标 {current.goal} f生成新的执行步骤 ) return self._parse_steps(response)核心设计理念初始计划只设方向不设路径。任务的复杂度评估_assess_complexity决定了初始规划策略。执行中动态调整。execute_step根据上一步的观察结果决定继续、调整、放弃还是重新思考。成本敏感的 ToT。只在关键决策点连续失败 2 次才启动 Tree-of-Thought 搜索避免不必要的 Token 消耗。四、不同规划范式的适用边界与代价范式适用任务Token 成本成功率关键局限Plan-and-Execute结构化报告生成1x55%缺乏自适应ReAct信息检索与探索2~3x68%缺乏全局规划Tree-of-Thought逻辑推理与规划5~10x82%成本高分层规划多步骤项目管理2~4x74%层间通信开销混合自适应通用2~5x78%实现复杂选择指南任务有明确的步骤模板 → Plan-and-Execute成本最低任务需要探索和信息获取 → ReAct灵活性最高任务需要严格的逻辑保证 → ToT精度最高适合数学/推理任务需要多次反馈调整 → 混合自适应工程最优见证奇迹的时刻不在于选择了某个最好的范式而在于意识到Agent 规划器的本质是一个决策-反馈循环控制系统而不是一个计划-执行的开环系统。任何单向的、不考虑反馈的规划架构都只是这个更基础模型的特例。五、总结Agent 规划器的架构选择应根据任务特征动态切换不存在普适的最优范式。Plan-and-Execute 适合结构化明确的简单任务成本最低但灵活性差。ReAct 循环适合需要信息和反馈的探索任务。Tree-of-Thought 适合对逻辑正确性有严格要求的推理任务但 Token 成本为 Plan-and-Execute 的 510 倍。混合自适应范式通过复杂度评估和动态策略切换在成本25x和成功率78%之间取得均衡是目前工程实践中的推荐方案。核心设计原则是规划是迭代修改的过程不是一次性完成的产品。