计划-执行控制流:可重规划的 Agent


文档摘要

计划-执行控制流:可重规划的 Agent 本节摘要:扛不住失败的计划只是脚本,能重规划的脚本才是 Agent——先把重规划器建起来。思维链 Agent 发 token 让循环猜工具调用在哪结束;计划-执行 Agent 先发结构化计划,再确定性地执行每步。本节建两块:一个产出计划的规划器,一个跑计划的执行器。有趣的是执行器撞失败时怎么办——中止、跳过、还是重规划。重规划是把脚本变 Agent 的那一个。你会学到带类型 step 的有序计划、失败时带先前错误回交规划器、每次修订发计划 diff、两个硬预算(步数上限与重规划上限)。 对应原课程:Phase 19 · Lesson 24 · (原英文 )。本节属「Agent Harness 深度构建赛道」第五节。

计划-执行控制流:可重规划的 Agent

本节摘要:扛不住失败的计划只是脚本,能重规划的脚本才是 Agent——先把重规划器建起来。思维链 Agent 发 token 让循环猜工具调用在哪结束;计划-执行 Agent 先发结构化计划,再确定性地执行每步。本节建两块:一个产出计划的规划器,一个跑计划的执行器。有趣的是执行器撞失败时怎么办——中止、跳过、还是重规划。重规划是把脚本变 Agent 的那一个。你会学到带类型 step 的有序计划、失败时带先前错误回交规划器、每次修订发计划 diff、两个硬预算(步数上限与重规划上限)。

对应原课程:Phase 19 · Lesson 24 · plan-execute-control-flow(原英文 phases/19-capstone-projects/24-plan-execute-control-flow/docs/en.md)。本节属「Agent Harness 深度构建赛道」第五节。

学习目标

阅读完本节,你应当能够:

  1. 把计划表示为带类型 step 的有序列表,让执行器能推理进度与结果。
  2. 顺序执行 step,把受控失败交回规划器。
  3. 从当前游标重规划,把先前错误放进上下文,让下一份计划知情。
  4. 每次修订发计划 diff,让下游追踪器或 UI 能展示计划为何变了。
  5. 强制两个预算:硬步数上限与硬重规划上限。

一、问题与直觉

计划-执行,而非思维链。计划是外壳可内省的数据,执行是外壳把那份数据跑过分发器。撞失败时三个选项:中止(返回失败,呈错)、跳过(标记步失败,继续其余)、重规划(把错误交规划器,从游标拿新计划)。重规划是把脚本变 Agent 的那一个。

二、从零实现

Step 的形状:id(计划修订内单调)、tool_nameargsexpected_outcome(规划器陈述的成功条件)、resulterrorexpected_outcome 是规划器随步发的一句短话,执行器强制它——它用于两件事:重规划器修订计划时读它;事件流发它让追踪器展示「这步本该做 X」。

规划器是纯函数:

def planner(goal: str, history: list[Step], last_error: str | None) -> list[Step]: ...

goal 是用户目标,history 是已执行步(带结果与错误),last_error 首次调用为 None、后续每次是最近失败消息,返回从游标开始的下一份计划。规划器不知道执行器、不知道重试、不知道超时——它只产计划。

执行器是小状态机。每步经分发器,结果三选一:成功、可重规划失败、致命失败。可重规划失败交回规划器;致命失败(预算超、重规划上限触)返回 FAILED

计划 diff(修订可见,非静默重写):

removed : 旧计划有新计划无的 step id added : 新计划有旧计划无的 step id revised : tool_name 或 args 变了的 step id

追踪器或 UI 可把 removed 渲染成删除线、added 高亮。重点不在 diff 格式,在「修订是可见事件」。

三、两个硬预算

max_steps 给整会话的总步执行设上限(含重规划),默认 12。一个线性五步计划重规划两次各加三步,就达 16 次执行、超预算,执行器拒重规划返回 FAILED。max_replans 给首次计划后的规划器调用次数设上限,默认 5——这是更重要的限:一个连续五次返回同一坏计划的规划器,否则会循环到步预算抓住它。限重规划让失败更快、原因更清。

本节确定性规划器(不调模型):

last_error is None -> 四步计划 last_error 匹配 X -> 三步计划,绕开 X last_error 匹配 Y -> 两步计划,优雅放弃 otherwise -> [] (信号: 无可重规划)

这够测执行器在每条转移路径上的行为:成功、重规划一次、重规划两次、重规划耗尽、步预算耗尽。

四、可复用产物

code/main.py 定义 PlanExecuteAgentStepPlanDiffSessionResult 与确定性规划器。执行器是单个 run(goal) 方法返回 SessionResult,计划 diff 通过比 step id 与 (tool_name, args) 元组算。code/tests/test_agent.py 覆盖线性成功、计划中失败重规划一次、重规划耗尽返回 failed:replan_budget、步预算耗尽、计划 diff 事件格式。

SessionResult 形状:status("completed"/"failed")、reason("goal_met"/"step_budget"/"replan_budget"/"no_plan")、historyrevisionsevents。第 20 节的循环可直接读它,第 23 节的分发器执行每步,第 21 节的注册表校验每步参数,第 22 节的传输会把整条流经 JSON-RPC 浮现给模型客户端。

五、框架对比

ReAct(思维链 + 行动)与计划-执行是两条路。ReAct 灵活但每步都让循环猜工具调用边界;计划-执行把规划与执行解耦,计划可内省、可 diff、可预算。ReWOO 与本节的「先规划再执行」同源。本节的差异化在「重规划带先前错误」与「计划 diff 可见」——这让失败不是静默重写,而是可追踪的修订事件。接真模型后会想加两样:部分计划缓存(前六步成了三步、后三步失败时,不重跑前三步,规划器读 history 即可);并行分支(规划器发 gather_step 而非 next_step,两工具调用经分发器并发)。

六、练习

  1. 重规划耗尽:让确定性规划器连续返回同一坏计划,确认 max_replans 抓住它返回 failed:replan_budget
  2. 步预算:让重规划每次加三步,确认 max_steps 在第 12 次执行时拒重规划。
  3. 计划 diff:构造一次重规划,确认 removed/added/revised 三字段正确。
  4. 部分计划缓存:接一个真规划器,确认失败后不重跑已成的步。
  5. 并行分支:加 gather_step,确认两工具调用经分发器并发。

本节要点回顾

  1. 计划-执行非思维链:计划是可内省数据,执行确定性地跑过分发器。
  2. 重规划是关键:把失败交规划器,从游标拿新计划,带先前错误。
  3. Step 带 expected_outcome:规划器陈述成功条件,执行器不强制,重规划器与追踪器读它。
  4. 计划 diff 可见:removed/added/revised,修订是事件非静默重写。
  5. 两个硬预算:max_steps(默认 12,含重规划)、max_replans(默认 5,更重要)。
  6. 确定性规划器测全路径:成功/重规划一次/两次/耗尽/步预算。

下一节,我们建「验证门与观察预算」——决定工具调用是否允许触发、模型能看到多少输出的确定性门链。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U