Skip to content

Engine Internals zh

Lex edited this page Aug 15, 2026 · 1 revision

引擎内幕

工作流跑起来时底下到底发生了什么。哪天的行为让你意外了,或者要改引擎之前,读这页。

状态机

工作流和节点状态各有声明式转换表。所有变更先过守卫;非法转换和终态违规是类型化错误(HTTP 409,不是 500)。终态不可逆,唯一例外:extend 可以重开一个在报告检查点自然完成的工作流——reporting leaf 意味着有个父智能体醒着在听。

事件溯源

所有变更是 durable dag.* 事件。投影器在发布事务内部写 SQLite 读模型——读模型不可能落后于日志。历史就是事件回放,没有日志表。一个漂移测试盯着投影器守卫和声明转换表,两边不同步就挂构建。

事件也是总线:执行循环、摘要发布器、TUI 消费同一条流。瞬态摘要事件(进度计数)故意不进 durable manifest——重算,不重放。

调度

节点在准入时持久化为 queued。拿到并发许可才创建子会话,所以大扇出不会一次性物化全部会话。波次由依赖图计算;波次内并行。排队等待计入节点截止时间。

父智能体从不轮询。唤醒是合成消息:report_to_parent 节点到终态,或工作流本身终结时送达。

失败分类

每个失败节点带一个分类:timeout(超截止时间——环境问题,任务本身没错)、exec_failed(运行时/会话层失败——模型、认证、连接、崩溃恢复丢失)、verdict_fail(跑了但破坏输出契约)。分类决定修复:换更长截止时间重跑、修配置再重跑、或重述契约。工作流级失败在唤醒摘要里归因到具体节点 id——修节点,不是重启图。

崩溃恢复

恢复是惰性的、按工作流、基于证据。重启时,残留 running 的节点对照其子会话的持久化状态和解:跑完的会话回填捕获输出;消失了的会话让工作流暂停,处置权交给父智能体(replan、resume 或 cancel)。恢复绝不自行接管或重放 provider 工作——那个决定属于被唤醒、有上下文的智能体。

修订

replan 替换节点时做标记;工作流行带 graph_rev 计数器,每次改写递增一次。视图过滤 superseded = false。过滤点设在重建输入处——被替换节点否则会以未满足依赖的身份重新进入运行图、把健康的工作流搞失败(这是真实发生过的 bug,修复由探针钉住)。终态聚合、状态输出、TUI 都走同一个过滤缝。已完成输出永远不过滤:旧修订的结果仍可解析——改写保住已经付过钱的工作。

所有权

位置权威每次检查从工作流行读目录戳,写戳只有两处:创建时(来自创建会话的持久目录)和 SessionMoved(从事件 payload 重盖,在发布事务内)。NULL 戳不匹配任何实例——设计上 fail-closed。收养和 spawn 再入闸还持有条件认领(一条 UPDATE,仅当行存在且非终态时成功),把收养和并发删除隔开。

Clone this wiki locally