Plan-Execute 技术解读

Plan-Execute(规划—执行)是一种常见的 AI Agent 架构:先由大模型把复杂目标拆成可执行步骤,再逐步调用工具完成任务,并根据执行结果调整计划。

一句话概括:

Planner 负责“想清楚怎么做”,Executor 负责“把每一步做完”。

1. 核心架构

否,结果正常

否,计划需调整

是

用户目标

Planner:生成计划

Executor:执行当前步骤

工具/API/数据库/代码

执行结果

任务完成?

Replanner:重新规划

汇总并输出结果

通常包含以下组件:

组件主要职责
Planner理解目标、拆分步骤、识别依赖关系
Executor执行当前步骤,选择并调用工具
Tool Layer提供搜索、数据库、Shell、代码执行等能力
State/Memory保存计划、执行结果和上下文
Replanner根据失败或新信息修改后续计划
Evaluator检查结果是否满足最终目标

2. Planner 如何生成计划

例如用户提出:

分析服务器磁盘占用,并找出可以安全清理的文件。

Planner 可能生成:

{
  "goal": "分析磁盘占用并提出清理方案",
  "steps": [
    {
      "id": 1,
      "description": "查看各文件系统磁盘使用率",
      "tool": "shell",
      "command_hint": "df -h",
      "depends_on": []
    },
    {
      "id": 2,
      "description": "定位占用空间最大的目录",
      "tool": "shell",
      "command_hint": "du",
      "depends_on": [1]
    },
    {
      "id": 3,
      "description": "识别日志、缓存和临时文件",
      "tool": "shell",
      "depends_on": [2]
    },
    {
      "id": 4,
      "description": "评估删除风险并生成清理建议",
      "tool": null,
      "depends_on": [3]
    }
  ]
}

好的计划一般需要满足:

  • 每一步都可以独立执行和验证。
  • 步骤粒度不能过大,也不能细到失去规划价值。
  • 明确步骤间的依赖关系。
  • 将查询、修改、删除等不同风险等级的操作分开。
  • 为失败、无结果或权限不足设计替代路径。

3. Executor 如何工作

Executor 通常只关注当前步骤:

输入:
- 最终目标
- 当前步骤
- 已完成步骤及结果
- 可用工具
- 安全约束

输出:
- 工具调用
- 步骤执行结果
- 是否成功
- 是否需要重新规划

简化伪代码:

state = {
    "goal": user_request,
    "plan": planner.create_plan(user_request),
    "results": {}
}

while True:
    step = get_next_step(state)

    if step is None:
        break

    result = executor.execute(
        goal=state["goal"],
        step=step,
        previous_results=state["results"]
    )

    state["results"][step.id] = result

    if result.need_replan:
        state["plan"] = replanner.update_plan(
            goal=state["goal"],
            old_plan=state["plan"],
            results=state["results"]
        )

answer = synthesizer.generate(state)

Executor 不一定对应一个模型。它也可以由以下部分组合而成:

  • LLM:理解步骤并选择工具。
  • 普通代码:进行参数校验、状态流转和重试。
  • 工作流引擎:处理并行执行、超时、审批和持久化。
  • 工具适配器:封装数据库、HTTP API、Shell 等能力。

4. 为什么需要 Replanner

初始计划是基于有限信息生成的,很容易出现偏差。

例如原计划准备查询 MySQL:

SHOW PROCESSLIST;

执行后发现需要重点排查锁等待,Replanner 可以把后续计划调整为:

  1. 查询当前会话。
  2. 查询 InnoDB 事务。
  3. 查询锁等待关系。
  4. 定位阻塞源头。
  5. 评估是否终止阻塞会话。

重新规划的常见触发条件:

  • 工具调用失败。
  • 返回内容为空。
  • 实际环境与假设不一致。
  • 缺少权限或必要参数。
  • 发现更优路径。
  • 某一步结果已经使后续步骤失去意义。
  • 操作风险提高,需要用户确认。

Replanner 不应每执行一步都重新规划,否则会增加延迟和成本。更合理的做法是仅在计划失效时触发。

5. Plan-Execute 与 ReAct 的区别

ReAct 是 Reasoning + Acting,即模型边思考边调用工具。

对比项Plan-ExecuteReAct
决策方式先形成整体计划,再执行每轮决定下一步
全局性较强较弱
灵活性依赖重新规划天然灵活
模型调用量可能较少通常较多
长任务稳定性较好容易偏离最终目标
短任务效率可能规划过度通常更高
并行执行容易识别可并行步骤相对困难
可审计性计划和进度比较清晰推进路径更动态

典型选择:

  • “查一下今天东京天气”:适合 ReAct 或直接调用工具。
  • “调研三个技术方案并形成报告”:适合 Plan-Execute。
  • “排查线上故障”:更适合两者结合,因为环境变化较快。

实际系统常采用混合架构:

高层:Plan-Execute
      ↓
单个复杂步骤:ReAct 循环
      ↓
工具调用

6. 计划的数据结构

生产系统不建议让 Planner 只返回自然语言列表,最好输出结构化数据:

{
  "goal": "定位数据库性能问题",
  "status": "running",
  "steps": [
    {
      "id": "step_1",
      "title": "查询活跃会话",
      "status": "completed",
      "depends_on": [],
      "risk": "read_only",
      "result_ref": "result_1"
    },
    {
      "id": "step_2",
      "title": "查询长事务",
      "status": "running",
      "depends_on": ["step_1"],
      "risk": "read_only"
    },
    {
      "id": "step_3",
      "title": "处理阻塞事务",
      "status": "pending",
      "depends_on": ["step_2"],
      "risk": "destructive",
      "requires_approval": true
    }
  ]
}

常见状态包括:

pending
ready
running
completed
failed
skipped
blocked
cancelled

这样方便实现:

  • 任务恢复
  • 失败重试
  • 并行调度
  • 人工审批
  • 执行进度展示
  • 日志审计

7. 关键技术难点

计划粒度

步骤过粗:

分析数据库并解决问题

Executor 无法明确选择工具,也难以验证是否完成。

步骤过细:

1. 输入 SHOW
2. 输入 PROCESSLIST
3. 输入分号

这会让规划本身失去价值。

比较合理的粒度是“一个可以执行、验证和产生明确结果的任务”。

错误传播

如果早期步骤结果错误,后面的执行可能全部建立在错误假设上。

可以为每一步保存:

  • 原始工具输出
  • 结构化结果
  • 置信度
  • 数据来源
  • 执行时间
  • 验证状态

无限重新规划

系统可能形成循环:

执行失败 → 重新规划 → 再次执行同一操作 → 再次失败

需要设置:

  • 最大执行次数
  • 最大重新规划次数
  • 相同错误检测
  • 总 token 或费用预算
  • 总执行时间限制

上下文膨胀

把全部历史工具输出不断塞回模型,会导致上下文过长。

一般采用:

  • 原始输出放外部存储。
  • State 只保存引用和结构化摘要。
  • 仅加载当前步骤的相关结果。
  • 定期压缩执行历史。

安全控制

不能因为 Planner 生成了操作,就直接信任它。权限控制应由确定性代码完成:

if step.risk == "destructive" and not step.approved:
    return wait_for_user_approval()

尤其需要拦截:

  • 删除文件或数据。
  • DROP、TRUNCATE、无条件 UPDATE。
  • 终止数据库会话。
  • 修改生产配置。
  • 对外发送消息。
  • 产生费用的外部操作。

8. 适用场景

Plan-Execute 比较适合:

  • 深度资料调研
  • 代码库分析和功能开发
  • 数据分析与报告生成
  • 数据库问题排查
  • 运维故障诊断
  • 多系统业务流程
  • 需要审批的自动化任务
  • 长时间运行且可恢复的任务

不太适合:

  • 简单问答
  • 单次工具查询
  • 对实时反馈要求极高的交互
  • 环境变化极快、无法提前规划的任务

9. 生产级实现建议

真正落地时,可以遵循以下原则:

  1. Planner 只负责生成和调整计划,不直接执行高风险操作。
  2. 使用 JSON Schema 或类型模型约束计划输出。
  3. Executor 每次只接收当前步骤和必要上下文。
  4. 工具调用必须经过参数校验和权限控制。
  5. 每一步执行后保存 checkpoint,支持中断恢复。
  6. 查询类操作可以自动执行,修改类操作设置审批节点。
  7. 对重试次数、运行时长、token 和成本设置预算。
  8. 最终结果必须引用真实执行结果,不能只根据计划生成答案。
  9. 用任务完成条件判断是否结束,而不是仅判断计划是否全部执行。
  10. 对稳定、重复的路径逐步代码化,减少对 LLM 的依赖。

Plan-Execute 的本质并不是简单的“让模型先列一个步骤清单”,而是将 Agent 从不可控的连续推理,转换为一个具备计划、状态、调度、校验、恢复和审批能力的任务执行系统。

在这里插入图片描述

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐