Skip to content

delivery: 统一后台完成事件的 owner 路由、epoch 与消费收据合同 #160

Description

@tt-a1i

一句话结论

OpenPI 的 Direct Subagent、Background Terminal、Workflow 都已实现“完成后投递给父会话”,但分别维护三套 pending map、消费、重试、持久化与 wake 语义。

建议抽取一个薄的 completion inbox contract:生产者仍拥有终态和 artifact,inbox 只负责 owner 路由、generation/epoch、防重复消费、投递收据和 wake policy。不要把三套执行状态机合并。

固定证据

对比固定在:

  • OpenPI main@2a69d3f32994da4123f1312b7fa84ef3d6119be1
  • OMP main@151dc754e8cd9314721aa6c78a168a205a4b0e4c

OMP 当前:

  • 每个 AgentSession 用自己的 agent id 注册 delivery sink,避免所有 completion 被硬路由到第一个 top-level Session:owner-routed contract
  • delivery entry 带 Session generation;/new、switch、handoff 后旧 epoch 会被丢弃,即使 job id 被复用:epoch contract, format/enqueue fence
  • owner sink late cleanup不会删除 revival 后的新 sink;没有 live owner 时 dead-letter,不会误投给其他 Session,结果仍暂存于 job row:sink replacement, dead-letter boundary
  • sink 失败采用有界退避重试,成功后才消费结果:delivery receipt path

OpenPI 当前:

  • Direct Subagent 使用内存 pending map;auto-delivery 与 explicit wait 谁先 drain 谁消费,delivery throw 会恢复批次:subagent delivery
  • Background Terminal 使用另一套 pending map + idle batcher,并在 idle 时 followUp/triggerTurn、busy backlog 时 nextTurnterminal pending, wake policy
  • Workflow 有第三套 durable delivery plane:稳定 delivery id、per-run receipt、retry、restart restore;transport 成功但 receipt 落盘失败时采用 at-least-once recovery:workflow delivery contract, receipt/retry

为什么值得讨论

三条实现分别解决了真实竞态,但合同逐渐漂移:

  • 只有 Workflow completion 可跨 process restart 恢复;
  • Direct Subagent 会主动重新唤醒 parent,Terminal 对 busy backlog 选择 nextTurn;
  • stable identity、attempt、receipt、dead-letter、owner-lost 的表达不同;
  • Session switch / branch / resume 后 stale completion 的判定没有统一 epoch vocabulary;
  • 修过的一类竞态需要在三条路径重新证明。

共享的应是 transport/inbox 不变量,不是 producer lifecycle。

OpenPI 应保留的优势

  • WorkflowDetails、SubagentSnapshot、TerminalSnapshot 仍是各自 canonical execution facts;
  • inbox 不从 UI label 推断完成;
  • producer 自己决定何时 terminal、artifact 在哪里、取消如何结算;
  • wake policy 可按 producer 和 client capability 配置,不统一成“一完成就强制起 turn”;
  • fail closed:不确定 owner/epoch 时保留可检查状态,不误投。

建议的最小 envelope

示意:

type CompletionEnvelope = {
  deliveryId: string;
  ownerSessionId: string;
  ownerEpoch: number;
  producer: "subagent" | "workflow" | "background";
  producerId: string;
  terminalRef: unknown;
  wake: "follow-up" | "next-turn" | "producer-policy";
}

具体 API 需先确认 Pi 是否已有 completion/yield queue seam;若有,应扩展 Pi seam,而不是 OpenPI 自建第二个 Session mailbox。

必须明确的语义

  • exactly-once 是“模型可见消费”还是 transport acceptance?崩溃窗口下能否真正保证?
  • transport 成功、receipt 失败时是 at-least-once,并如何让模型识别 replay?
  • explicit wait/status 与 automatic delivery 如何原子争抢消费权?
  • owner Session switch、fork、resume、dispose、revive 时 epoch 如何变化?
  • 无 live owner 是 dead-letter、durable pending,还是迁移到新 owner?
  • client 不支持 agent-initiated turn 时如何降级为 next-turn/card?
  • 一批 completion 部分成功时如何只重试未确认 sibling?

非目标

  • 不统一三类执行状态机;
  • 不把 producer result 内联进 inbox storage;
  • 不声称分布式 exactly-once;
  • 不让 completion 自动决定 Goal/Task 完成;
  • 不强制所有 producer 采用相同 wake 行为;
  • 不把 delivery success 当 execution success。

完成条件

  • 明确 canonical execution、delivery envelope、model context、UI projection 四层边界
  • envelope 有稳定 delivery id、owner identity、epoch、producer identity 和 terminal reference
  • wait/status 与 auto-delivery 并发只产生一次模型可见消费
  • transport/receipt 失败、process crash、session switch/resume、owner dispose/revive 全部有测试矩阵
  • stale completion 不会进入新 transcript,结果仍可从 producer canonical state 找回
  • partial batch receipt 只重试未确认 envelope
  • wake policy 尊重 interactive/print/RPC/ACP client 能力
  • 迁移后删除重复机制,不能在共享层外继续保留三套消费 gate

与现有 Issue 的关系

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions