Appearance
Graph 怎样被调度并持久化:Scheduler、State Machine 与 StateStore
前置:模型计划如何变成真实执行:ToolExecutor、Planner 与 GraphCompiler
核心问题:节点完成的一瞬间,Scheduler、State Machine、StateStore 各自更新什么,怎样保证 crash 后恢复到一致事实?
A/B READY 并行,C 等二者;A 已成功而 B crash,resume 保留 A result。批准按钮发 command,Runtime 验证后从 WAITING→RUNNING,而不是前端直接写 DB 状态。
Mental Model
最终架构把前面所有知识收敛为可替换 contract:Model、Context、Retriever、Tools、Planner、Runtime、State、Approval、Trace/Eval、MCP、Workspace、API。
Scheduler
Scheduler 只从 committed RunState/NodeState 推导 ready work,并通过 worker/ToolExecutor 发起 execution attempt。它不保存第二份“真实状态”。
claim、complete、fail、cancel 都通过 Runtime transition contract 提交;进程崩溃后可从 StateStore/CheckpointStore 重新计算 ready queue。
Run State Machine
State Machine 在最终 Harness 中表现为纯 transition/reducer + invariant validation:command/event 输入,得到新的 domain state 或明确拒绝。
🔍 源码对照:Observation 是 StateMachine 的输入事实之一
完整源码与通用分析见 09-01 Run Lifecycle / State Machine。这里不重复代码;这里关注 State Machine:Observation 是 reducer / transition 的输入事实,而不是模型消息本身。
源码说明
Agent/conversation state、storage 与 subagent runtime 分开,是我们检验 Scheduler/StateStore boundary 的好材料:Scheduler 根据状态决定 ready work,但 authoritative state 不能藏在 scheduler coroutine/Promise 里;执行 owner 变化后仍必须通过 Store/version 看到同一事实。
工程边界
案例可能采用与 Shadow Harness 不同的持久化粒度;我们不复制 storage schema,只吸收 state ownership 与 execution ownership 解耦。
Shadow Harness 对照
- Scheduler 是纯/近纯 decision layer:读取 state→选 ready nodes→提交 claim/transition。
- StateStore 使用 optimistic version/lease 防止两个 worker 同时推进同一 node。
验证
两个 scheduler worker 同时读取 READY node,只允许一个 claim 成功;失败方必须重新读取 state,而不是继续执行旧 snapshot。
State Store
StateStore 是 materialized current state 的持久化 port,提供版本化 read/CAS/transaction;CheckpointStore 与 EventLog 分别承担恢复切片和历史记录。
Store adapter 可以换 Postgres/InMemory,但 Runtime 看见的 version/conflict semantics 必须一致。
一次 Node 完成时需要提交哪些事实
test_auth 从 READY 进入 RUNNING,Executor 返回 exit code 0。Runtime 不应该只做:
python
node.status = "SUCCEEDED"更完整的提交路径是:
text
Scheduler admits node
→ StateMachine: READY → RUNNING
→ persist attempt/execution identity
→ Executor runs
→ normalize result
→ StateMachine: RUNNING → SUCCEEDED
→ persist output/event/checkpoint
→ update downstream indegree
→ enqueue newly-ready nodesStateStore 保存的是 Runtime truth,而 Scheduler 的 ready queue 可以是可重建的派生结构。这样进程 crash 后,不必相信内存队列仍然存在;从 durable node state + dependency graph 就能重新计算哪些节点应该 ready。
Failure Modes
Scheduler 与 StateStore 各自维护一套状态
症状: 内存 scheduler 认为 node RUNNING,数据库仍是 PENDING,或反过来。
为什么危险: crash/resume 后无法确定哪套状态是真实事实。
处理: 状态迁移通过单一 Runtime reducer/transaction contract 提交;scheduler 从 committed state 推导 ready work。
如何验证
| Case | 断言 |
|---|---|
| Scheduler 与 StateStore 各自维护一套状态 | 在 claim/commit 之间注入 crash,恢复后 ready work 只由 committed StateStore 推导,不出现重复 RUNNING。 |
关联源码
自测
- Scheduler 选中 READY node 后进程 crash。StateStore 必须记录哪些 transition,恢复时才能知道这个 node 是否真的开始过?
- 为什么 Scheduler 的并发选择与 RunStateMachine 的合法状态转移是两套相邻但不同的职责?