Pre-alpha 文档
每个 Model 与 Tool Attempt 最多 Dispatch 一次。
冻结精确 Provider、可信 Budget Admission、外部 I/O 前提交 Start、验证 Stream、保留 Tool 歧义,并在不重新 Dispatch 的前提下恢复 Terminal Write。
Claim Work 前冻结精确 Provider
Registry 是以精确 Owner/Name/Version Capability Identity 为键的不可变 Startup Snapshot。Resolution 会比较 Durable Descriptor、Startup Snapshot 与 Live Provider 的完整内容。Alias、Family Name、Endpoint Fallback 与可变 Routing 不参与恢复授权。
let mut models = ModelProviderRegistryBuilder::new();
models.register(model_adapter)?;
let mut tools = ToolProviderRegistryBuilder::new();
tools.register(tool_adapter)?;
let mut schemas = JsonSchemaRegistryBuilder::with_default_limits();
register_standard_invocation_execution_event_schema(&mut schemas)?;
register_application_schemas(&mut schemas)?;
let executor = DurableInvocationExecutor::new(
store,
schemas.build()?,
models.build(),
tools.build(),
budget_provider,
DurableInvocationExecutorOptions::default(),
)?; Budget Provider 重新加载不可变 Run Provenance 与累计持久化 Usage。Executor 从不接受不可信调用者填写的 Remaining Capacity。
只有全新持久化 Start 才是 Dispatch Authority
-
校验
检查 Fence Scope、Ledger State、精确 Provider、Budget、Deadline 与 Input Contract。
-
提交
在同一个 Fenced Transaction 中追加稳定 Start Event,并把精确 Invocation 推进到 Executing。
-
Dispatch
只有全新的
Committed结果才调用外部代码;Idempotent Start 只返回Recovered。 -
校验并完成
校验完整 Provider Evidence,再对精确 Invocation Head 提交稳定 Terminal Event。
Model 或 Tool 执行期间不保持数据库事务。Lost ACK 后复用相同 Handoff 不会重复 Dispatch 同一个物理 Attempt。
需要让顺序独立于时序时,分阶段执行 Tool I/O
普通调用方使用 execute_tool。可信有界 Coordinator 可以先调用 start_tool_attempt,只把 Fresh ToolDispatchHandoff 交给 dispatch_started_tool,随后把保留的 ToolTerminalCommitHandoff 传给 commit_tool_terminal。Duplicate Start 只返回 Recovered,并禁止 Provider I/O。
三阶段路径允许 Read-only Provider Call 重叠,同时让 Start/Terminal Fact
保持串行且具有 语义顺序;它不授权 Parallel Write。Coordinator 必须限制
Retained Payload、Settled 每个已启动 Call,并让 Child Task 随 Owner 一起
Abort。丢弃 Dispatch Handoff 只会留下 可见 Executing Evidence,绝不会产生隐式
Redispatch Authority。
Streaming 必须有持久化 Sink
Streaming Model Handoff 必须包含 ModelEventSink。Runtime
校验并累积每一个语义 Event,等待 Sink 按序接受,并要求有效 Terminal Stream
Event。Sink 必须先按 (attempt_id, sequence) 基于持久化记录去重,再对外暴露数据。
累积 Response 只有在独立 Terminal Ledger Commit 后才成为权威结果。Sequence 违规、不完整 EOF、Sink Failure、Cancellation 或 Deadline 会成为 Public-safe Error Evidence。
停止的 Write 是未知结果
Read-only Cancellation/Timeout 有已知 No-write Boundary。Write 的本地
Future 停止时,外部系统可能已经改变,因此 Executor 记录
AmbiguousExternalOutcome、ToolExternalEffect::Unknown
与 RetryAdvice::ReconcileFirst,绝不把不确定性转换成盲目 Tool
Retry。
使用权威证据解析 Unknown Attempt
ToolReconciliationHandoff::result 与 ::error 只接受绑定到精确
Unknown Invocation 与 Physical Attempt 的 Evidence。Result Evidence
必须在任何数据库 Mutation 之前通过冻结的本地 Output Schema 校验。Commit 会追加独立
Audit Event,并在 Live Fence 下原子推进 Ledger,不执行 Provider Lookup 或 Tool
I/O。
let reconciliation = ToolReconciliationHandoff::result(
live_fence,
unknown_invocation,
reconciliation_event_id,
authoritative_result,
)?;
match executor.commit_tool_reconciliation(reconciliation).await? {
ToolReconciliationOutcome::Committed { .. } => acknowledge(),
ToolReconciliationOutcome::Idempotent { .. } => acknowledge(),
} 同一 Event 的精确 Retry 会幂等收敛。Persistence Failure 会保留 Evidence Handoff; Ownership 变化时只允许重新绑定同一 Run 的 Live Fence。Network-facing Service 必须先增加 Authorization 与 Evidence-source Policy,才能暴露这个可信 Worker/Operations Boundary。
Provider 也可以实现 Reconciliation SPI,并声明与之匹配的 Status-query
Capability。reconcile_tool 只针对原 Attempt 执行一次受 Deadline
与 Cancellation 约束的 Probe。Result 或权威 Error 复用同一条原子 Commit Path;Pending 不产生 Mutation,必须转换为持久化 Delayed Retry。
let probe = ToolReconciliationAttemptHandoff::new(
live_fence,
unknown_invocation,
stable_reconciliation_event_id,
cancellation,
)?;
match executor.reconcile_tool(probe).await? {
ToolReconciliationAttemptOutcome::Resolved { invocation, .. } => {
continue_from(invocation)
}
ToolReconciliationAttemptOutcome::Pending { retry_after, .. } => {
persist_delayed_retry(retry_after)
}
} 默认 Provider 实现会 Fail Closed。若 Provider 声称支持 Reconciliation、但冻结 Descriptor 未声明 Status Query,Startup 会拒绝注册;反向组合仍可用于明确的人工 Reconciler。
保留 Terminal Evidence,而不是再调用一次
若外部 I/O 已完成但 Terminal Persistence 无法确认,Error 会持有
Payload-redacted Recovery Handoff。只能通过 commit_model_terminal 或
commit_tool_terminal 重试;两者都不执行 Provider I/O。若所有权已变化,
把同一 Run 的 Handoff Rebind 到当前 Live Fence,再由 PostgreSQL 做权威校验。
match executor.execute_model(handoff).await {
Ok(outcome) => consume(outcome),
Err(ModelAttemptExecutionError::Terminal(error)) => {
let recovery = error.into_recovery();
retry_without_provider_io(recovery).await?;
}
Err(error) => handle_pre_dispatch_failure(error),
} 只公开关联证据
通过标准注册函数安装 Schema,其稳定 Identity 为 https://stknot.com/schemas/runtime/invocation-execution-event/1.0.0。八种关闭 Operation 只暴露 Binding Kind、Invocation ID、Attempt ID 与
Intent Digest,不暴露 Prompt、Argument、Output、Error、Endpoint 或
Credential。
验证证据
PostgreSQL 16/17 Test 覆盖 Lease Takeover 后只提交一次 Terminal、无
Redispatch 与 Budget Re-evaluation;七个 Event 的有序持久化 Model Stream
与 Duplicate Suppression;以及 Timed-out Idempotent-write Tool
分别对账为经过校验的 Result 或权威 Error。组合式真实 PostgreSQL 与
Loopback MCP Test 证明 Network 完成前已有 Durable State、Lost Response、Unknown、No Redispatch、精确 Reconciliation Replay 与一次 Physical Call。使用该
独立 PostgreSQL + Loopback A2A Test 证明 Send 前已有 Durable State、
Lost-response Unknown 与 Duplicate No-redispatch。使用该 pre-alpha Surface
前请阅读完整集成与运维合约。