返回 G01~G90 教材库
G37 · 总 Day 217教材已备 ≠ 学习已完成

G37:从零构造 Planner–Executor 状态机

Planner–executor 状态机把“提出下一步”和“执行受控动作”拆成显式转移,使每次工具调用都有前置条件、结果类型、恢复路径和可重放证据。

2027-03-30planner-executor、state-machine、recovery、invariant、tool-use

内容类型:预习教材(不代表已完成)
日期:2027-03-30
阶段:P3 · AGI Foundations 90
总路线:Day 217 / 360
周次:W6 · Memory、Planning 与 Tool Use
节奏:周二最小机制
状态:教材已备;学习未完成
标签:planner-executor、state-machine、recovery、invariant、tool-use

一句话定义

Planner–executor 状态机把“提出下一步”和“执行受控动作”拆成显式转移,使每次工具调用都有前置条件、结果类型、恢复路径和可重放证据。

学习目标

  1. 从零定义 PLAN→VALIDATE→EXECUTE→OBSERVE→COMMIT 的有限状态机。
  2. 区分 goal、plan、action、observation、event 与 terminal condition。
  3. 用 invariant 和 transition table 推导超时、拒绝、冲突与重试的恢复路径。
  4. 比较显式状态机、自由 Agent loop 与一次性 prompt 的适用边界。

核心知识

  • Planner 负责在当前已知状态下提出有限候选,不拥有执行权限;executor 接受通过验证的 typed action,并将 typed result 返回给 reducer。
  • 状态机的价值不是保证模型正确,而是限制错误形态:未通过 schema/permission 的动作不会执行,未知结果不会被写成成功,失败可从 event log 重放。
  • observation 是外部工具返回或环境事件;模型对 observation 的解释是另一条派生记录。混合二者会使审计无法区分事实与推断。
  • Terminal condition 应由可验证状态判断,例如 all_required_fields_resolved,而不是模型自由声称“任务完成”。循环还需有最大步数、时间和成本上限。
  • 恢复不是简单重试。根据副作用可分安全重试、查询确认、人工介入和补偿动作;补偿也不是严格回滚,因为外部世界可能已被观察或改变。

机制与推导

定义状态集合:

INIT, PLANNING, VALIDATING, EXECUTING,
OBSERVING, COMMITTING, WAITING_HUMAN,
SUCCEEDED, FAILED, UNKNOWN

转移函数 (\delta(x,event)=x') 应尽量确定。例如:

PLANNING + action_proposed -> VALIDATING
VALIDATING + denied -> WAITING_HUMAN | FAILED
VALIDATING + allowed -> EXECUTING
EXECUTING + timeout(side_effect_possible) -> UNKNOWN
UNKNOWN + status_confirmed(success) -> COMMITTING
UNKNOWN + status_confirmed(absent) -> EXECUTING
COMMITTING + event_saved -> PLANNING | SUCCEEDED

设置三个 invariant:

  1. executed(action) => validated(action, policy_version)
  2. committed(success) => observed(typed_success)
  3. side_effect_count(logical_action_id) <= 1

它们不是测试 Gate,而是帮助理解状态所有权的性质。若事件日志为 (E=(e_1,...,e_n)),当前状态可由 reducer 重建:

[ x_n=reduce(reduce(\cdots reduce(x_0,e_1),e_2),\ldots,e_n) ]

这要求 event 不被事后静默修改,并记录 schema、tool 与 policy 版本。自由循环通常把状态藏在自然语言中,难以证明这些 invariant 是否成立。

Planner 可输出最多 (K) 个候选,每次只执行一个;停止条件为:

[ stop=goal_verified\lor steps\ge B_s\lor cost\ge B_c\lor risk>r_{max} ]

预算耗尽应形成 incompleteneeds_review,不能冒充成功。

最小练习或观察步骤

  1. 用字典或 enum 写出上述状态与 transition table,不需要任何 Agent SDK。
  2. 定义一个目标:“读取三条合成记录并生成差异草稿”;工具只有 read_record(id)save_draft(text,key)
  3. Planner 只返回 {action, args, rationale_summary};validator 检查 allowlist、参数和剩余预算,executor 只接受验证 token。
  4. 手工注入五条轨迹:正常成功、参数错误、权限拒绝、只读超时、写入超时未知。逐条检查下一状态。
  5. 保存事件后从空状态 replay,比较重建状态与原状态;不要记录或要求隐藏思维链。
  6. 把自由 while-loop 版本与状态机版本画成两张图,比较可观察点和错误恢复,而不是只比代码行数。

常见误区与边界

  • Planner 输出了函数名就直接调用,绕过 schema、policy 与预算检查。
  • 把所有工具异常归为同一 error,丢失“明确未执行”和“结果未知”的关键差别。
  • 模型说“完成”就进入 SUCCESS,没有独立 terminal predicate。
  • event log 保存完整敏感 payload 或隐藏推理文本,制造新的隐私与安全面。
  • 认为状态机能消除语义错误;它只能让动作边界和恢复更可控。
  • toy 状态机不等于生产级 Agent runtime,本日不连接外网和真实业务写接口。

研究/系统场景连接

在客户投诉摘要场景,Planner 可提出“读取已授权工单→对照政策→保存建议草稿”,executor 只能操作合成数据和草稿区。任何“关闭投诉”“退款”“修改客户资料”都不在 allowlist。研究 Agent 同样可以读取本地论文清单、生成实验配置草稿,却不能自行下载任意代码或覆盖原始结果。显式 WAITING_HUMAN 不是能力不足的尴尬,而是自主程度与风险相匹配的控制状态。

自检问题

  1. action proposal 与 action authorization 为什么必须是不同事件?
  2. 写入超时应进入 FAILED 还是 UNKNOWN,为什么?
  3. 哪三个 invariant 最能阻止错误状态被写成成功?
  4. event replay 依赖哪些版本和不可变性条件?
  5. 状态机相对自由循环仍然不能解决什么?

专业课程对齐

  • 阅读 ReAct 原始论文,将其 action/observation 序列映射到 typed event,同时保留论文任务与本地 runtime 的差异。
  • 阅读 Toolformer 原始论文,观察工具选择学习目标,再列出 schema validation、权限和恢复为何仍属于系统层。
  • 阅读 Generative Agents 原始论文,关注 observation、reflection 与 planning 的组织方式,并审视哪些状态属于仿真而非外部事实。

深入学习提示

可进一步比较 hierarchical state machine、behavior tree、Petri net 与 event sourcing。不要为了“工程完整”引入消息队列和数据库;先用一页 transition table 找出所有未知状态。深入研究点是 failure semantics:在非幂等世界里,恢复为何需要查询、人工或补偿,而不是盲重试。

学后填写区

  • 实际画出的状态与事件:
  • 手推的失败轨迹:
  • 一个保持或破坏的 invariant:
  • replay 需要的版本信息:
  • 明确禁止的动作:
  • 尚未理解的问题:
本页是未来 P3 的预习教材。等 P1、P2 完成并正式进入 P3 后,再填写真实理解、实验现象与不确定项;现在阅读不会改变P1 唯一进度账本