Agent Planning:什么时候需要计划,什么时候直接执行?
Planning 不是所有 Agent 的必经步骤。它只在任务存在多阶段、依赖、风险或协作需要时,才值得成为可更新的外部执行结构。

文章目录
- 导语
- 一、Agent Loop 本身已经会逐步决策
- 二、什么情况下值得先计划
- 任务包含多个可验证阶段
- 步骤之间存在依赖
- 某些动作成本高或风险高
- 多方需要共享进度
- 三、三种常见执行方式
- 直接执行
- 轻量 Plan-first
- 固定 Workflow + 局部 Agent
- 四、一份计划应该长什么样
- 五、Plan Step 和 Agent Step 不是一回事
- 六、谁生成计划,谁批准计划
- 七、什么时候需要 Replan
- 前提被证伪
- 工具返回新约束
- 用户改变目标
- 资源不可用
- 八、完成状态必须由证据推进
- 九、Planning 最常见的失败方式
- 为任何任务都生成计划
- 计划写得太细
- 计划写得太空
- 计划完成状态靠模型自报
- 计划与真实执行脱节
- 把 Plan 当作权限凭证
- 十、前端怎样展示计划
- 十一、后端怎样把计划放进 Runtime
- 十二、用三个任务检验是否需要计划
- 任务 A
- 任务 B
- 任务 C
- 十三、这一篇真正要记住的事
- 下一篇预告
- 参考资料
导语
前几篇已经搭起一个能运行、能保存、能记忆的 Agent。
接下来很自然会想到:任务开始前,要不要先让模型列一份计划?
对于:
读取 package.json,告诉我项目使用哪个包管理器。
先生成五步计划只会增加一次模型调用和阅读负担。直接读取文件更合理。
但对于:
把这个 Node.js 服务升级到新版本,修复兼容问题,运行测试,并给出迁移说明。
任务包含调查、修改、验证和交付。如果没有外部计划,Agent 可能修完一处就宣布完成,或忘记运行关键测试。
Planning 不是“让模型多思考一会儿”,而是把复杂任务拆成一组可检查、可更新、可恢复的执行承诺。
这一篇会回答:什么时候直接执行,什么时候先计划,计划应该保存什么,以及新证据出现后怎样 Replan。
一、Agent Loop 本身已经会逐步决策
第二篇介绍的 Agent Loop 是:
模型选择下一步
→ Runtime 执行工具
→ Tool Result 回到下一轮
→ 模型继续选择
这是一种 Reactive(反应式)执行:每轮根据最新观察选择下一步。
它适合:
- 下一步很明确;
- 任务较短;
- 环境不确定,需要先行动再判断;
- 即使走错一步,也容易恢复。
例如“查一个订单状态”通常只需要调用 get_order,没有必要先维护 Plan。
Planning 是叠加在 Agent Loop 之上的能力,不是替代循环。即使已经有计划,每一步执行后的结果仍可能改变后续安排。
二、什么情况下值得先计划
可以从四个信号判断。
任务包含多个可验证阶段
定位问题 → 修改代码 → 运行测试 → 整理交付
阶段遗漏会直接影响完成质量。
步骤之间存在依赖
先确认数据库版本
→ 选择迁移脚本
→ 在 staging 验证
→ 再决定是否申请生产执行
后续动作不能随意提前。
某些动作成本高或风险高
安装大量依赖、运行长测试、写生产数据之前,先展示计划能让用户确认范围。
多方需要共享进度
用户、前端界面、后台 Worker 或多个 Agent 需要知道当前阶段与剩余工作。计划成为协调接口。
如果这些信号都很弱,直接执行往往更快、更可靠。
三、三种常见执行方式
直接执行
模型每轮选择下一步,不生成显式计划。
适合短小、低风险、强反馈任务。
轻量 Plan-first
任务开始时生成少量高层步骤,执行中允许修改。步骤数由任务的实际阶段决定,不为了显得完整而凑数。
适合大多数代码修改、研究和数据分析任务。
固定 Workflow + 局部 Agent
外层阶段由代码确定,阶段内部允许 Agent 动态探索:
固定:收集输入
Agent:调查问题
固定:人工确认
Agent:执行已批准修改
固定:验证与发布
适合流程必须合规,但局部路径不确定的场景。
并不是 Agent 越自主越高级。外层固定结构能保证关键关卡不被模型跳过,内层 Agent 提供灵活性。
四、一份计划应该长什么样
差的计划只是把目标换个说法:
1. 分析问题
2. 解决问题
3. 确保正确
每一步都无法判断是否完成。
更可用的 Plan Step 至少包含:
type PlanStep = {
id: string
title: string
objective: string
status: 'pending' | 'in_progress' | 'completed' | 'blocked' | 'skipped'
dependsOn: string[]
completionCriteria: string[]
completionEvidence?: string[]
risk: 'low' | 'medium' | 'high'
}
升级 Node.js 服务的计划可以是:
[
{
"id": "inspect",
"title": "确认当前版本与升级约束",
"objective": "读取 package.json、锁文件和 CI 配置",
"status": "pending",
"dependsOn": [],
"completionCriteria": ["记录当前版本", "明确目标版本", "列出受影响配置"],
"risk": "low"
},
{
"id": "change",
"title": "应用兼容性修改",
"objective": "更新版本和必要代码,不做无关重构",
"status": "pending",
"dependsOn": ["inspect"],
"completionCriteria": ["列出变更文件", "保留关键 diff"],
"risk": "medium"
},
{
"id": "verify",
"title": "验证升级结果",
"objective": "运行约定测试并记录失败",
"status": "pending",
"dependsOn": ["change"],
"completionCriteria": ["记录测试命令", "记录退出码", "有失败时附上摘要"],
"risk": "low"
}
]
计划描述的是目标、依赖和完成条件;真正的完成证据要等执行后再回填。计划不需要提前写死每一次 read_file 或 search_code 调用,具体工具选择仍由 Agent Loop 根据现场信息完成。
五、Plan Step 和 Agent Step 不是一回事
这两个 Step 很容易混淆。
| 概念 | 粒度 | 例子 |
|---|---|---|
| Plan Step | 面向任务目标的阶段 | 验证升级结果 |
| Agent Step | 实际发生的一次事件 | 调用 run_tests、收到 Tool Result |
一个 Plan Step 可能包含多个 Agent Step:
Plan Step:验证升级结果
├─ Agent Step:读取测试脚本
├─ Agent Step:运行单元测试
├─ Agent Step:读取失败日志
└─ Agent Step:运行兼容性测试
Plan 用于协调与完成判断;Agent Step 用于执行记录与排错。
把两者混成一张表,会出现两个极端:计划细到每个工具调用,难以维护;或执行记录只剩“验证中”,无法复盘。
六、谁生成计划,谁批准计划
模型适合根据自然语言目标提出初稿,但 Runtime 和应用仍要补上系统事实:
- 可用工具;
- 当前权限;
- 时间和成本预算;
- 必经审批节点;
- 组织固定流程。
对于低风险任务,如果 Runtime Policy 允许,模型提出的计划可以不经用户确认就开始执行。
对于高成本或高副作用任务,先展示给用户:
将修改 3 个配置文件
预计运行 2 组测试
不会部署生产
应用修改前需要确认
用户批准的是可理解的范围与风险,不是模型内部推理。
不要让模型通过修改 Plan 绕过 Runtime Policy。即使计划里写“直接发布”,发布工具仍要经过权限检查。
七、什么时候需要 Replan
计划不是任务开始时生成后永不变化的剧本。
下面几类事件会触发 Replan:
前提被证伪
计划假设项目使用 npm,实际发现是 pnpm。依赖安装步骤要更新。
工具返回新约束
测试结果显示数据库版本不兼容,需要插入迁移步骤。
用户改变目标
用户追加“只给修复方案,不要改文件”,所有写入步骤都要取消,必要时改成输出方案或 Patch 预览。
资源不可用
生产日志权限不足,调查路径需要改用 staging 复现或等待授权。
Replan 不等于每一步都重新生成整份计划。可以只修改受影响部分,并记录原因:
type PlanRevision = {
planId: string
fromVersion: number
toVersion: number
reason: string
changedStepIds: string[]
createdAt: string
}
保留版本后,用户和工程师才能知道为什么路线发生变化。
八、完成状态必须由证据推进
模型说“这一步完成了”,不一定真的完成。
计划状态更新可以采用:
async function completePlanStep(
step: PlanStep,
runState: AgentRunState
) {
const evidence = collectEvidence(step, runState)
const result = validateCompletion(step.completionCriteria, evidence)
if (!result.ok) {
throw new Error(result.reason)
}
return updateStepStatus(step.id, 'completed', {
completionEvidence: evidence
})
}
验证方式随任务而变:
“读取配置” → 已保存文件路径与内容摘要
“运行测试” → 有命令、退出码和测试报告
“创建草稿” → 有外部资源 ID
“等待确认” → 有用户事件和批准范围
不是所有完成条件都能由代码完全判定。语义质量可能仍需要模型或人工评审。但可确定的事实,优先由程序验证。
九、Planning 最常见的失败方式
为任何任务都生成计划
读取一个文件也先列五步,成本和延迟增加,用户还要阅读无意义进度。
计划写得太细
提前决定每次搜索关键词和文件路径。新证据一出现,整个计划失效。
计划写得太空
“分析—执行—检查”无法指导动作,也无法验收。
计划完成状态靠模型自报
测试没运行,却因为模型输出“已验证”而标记完成。
计划与真实执行脱节
Agent 临时做了额外修改,Plan 却没有更新。前端显示的进度与真实世界不同。
把 Plan 当作权限凭证
用户批准“升级依赖”,不代表批准任意删除文件或部署生产。每个高风险动作仍需按策略判断。
十、前端怎样展示计划
计划适合成为长任务的产品骨架:
✓ 确认版本与约束
● 应用兼容性修改
○ 运行验证
○ 生成迁移说明
用户需要看到:
- 当前阶段;
- 已完成证据摘要;
- 新增或取消步骤的原因;
- 哪一步等待确认;
- 如何暂停、取消或接管。
不要把模型生成的长段思考当成计划展示。Plan 应该简洁、可操作、状态稳定。
任务总量不确定时,不要伪造精确百分比。可以展示阶段和已完成项。
十一、后端怎样把计划放进 Runtime
一个轻量执行器可以这样工作:
async function runPlannedTask(plan: Plan) {
while (true) {
const step = findNextRunnableStep(plan)
if (!step) {
return finishOrReportBlocked(plan)
}
await markInProgress(step.id)
const result = await runAgentLoop({
objective: step.objective,
completionCriteria: step.completionCriteria
})
if (result.newConstraint) {
plan = await reviseAffectedSteps(plan, result)
continue
}
await validateAndComplete(step, result)
}
}
实际实现还要处理并发、重试和用户中途指令。这里的重点是:Plan 选择当前任务阶段,Agent Loop 在阶段内动态行动,执行结果又可以反过来修改 Plan。
十二、用三个任务检验是否需要计划
任务 A
读取 README,告诉我本地启动命令。
通常直接执行。路径短,风险低,结果容易验证。
任务 B
修复登录按钮无响应,并运行相关测试。
可以用轻量计划:定位、修改、验证。调查阶段内部保持反应式。
任务 C
迁移数据库并部署生产。
更适合固定 Workflow + 局部 Agent:备份、审批、staging 演练、生产窗口等关卡由系统确定,Agent 只在调查与生成迁移方案等局部发挥。
如果你能根据阶段数量、依赖、风险和协作需求选择方式,而不是看到“Agent”就强制规划,Planning 的边界就清楚了。
十三、这一篇真正要记住的事
Planning 的价值不是让输出看起来更认真,而是让复杂任务:
不遗漏关键阶段
明确步骤依赖
用证据推进完成状态
在风险动作前获得确认
出现新事实时可局部调整
暂停后还能继续
短任务直接执行;中等复杂任务使用轻量可更新 Plan;强合规、高风险流程使用固定 Workflow 包住局部 Agent。
Plan Step 表达任务阶段,Agent Step 记录真实执行。计划永远不能替代 Runtime 权限。
下一篇将专门处理这道边界:哪些工具可以自动执行,哪些动作必须拦截,权限判断为什么不能交给模型自己决定?
下一篇预告
下一篇:Agent 权限控制:哪些动作可以自动做,哪些必须确认?
参考资料
- Plan-and-Solve Prompting:
https://arxiv.org/abs/2305.04091 - OpenAI Agents SDK — Running agents:
https://openai.github.io/openai-agents-js/guides/running-agents/ - OpenAI Agents SDK — Sessions:
https://openai.github.io/openai-agents-js/guides/sessions/