agent 进阶:Plan-and-Execute 适合什么样的场景

前言

本文主要描述Plan-and-Execute开发中的ReAct模式,并且使用一个demo,彻底搞懂怎么在实际工作中使用Plan-and-Execute模式

话不多说,我们开始

代码结构

代码地址

text 复制代码
.
├── main.py       # 主入口,串起规划、执行、分析三个阶段
├── planner.py    # Planner,负责让 LLM 先生成排查计划
├── executor.py   # Executor,负责按计划调用工具
├── analyzer.py   # Analyzer,负责根据工具结果做最终分析
└── tools.py      # 工具层,模拟告警、日志、错误分析等数据源

先规划 → 再执行 → 最后总结,这就是典型的 Plan-and-Execute 模式

  • ReAct 更像一个值班同学一边查一边想:先看告警,不够再看日志,再不够继续查 SQL
  • Plan-and-Execute 更像先开一个排障 checklist:先查告警,再查日志,再分析错误,最后汇总根因

代码解析

  • main.py,代码入口,分成三部完成需求

    • make_plan(user_input) 让 LLM 根据用户输入生成一个计划
    • executor.run(plan) 按计划调用工具,并收集每一步结果
    • analyze(user_input, observations) 把用户问题和工具结果交给 LLM,生成最终结论
  • planner.py,调用一次llm,让大模型自动生成计划

    • 自动扫描 tools.py 里的函数,把函数名、参数、docstring 都提取出来
    • 构造prompt,明确llm的角色以及可以调用的tools,并且按照固定的格式返回
  • executor.py,按计划调用工具,并收集每一步结果

  • tools,所有能够调用的工具都记录在此

    • query_alarm,查询服务的监控告警
    • query_logs,查询服务日志
    • analyze_errors,分析错误日志
  • analyzer.py,再次调用llm,将获得数据结果与需求进行综合分析得出结论

执行链路

把这几个模块串起来,完整执行链路是这样的:

Plan-and-Execute 特点

计划现行,先让模型把任务拆成计划,再由执行器按计划完成,最后再统一汇总

比如一次线上故障排查,可能要同时看告警、日志、链路追踪、数据库、发布记录、配置变更。那就把这些需要采集的信息列一个计划,然后逐一获取数据,最后再来汇总分析

优点:后续所有的操作全是围绕着最初制定的计划来执行,不会出现跑偏的情况,并且不需要频繁与大模型交互,减少时间、token的损耗

缺点:一但制定的计划不合理,那后续的工作就肯定事倍功半,因为在运行途中没有主动纠错的能力

和 ReAct 的核心区别

ReAct 是边执行边决策

Plan-and-Execute 是先决策再执行

维度 Plan-and-Execute ReAct
决策方式 先生成计划,再执行 每一轮根据 Observation 决定下一步
可控性 更强,计划可审查 相对弱,路径更动态
灵活性 一般,依赖初始计划质量 更强,能根据中间结果调整
成本 通常更可控 多轮调用时成本更高
延迟 路径明确时更低 轮数多时延迟更高
可解释性 计划天然可展示 过程可解释,但轨迹可能更长
工程治理 更容易加审批、限流、审计 需要对每轮 Action 做治理
适合任务 流程清晰、步骤稳定、可批处理 探索性强、信息不确定、需要动态调整

更适合 Plan-and-Execute 的场景

流程相对固定的任务

这类任务的特点是:步骤大体稳定,顺序大体明确,执行过程中不需要与大模型参与

  • 标准化巡检
  • 常规故障排查
  • 批量数据分析
  • 固定格式报告生成
  • 发布前检查
  • 安全基线扫描

需要审批和审计的任务

如果 agent 涉及高风险操作,

1)修改配置

2)重启服务

3)扩容缩容

4)执行 SQL

5)发起回滚

计划先出来,系统可以先展示给人看:

json 复制代码
[
  {
    "step": 1,
    "tool": "query_alarm",
    "args": {"service": "order-service"},
    "reason": "确认服务是否处于告警状态"
  },
  {
    "step": 2,
    "tool": "rollback_release",
    "args": {"service": "order-service", "version": "v1.2.3"},
    "reason": "最近发布后错误率上升,尝试回滚"
  }
]

这时候系统可以拦住第二步,要求人工确认

批处理的任务

帮我分析最近 20 个告警,按服务归类,找出最可能的共性根因。这类任务如果用 ReAct,很可能一轮一轮查,过程会比较长

Plan-and-Execute 可以先生成一个批处理计划:

text 复制代码
1)拉取最近 20 个告警
2)按 service 聚合
3)查询每个 service 的错误率和日志
4)提取共性关键词
5)生成汇总报告

这种任务不需要模型每一步重新想。它需要的是稳定执行和最后归纳

更适合 ReAct 的场景

笔者觉得主要是探索性任务。

比如:

  • 问题边界不清楚
  • 不知道下一步该查什么
  • 工具结果会强烈影响后续路径
  • 需要不断缩小问题范围
  • 任务目标会随着中间证据变化

比如线上故障里,用户只说一句:

text 复制代码
系统有点慢,帮我看看。

这时候你很难一开始就列出完整计划。因为"慢"可能来自网关、服务、数据库、缓存、第三方依赖,也可能是用户网络问题

ReAct 更适合这种情况:

text 复制代码
先查整体告警 → 发现订单服务异常 → 查订单日志 → 发现 DB timeout → 查数据库指标 → 发现慢 SQL → 查最近发布 → 定位变更

混合使用

更常见的做法是混合使用。

比如:

  • 先 Plan-and-Execute 生成一个大方向计划

  • 每个复杂步骤内部再用 ReAct 动态探索

  • 最后统一 Analyzer 汇总

    举个例子:

    text 复制代码
    总计划:
    1)检查告警
    2)检查日志
    3)检查数据库
    4)检查发布变更
    5)输出报告
    
    其中第 3 步"检查数据库"内部,可以用 ReAct:
    Thought: 先看连接数
    Action: query_db_connections
    Observation: 连接数打满
    Thought: 继续查慢 SQL
    Action: query_slow_sql
    Observation: 某条 SQL 扫描 300 万行
    Final Answer: 数据库瓶颈来自慢 SQL 导致连接池耗尽

这样既有全局计划,也有局部灵活性

代码改进

  • 规划plan的时候加入人工确认,如果模型的plan不合理或者还需要加入新步骤的时候,需要人工补充

  • 限制最大步骤数。否则模型一口气规划 30 步,浪费时间还耗费token

  • 增加工具白名单和权限,或者直接调用mcp

  • 支持失败重规划,Plan-and-Execute 的短板是计划不容易中途修正,可以加一个 Replanner,比如某一步工具失败,或者结果明显不足,就把当前 observations 发给模型,让它重新规划后续步骤。

    • Plan → Execute → 判断是否足够 → 不足则 Replan → Execute → Analyze,这样就比纯 Plan-and-Execute 更灵活

总结

Plan-and-Execute 的本质先先规划,再执行

它的优点是结构清晰、成本可控、方便审计,也更适合流程明确的工程任务

它的缺点是灵活性不如 ReAct,如果初始计划质量不高,后续执行就容易跑偏

所以任务清楚、流程稳定,用 Plan-and-Execute;问题模糊、需要探索,用 ReAct;场景复杂,就把两者组合起来

联系我

  • 联系我,做深入的交流

至此,本文结束

在下才疏学浅,有撒汤漏水的,请各位不吝赐教...