规划模块是 Agent 智能含量的核心。它决定了 Agent 是「无脑地一步步走」还是「聪明地想清楚再走」。但规划不是越大越好——给一道「1+1」配全套 ReAct + 任务分解,既慢又贵。规划真正的难点,是「该想多深、该走多远、用什么策略」。
回到主循环,Planning 模块每轮都要回答一个问题:「在当前状态下,下一步该做什么?」
输入: Profile + Memory(状态+历史) + 可用工具 ↓ [Planning 规划模块] ↓ 输出: 下一步动作 (调用工具 / 直接回答 / 求助)
注意输出的三种形态:
| 输出形态 | 含义 | 例子 |
|---|---|---|
| 工具调用 | 调用外部工具获取信息或执行操作 | search("财报数据") |
| 直接回答 | 信息已足够,直接生成最终答案 | 「同比 +12%」 |
| 求助/中止 | 判断无解或越界,请求人类介入 | request_human_help |
💡 Planning 不等于「想很多步」。Planning 的本质是决策——决定下一步做什么。它可以是简单的「直接回答」,也可以是复杂的「多步推理后调用工具」。判断「该不该想」本身,就是 Planning 的一部分。
Planning 的第一步不是「想策略」,而是「理解任务」。同一个用户请求,不同建模会导出完全不同的规划。
任何任务都可以拆成三要素:
| 要素 | 含义 | 例子(「帮我分析这家公司」) |
|---|---|---|
| 目标状态 | 任务完成时世界应该是什么样 | 「输出一份完整的分析报告」 |
| 初始状态 | 当前已知什么、有什么资源 | 「公司名已知,有财报工具与股价工具」 |
| 约束 | 时间、预算、行为边界 | 「30 分钟内、不超过 20 步、不给投资建议」 |
Planning 的本质,就是在「约束」下,从「初始状态」走到「目标状态」的路径搜索。
按「路径是否明确」,任务分三类,对应不同规划难度:
| 任务类型 | 路径明确度 | 例子 | 适合的规划 |
|---|---|---|---|
| 确定性任务 | 路径唯一、明确 | 「查昨天的股价」 | 直接调用 |
| 半结构化任务 | 路径有几条、需选 | 「分析这家公司的财务健康」 | CoT / ReAct |
| 开放性任务 | 路径不明确、需探索 | 「给我设计一个增长策略」 | ToT / 任务分解 |
⚠️ 最常见的规划错误是「路径错配」——给确定性任务配复杂规划(浪费),或给开放性任务配简单规划(失效)。Planning 的第一职责是判断任务类型,然后路由到合适的策略。这一步做错,后面再精妙的算法都救不回来。
Planning 不是单一算法,而是一个策略空间。从简单到复杂,主要策略如下:
| 策略 | 思考方式 | 步数 | 代表方法 | 详见 |
|---|---|---|---|---|
| 直接回答 | 不规划,一次性生成 | 1 | Zero-shot | — |
| 思维链 CoT | 把推理过程分步写出来 | 1(但展开思考) | CoT / Self-Consistency | 第 3.1 节 |
| 思维树 ToT | 多条路径并行探索+回溯 | 多步搜索 | ToT / GoT | 第 3.2 节 |
| 任务分解 | 大任务拆成小任务 | 多步 | Decomposed Prompting | 第 3.3 节 |
| ReAct | 思考与行动交替 | 多步 | ReAct / Reflexion | 第 4 章 |
| 先规划后执行 | 一次出完整计划再执行 | 多步 | Plan-and-Execute / ReWOO | 第 3.4 节 |
这六种策略不是互斥的,经常组合使用。例如一个复杂任务可能先「任务分解」拆成子任务,每个子任务用「ReAct」执行,遇到创意环节再用「ToT」探索。
不同策略在三个维度上有本质差异:
<svg viewBox="0 0 720 420" xmlns="http://www.w3.org/2000/svg"> <!-- 坐标轴 --> <line x1="80" y1="360" x2="680" y2="360" stroke="#475569" stroke-width="2"/> <line x1="80" y1="40" x2="80" y2="360" stroke="#475569" stroke-width="2"/> <text x="680" y="380" font-size="13" fill="#475569" text-anchor="end">推理深度 →</text> <text x="60" y="40" font-size="13" fill="#475569" text-anchor="end" transform="rotate(-90 60 40)">↑ LLM 调用次数</text> <!-- 策略点 --> <circle cx="140" cy="320" r="14" fill="#dcfce7" stroke="#16a34a"/> <text x="140" y="324" font-size="11" fill="#14532d" text-anchor="middle" font-weight="bold">直接</text> <text x="140" y="345" font-size="10" fill="#475569" text-anchor="middle">1 次调用</text> <circle cx="240" cy="270" r="14" fill="#dbeafe" stroke="#2563eb"/> <text x="240" y="274" font-size="11" fill="#1e3a8a" text-anchor="middle" font-weight="bold">CoT</text> <text x="240" y="295" font-size="10" fill="#475569" text-anchor="middle">1 次,长推理</text> <circle cx="360" cy="200" r="14" fill="#fef9c3" stroke="#ca8a04"/> <text x="360" y="204" font-size="11" fill="#713f12" text-anchor="middle" font-weight="bold">ReAct</text> <text x="360" y="225" font-size="10" fill="#475569" text-anchor="middle">多步,边想边做</text> <circle cx="500" cy="140" r="14" fill="#fce7f3" stroke="#db2777"/> <text x="500" y="144" font-size="11" fill="#831843" text-anchor="middle" font-weight="bold">分解</text> <text x="500" y="165" font-size="10" fill="#475569" text-anchor="middle">多步,层次化</text> <circle cx="620" cy="80" r="14" fill="#f5e1ff" stroke="#9333ea"/> <text x="620" y="84" font-size="11" fill="#581c87" text-anchor="middle" font-weight="bold">ToT</text> <text x="620" y="105" font-size="10" fill="#475569" text-anchor="middle">多步,树搜索</text> <!-- 趋势线 --> <path d="M 140 320 Q 240 270 360 200 T 620 80" stroke="#94a3b8" stroke-width="1.5" fill="none" stroke-dasharray="4 4"/> <text x="380" y="60" font-size="12" fill="#475569" text-anchor="middle">策略复杂度递增 →</text> </svg>
三个维度:
💡 核心权衡:策略越复杂,能解决的问题越难,但成本与延迟也越高。优秀的 Planning 不是「永远用最复杂的策略」,而是「为每个任务选最小够用的策略」。这是 2.3.4 节策略路由的核心思想。
策略路由(Strategy Routing)是 Planning 模块的「元决策」——在开始规划之前,先决定用哪种规划策略。这是生产级 Agent 与玩具 Agent 的关键分水岭。
一个典型的策略路由决策树如下:
决策树的关键判分点:
| 判分点 | 问题 | 影响 |
|---|---|---|
| 是否需要外部信息 | 任务能靠 LLM 内部知识解决吗? | 决定是否需要工具调用 |
| 路径是否明确 | 解法是唯一的还是开放的? | 决定用线性还是搜索式规划 |
| 步骤多寡 | 任务规模是大是小? | 决定是否需要任务分解 |
| 是否需要创意 | 是否要探索多方案? | 决定是否用 ToT |
策略路由本身可以由三种方式实现:
| 实现方式 | 做法 | 优缺点 |
|---|---|---|
| 规则路由 | 用 if-else 规则判分 | 简单可控,但覆盖不全 |
| LLM 路由 | 让一个小 LLM 先判分任务类型 | 灵活,但增加一次调用 |
| 混合路由 | 规则兜底 + LLM 处理边界 | 生产主流 |
任务 → [路由器] → 任务类型标签 → [对应策略模块] ↑ 规则 + 小 LLM 混合判分
⚠️ 路由的代价:策略路由本身要花一次 LLM 调用(如果用 LLM 路由)。对极简单任务,这次调用的开销可能超过任务本身。生产实践通常用「规则优先 + LLM 兜底」——能靠规则判分的就走规则,判不了的才上 LLM 路由。
除了「用什么策略」,Planning 还有一个根本选择:「先想好再走,还是走一步看一步」。这是规划范式的根本分野。
| 范式 | 思路 | 代表 | 优点 | 缺点 |
|---|---|---|---|---|
| 先规划后执行 (Plan-then-Execute) |
一次性生成完整计划,再逐步执行 | Plan-and-Execute / ReWOO | 总览全局,易并行 | 计划脱离实际时失效 |
| 边规划边执行 (Interleaved) |
每走一步根据观察再决定下一步 | ReAct | 鲁棒,能纠错 | 步数多,延迟高 |
[先规划后执行] 规划: A → B → C → D → E (一次出全部) 执行: A → B → C → D → E (按计划走) 特点: 快,但中途出意外就崩 [边规划边执行] 执行 A → 观察 → 规划 B → 执行 B → 观察 → 规划 C → ... 特点: 慢,但能根据观察动态调整
两种范式各有适用场景:
| 场景特征 | 推荐范式 | 理由 |
|---|---|---|
| 步骤明确、环境稳定 | 先规划后执行 | 计划不易失效,效率高 |
| 步骤不明、环境多变 | 边规划边执行 | 需要观察反馈纠错 |
| 步骤可并行 | 先规划后执行 | 便于识别并行机会 |
| 长程探索任务 | 边规划边执行 | 无法一次想清 |
💡 混合范式是工业主流:很多生产级 Agent 采用「先粗规划,再 ReAct 执行」——先用 Plan-and-Execute 出一个粗略路线图,每个子任务内部用 ReAct 边走边调。这既享受了全局视野,又保留了局部灵活性。第 3.4 节会详细对比这几种范式。
规划不是无限进行下去的。它必须有停止条件与失败处理:
| 条件 | 触发 | 处理 |
|---|---|---|
| 目标达成 | 终止判定器确认 | 返回结果 |
| 步数上限 | 达到最大迭代 | 中止 + 返回当前进度 |
| 重复检测 | 进入循环 | 强制换策略或中止 |
| 主动求助 | Agent 自判无解 | 触发人类在环 |
规划失败(走不通、超时、循环)时,有四种典型处理:
| 策略 | 做法 |
|---|---|
| 回溯 | 退回上一个分支点,换路径(ToT 式) |
| 重试 | 同一步重试 N 次(偶然失败) |
| 降级 | 换更简单的子目标 |
| 求助 | 报告失败,请求人类介入 |
⚠️ 规划失败 ≠ Agent 失败。一个成熟的 Agent 应当能优雅地失败——即便任务没完成,也要清晰地报告「我做到哪一步、为什么卡住、需要人类做什么」,而不是死循环或崩溃。失败报告的质量,是 Agent 工程成熟度的标志。
Planning 处于 Agent 的中枢,与另外三个模块都有强耦合:
| 耦合对象 | 耦合点 | 设计含义 |
|---|---|---|
| Profile | Profile 决定规划的「目标与约束」 | 财务助手不会规划「去订机票」 |
| Memory | Memory 提供「已知什么」,Planning 决定「还要查什么」 | 主动检索(第 5 章) |
| Action | Planning 输出动作,Action 执行并返回观察 | 动作空间决定规划范围 |
最关键的是 Planning ↔ Action 的耦合:Planning 决定「调什么工具」,Action 执行「真的调」,观察再回到 Planning 决定「下一步」。这个紧密耦合的循环,正是第 4 章 ReAct 的全部主题。
| 反模式 | 表现 | 后果 | 正确做法 |
|---|---|---|---|
| 永远用最复杂策略 | 一上来就 ReAct+ToT+分解 | 慢、贵、过度工程 | 策略路由 |
| 不判任务类型 | 所有任务用同一策略 | 简单任务浪费,复杂任务失效 | 先路由再规划 |
| 无停止条件 | 不设步数/时间上限 | 死循环、烧预算 | 强制门禁 |
| 失败即崩溃 | 卡住就放弃 | 用户体验差 | 优雅失败 + 报告 |
| 忽视观察反馈 | 一次规划走到底 | 计划脱离实际 | 关键步骤要边走边调 |
下一节《2.4 Action 行动模块》将讨论动作空间分类、执行接口与观察回传——具体的函数调用、代码解释器、沙箱安全留待第 6 章。