Durable Agent Runtime 与分布式系统:从一次推理到可恢复执行
研究与在线复核基线:2026-08-03。本文讨论 Coding Agent 的执行底座,不讨论如何再做一个项目,也不把工作流引擎、容器或数据库当作答案本身。目标是建立一套能解释状态、失败、恢复、副作用、资源与证据的完整运行时模型。文中严格区分三种话语:链接一手资料能够直接支持的产品/协议事实、从这些事实抽象出的工程综合、以及尚未公开的 unknown。Frontier 判断以 Codex、Claude Code 已公开的跨 surface / 云端长任务 / parallel sessions / worktrees / remote steering / automation 产品 contract,以及 pi 的极简 session/runtime kernel 为参照;Kimi Code 仅作为可读源码的 glass-box mechanism sample。Kimi 代码事实固定到公开仓库提交
29c9e2a;main后续变化不属于本文已核验范围。
0. 结论先行
Agent Runtime 的根本任务不是“让模型不断调用工具”,而是把一个概率决策者的长时间执行,编译成一串满足以下条件的系统动作:
- 每个动作有身份:知道属于哪个 session、run、turn、step、tool call 与 effect attempt;
- 每个状态有事实源:进程内对象只是缓存,崩溃后能从 durable facts 重建;
- 每个副作用有语义:区分 intent、dispatch、effect、receipt、observation 与 verification;
- 每次失败可判定:retry、resume、reconcile、compensate、replan、fail 与人工接管不是同一个动作;
- 每种资源受控制:模型、工具、CPU、内存、磁盘、网络、时间、成本、权限和人工注意力都有预算与背压;
- 每个结果有证据:Agent 的自然语言结论不能替代外部状态、artifact、测试和验收记录;
- 每个租户被隔离:身份、数据、执行、资源、网络、密钥、日志与故障域不能串扰;
- 每次恢复不制造第二个世界:旧 worker 失去所有权后,不能继续提交副作用或覆盖新 owner 的状态。
可以把可靠性目标写成:
[ \begin{aligned} \text{Durable Agent} ={}& \text{Recoverable Control State} \ &+ \text{Reconciled Effects} \ &+ \text{Replaceable Compute} \ &+ \text{Verifiable Evidence} \end{aligned} ]
其中最容易被忽视的是第二项。恢复“模型对话”不等于恢复任务:如果外部命令、Git push、数据库写入或远程 API 的结果处于未知状态,Runtime 必须先恢复世界状态,再允许模型继续决策。
1. 对象本体:先把生命周期说清楚
1.1 不要把所有东西都叫 session
| 对象 | 精确定义 | 典型身份 | 所有权 | 终止后是否保留 |
|---|---|---|---|---|
| App | 一个运行时部署或客户端进程的顶层资源域 | app_id / deployment |
platform | 配置与审计保留 |
| Surface | terminal、IDE、desktop、web、mobile、Slack 等 control/observation 入口;不是执行 owner | surface_id / device / connection |
user + control plane | connection 否;command/approval 是 |
| Automation | 可由 schedule/API/event 触发的持久工作定义;每次 firing 应产生独立 run/session lineage | automation_id + fire_id |
user/project + scheduler | 定义与 firing receipt 是 |
| Workspace | 一组代码、工具、信任、环境与存储的工作边界 | workspace_id + revision |
user/project | 通常保留或快照 |
| Session | 用户与 Agent 的持久交互/任务容器 | session_id |
user/project | 是 |
| Run | Session 的一次执行实例;可由不同 worker 接力 | run_id + epoch |
orchestrator | 是 |
| Execution environment | 实际运行工具的 local machine、SSH/devbox 或 cloud sandbox | environment_id + placement + revision |
run/platform | 通常可替换;证据保留 |
| Agent | 一个具备独立 policy/context/tool view 的决策者 | agent_id |
session | 是,至少保留事实 |
| Turn | 一次被 admission 接纳的目标或 steering 单元 | turn_id |
agent loop | 是 |
| Step | 一次“构造 context → 推理 → 执行/观察”的推进 | step_id |
turn | 是 |
| Model request | 一次具体 provider 调用与流式响应 | request_id |
step | trace/usage 保留 |
| Tool call | 模型声明的一个工具意图 | tool_call_id |
step | 是 |
| Effect attempt | Tool call 对外部世界的一次实际尝试 | effect_id + attempt |
tool executor | 是 |
| Receipt | effect authority 返回的可核验结果 | receipt_id / operation id |
evidence plane | 是 |
| Artifact | 大输出、diff、日志、截图、二进制或快照 | content hash / artifact id | workspace/evidence | 按保留策略 |
六个边界必须特别强调:
- Surface ≠ Session:terminal、phone 或 WebSocket 只是入口;断开 surface 不应隐式取消或删除 work object。
- Remote surface ≠ remote execution:手机可以控制本机进程;terminal 也可以创建 vendor-cloud task。必须单独记录 control locus 与 execution locus。
- Automation ≠ immortal chat loop:durable trigger、fire receipt、run/session 与 review result 是不同对象。
- Session ≠ process:客户端、WebSocket、worker 和 sandbox 都可以消失,Session 仍应存在。
- Turn ≠ model request:一次 Turn 可有多个 Step;一次 Step 也可能包含 provider retry,但不能因此产生两个逻辑决定。
- Tool call ≠ effect:同一个 tool call 可能没有产生 effect、产生一个 effect、产生多个子 effect,或产生了结果未知的 effect。
1.2 推荐的层级与基数
这里 Run 与 Agent 是两个正交维度:Run 表示“谁在何时推进”,Agent 表示“哪个逻辑决策者”。恢复时可以换 Run/worker,但保持 Agent identity;切换模型也不必更换 Agent identity,除非产品语义真的创建了一个新角色。
1.3 生命周期所有权表
每一层都必须回答七个问题:
| 问题 | 例子 |
|---|---|
| Identity | ID 由谁分配,是否跨恢复稳定? |
| Configuration | 配置在创建时冻结,还是动态跟随 App? |
| Resources | provider client、MCP connection、sandbox、artifact store 在哪一层共享? |
| Persistence | 哪些状态可重建,哪些必须持久化? |
| Concurrency | 允许多少 writer、turn、tool、subagent 并发? |
| Disposal | cancel、close、TTL、GC 分别销毁什么? |
| Observability | trace、metric、log 用什么稳定关联键? |
“全局单例”通常在这七个问题里至少错三个:它让一个 session 的配置、凭据、取消或日志泄漏到另一个 session,也让测试无法构造真实生命周期。
2. 形式化状态模型
2.1 Runtime 状态
定义某个 Agent 在 durable offset n 的状态:
[ S_n = (q, e, o, W, J, A, B, C, V, P) ]
其中:
q:控制状态,含 session/run/turn/step 的 phase;e:当前 owner epoch / fencing token;o:outstanding work,包括 provider request、tool intent、effect attempt、approval;W:workspace identity、base revision、dirty overlay 与环境摘要;J:durable journal offset 与 schema version;A:artifact/receipt 索引;B:多维预算向量;C:cancellation/deadline 状态;V:verification contract 与已获得证据。P:execution placement、environment identity/revision、state authority 与 control authorization policy;瞬时 surface connection 由此派生,不作为 durable owner。
事件 x_n 通过确定性 reducer 产生下一状态:
[ S_{n+1} = \delta_{v_n}(S_n, x_n) ]
v_n 是 event schema / reducer version。若 reducer 不确定、依赖当前时间、网络或随机数,则 replay 得到的不是恢复,而是另一条历史。
2.2 控制状态机
状态机的价值不在画图,而在禁止非法跃迁。例如:
Executing → Completed非法,因为缺少 observation 持久化与 verification;Cancelling → Cancelled只有在所有可控子任务已终止、不可控 effect 已被标注时才合法;Reconciling → Executing只有在确认旧 effect 未发生后才可重试;- terminal state 是吸收态,若要继续,应创建新 Turn 或新 Run,而不是把
Completed改回Running。
2.3 必须保持的不变量
- 单调日志:已确认 durable offset 不回退;修复用新 generation 或原子 rewrite,不原地静默改历史。
- 单 owner epoch:同一逻辑推进点只有一个可提交 writer;旧 epoch 的写入被存储层或 effect gateway 拒绝。
- 稳定身份:逻辑 Tool Call 重试时
tool_call_id不变;具体尝试的attempt与effect_id变化。 - 预算单调:消耗只能增加,不能因 retry、resume 或 worker 重启归零。
- 取消单调:一旦父 scope 进入 cancelling,不能再接纳新的普通子任务;只有 cleanup/reconciliation 可运行。
- terminal 吸收:完成、取消、失败之后不再追加同一 Turn 的业务 effect。
- 先事实后投影:UI transcript、缓存、搜索索引和 dashboard 都能丢失重建;事实 journal 不能依赖它们。
- 副作用闭环:每个持久化 intent 最终落在
not_dispatched | confirmed | rejected | unknown | compensated之一。 - 证据可寻址:声称使用的 receipt/artifact 必须存在、hash 匹配且授权可读。
- 租户闭包:任何状态转换不得引用另一个 tenant 的 workspace、secret、artifact 或 quota。
2.4 Budget 是向量,不是一个 max_steps
[ B = (b_{step}, b_{wall}, b_{token}, b_{cost}, b_{tool}, b_{effect}, b_{cpu}, b_{mem}, b_{disk}, b_{net}, b_{human}) ]
单一 max_steps 会掩盖真实风险:一个 Step 可以发起 20 个并行工具,消耗大量外部额度;也可能只做一次便宜检索。Runtime 应同时支持:
- hard limit:安全、合规、计费与基础设施绝不越界;
- soft limit:接近阈值时让 policy 降级、收敛或请求扩容;
- reservation:执行前预留最坏成本,结束后按实际结算;
- hierarchical charge:effect 计入 tool call、step、turn、session、tenant 多层;
- inherited deadline:子任务 deadline 不得晚于父任务;
- retry budget:不能藏在 SDK 内脱离总预算。
3. State machine、Event Log、Snapshot、Checkpoint、Replay、Resume
3.1 六个概念不是同义词
| 概念 | 它回答的问题 | 典型内容 | 不能替代什么 |
|---|---|---|---|
| State machine | 现在处于哪个合法阶段? | phase、transition、guards | 历史证据 |
| Event log / journal | 什么按什么顺序发生? | intent、result、state transition | 大 artifact、外部真相 |
| Snapshot | 某 offset 的派生状态是什么? | reducer state、indexes | snapshot 之后的事件 |
| Checkpoint | 从哪里可以安全继续? | offset + workspace ref + outstanding work + invariants | 所有历史 |
| Replay | 如何由事实重新计算状态? | events → reducer / recorded outputs | 重新执行副作用 |
| Resume | 如何取得新所有权并继续推进? | restore + reconcile + lease + next action | replay 本身 |
Snapshot 是性能优化,Checkpoint 是语义承诺。 一个内存 dump 可以是 snapshot,却不一定能安全恢复:它可能没有 workspace revision、effect receipt、owner epoch 或 schema version。
3.2 推荐持久化分层
推荐事实分工:
- journal:小、顺序化、版本化的业务事件;
- atomic document:低频整体更新的 session metadata、lease 或 config snapshot;
- blob/artifact store:大 tool output、完整 stdout/stderr、图片、diff、workspace snapshot;
- derived index:按 tenant/session/time/tool 查询的索引;
- telemetry:统计与诊断信号,不作为业务恢复事实源。
3.3 Journal 记录设计
最小 envelope:
record_id
tenant_id / workspace_id / session_id / agent_id
run_id / owner_epoch
turn_id / step_id / tool_call_id / effect_id // nullable by层级
event_type / schema_version
logical_time / recorded_at
causation_id / correlation_id / trace_id
payload_ref or payload
prev_hash / content_hash // 高保障场景
privacy_class / retention_class
关键规则:
- 序号由事实存储分配,不相信 worker 本地计数;
recorded_at用于观测,不能作为 reducer 决策输入;causation_id表示“谁导致我”,correlation_id表示“同一业务链”;- schema migration 必须可测试,unknown record 的策略要显式;
- append 成功与否必须向调用者可见。只更新内存、异步 append 失败后记录日志,会造成 acknowledged state 不 durable;
- 大 payload 存 hash/ref,且 journal append 前必须明确 blob 与 record 的提交顺序及孤儿清理策略。
3.4 Snapshot 策略
常见触发条件:
- event count / bytes 超阈值;
- Turn 结束或确认安全 checkpoint;
- 准备迁移 worker / region;
- reducer replay p95 超 SLO;
- schema major upgrade 前。
Snapshot 应携带:source_offset、schema_version、reducer_version、workspace_ref、outstanding_effects、budget_used、owner_epoch、hash。恢复流程是:
- 校验 snapshot identity 与 hash;
- 按版本迁移或选择相容 reducer;
- 从
source_offset + 1重放 journal; - 重建 derived indexes;
- 获取新 lease / epoch;
- 扫描 outstanding effects;
- reconciliation 完成后才重新 admission。
3.5 三种 replay 必须区分
| Replay 类型 | 是否再次调用 LLM | 是否再次执行工具 | 用途 |
|---|---|---|---|
| Deterministic state replay | 否 | 否 | 崩溃恢复、重建状态 |
| Observation replay | 否;读已记录 response | 否;读 receipt/artifact | 重现 UI/context/trace |
| Counterfactual / evaluation replay | 可以 | 只在隔离环境中按实验策略 | 比较模型、prompt、harness |
Temporal 的 Workflow 模型要求 orchestration code 可确定性 replay;网络、数据库、LLM 与工具这类非确定 I/O 应放进 Activity,Workflow replay 时用 Event History 中的结果推进,而非重新执行这些 I/O。其官方架构文档也说明 History Service 持久化 Workflow 的事件历史。Temporal Workflow Definition、Temporal Events and Event History、Temporal History Service。
还要避免术语误导:Temporal 的 SideEffect 是在 Workflow 中记录短小非确定计算结果的 replay helper;官方文档明确警告,失败窗口下它仍可能执行多次,因此不能拿来包装数据库写入、发消息或任意外部工具 effect。Temporal Events and Event History。
Agent Runtime 不一定采用 Temporal,但必须保留同一个原则:恢复 replay 与重新执行不是一回事。
3.6 Continue-as-new 与日志分段
无限 session 不等于无限单日志。长期执行可以:
- 保持稳定
session_id; - 创建新
run_id/ journal segment; - 把必要状态、未处理消息、budget、workspace ref 传给新 segment;
- 用 lineage 连接旧、新 run;
- 老 segment 变成只读审计历史。
Temporal 的规范把 Continue-As-New 定义为:把继续运行所需状态带入一个新的 Workflow Execution,保持 Workflow ID、生成新 Run ID 与新 Event History;旧 execution 是 execution chain 中独立的历史段,并仍受 namespace retention 约束。Temporal Continue-As-New、Temporal Events and Event History。这与 Agent 的日志分段相似但不等同:如果产品要求永久完整 transcript、effect receipt 或审计证据,必须另行定义 archive/retention contract,不能假设 Continue-As-New 自动提供永久外部事实库。分段阈值也应由 replay latency、存储限制、debug 需求与恢复语义决定。
4. Crash Consistency 与“Exactly-once 幻觉”
4.1 最危险的崩溃窗口
外部副作用的通用协议:
崩溃最危险地发生在 E 已执行、receipt 尚未 durable 之间。此时新的 worker 只看到 intent,无法通过本地历史判断 effect 是否发生。
4.2 故障窗口矩阵
| 崩溃点 | Durable facts | 外部状态 | 恢复动作 |
|---|---|---|---|
| intent 前 | 无 | 未发生 | 可重新规划 |
| intent append 后、dispatch 前 | intent | 未发生 | 由 dispatcher 状态/operation query 确认后执行 |
| dispatch 后、外部执行前 | intent + maybe dispatch | 未发生或未知 | query / dedup key;不可盲重试 |
| 外部执行后、receipt 前 | intent | 已发生但本地未知 | reconciliation;查询 operation ID/idempotency key/外部状态 |
| receipt append 后、observation 前 | intent + receipt | 已发生且已知 | 仅重建 observation,不再执行 |
| observation 后、verification 前 | 完整 effect facts | 已发生 | 恢复 verifier |
| terminal event append 前 | 已验证证据 | 已发生 | 重新计算终态并 append terminal |
4.3 Exactly-once 到底能保证什么
“消息恰好交付一次”“handler 恰好运行一次”“外部业务效果恰好发生一次”是三个不同 claim。
工程上常用的实现近似是(不是协议证明,也不是所有 authority 上都成立的保证):
[ \begin{aligned} \text{Exactly-once observable effect} \approx{}& \text{At-least-once delivery} \ &+ \text{stable operation identity} \ &+ \text{dedup at authority} \ &+ \text{durable receipt} \ &+ \text{reconciliation} \end{aligned} ]
如果 effect authority 不支持幂等键、状态查询或条件写,Runtime 无法单方面把一个任意外部副作用变成 exactly-once。它最多能:
- 保守停止并报告
unknown; - 使用业务唯一键探测;
- 设计补偿;
- 要求人工确认。
Azure Durable Functions 明确说明 Activity 是 at-least-once,完成后结果落历史之前失败可能导致再次运行,因此应尽量幂等。Durable Task Programming Model。Google Pub/Sub 的 exactly-once 也有明确边界:仅 pull subscription、区域内、成功 ack 之后不重投,且 publish-side duplicates 仍可能拥有不同 message ID。Google Cloud Pub/Sub exactly-once。这些边界说明“exactly-once”必须写完整作用域。
4.4 幂等性的六种层级
| 类型 | 例子 | 重试策略 |
|---|---|---|
| 天然幂等 | 读取文件、PUT value=7 |
可按 freshness 要求重试 |
| 条件幂等 | update where version=12 |
CAS 失败后读取并重规划 |
| 去重幂等 | 创建 PR 带稳定 operation key | 同 key 重试,参数 hash 必须一致 |
| 可交换/单调 | set-union、max watermark | 可重复合并,但要处理顺序语义 |
| 可补偿 | 创建临时分支、预留资源 | 记录 saga,补偿也可能失败 |
| 不可安全重试 | 发送无幂等支持的外部消息、物理动作 | receipt 未知时阻塞/人工处理 |
Stripe 的官方 idempotency contract 是很好的正例:服务保存首个请求的 status/body,同 key 后续返回同结果,并比较参数防止误复用;key 清理后重用又会成为新请求。Stripe Idempotent Requests。因此 idempotency key 必须包含稳定业务身份和足够长保留期,不能每次 retry 重新生成。
4.5 Fencing:lease 还不够
Lease 只能说明“根据最近观测,A 可能仍持有所有权”。在网络分区或长 GC pause 下,A 可能恢复并继续写;与此同时 B 已接管。解决 stale owner 必须有单调 epoch:
acquire(session_id) -> epoch 42
write(..., epoch=42) accepted
lease expires
new owner acquire -> epoch 43
old owner write(..., epoch=42) rejected by state/effect authority
如果只有 worker 本地 if lease_valid 检查,而 journal、sandbox control plane 或 effect gateway 不校验 epoch,就没有真正 fencing。
Kubernetes Lease 使用 holderIdentity、renewTime、leaseDurationSeconds 与 optimistic concurrency 的 resourceVersion 协调 leader;lease 过期后其他 candidate 才竞争接管。Kubernetes Leases、Coordinated Leader Election。Agent Runtime 需要在此基础上进一步把 epoch 传播到可提交副作用的边界。
4.6 Reconciliation 决策树
unknown 是正确状态,不是失败处理不完整。把 unknown 强行归类为 success 或 failure,才会制造重复 effect 或丢失 effect。
5. Queue、Scheduler、Lease、Heartbeat
5.1 两级调度:业务 admission 与计算 placement
不要用一个 FIFO 队列同时解决所有问题。
| 层 | 决策 | 关注点 |
|---|---|---|
| Logical admission | 哪个 Turn/Step 可以进入执行? | session 顺序、steering、approval、budget、conflict |
| Physical placement | 放到哪个 worker/sandbox/provider? | locality、capability、capacity、tenant fairness、region |
一个 session 内通常是 single logical writer,但工具可以在明确 conflict model 下并行。跨 session 则要做 tenant fairness,避免一个大任务占满模型并发或 sandbox pool。
5.2 Scheduler 输入
最小调度描述符:
work_id / tenant_id / session_id / turn_id
priority_class / enqueue_time / deadline
required_capabilities
resource_request {cpu, memory, disk, gpu, network, provider_slots}
estimated_cost / max_cost
locality {workspace_snapshot, region, data_residency}
affinity / anti_affinity
preemptibility / checkpointability
attempt / retry_not_before
5.3 公平性不是平均分配
推荐组合:
- tenant 级 weighted fair queue / deficit round robin;
- tenant 内按 deadline、interactive/background、age 排序;
- 每 tenant concurrency cap 与 token bucket;
- provider、sandbox、artifact 分别设 semaphore;
- admission 时估算,运行中按实际消费;
- 防 starvation 的 aging;
- retry 回到延迟队列,不立即抢占正常请求;
- 恢复 storm 单独限速。
Kubernetes API Priority and Fairness 的核心经验是:过载时既要限制 inflight,又要对请求分类、隔离与公平排队,防止一个行为不良的 client 饿死同优先级的其他 client。Kubernetes API Priority and Fairness。Agent scheduler 同理,但还要把模型配额、sandbox 启动和人工审批当作独立稀缺资源。
5.4 Lease 与 heartbeat 的含义
- Lease:到某个时刻为止,谁被允许推进;
- Heartbeat:owner/长工具仍在活跃,并可携带进度 checkpoint;
- Liveness:进程能响应,不代表工作正确推进;
- Progress:offset、processed bytes、test count 等单调变化;
- Readiness:worker 当前能否接新任务;
- Fencing:旧 owner 即使活着也不能再提交。
Heartbeat payload 应小而有界:work_id, epoch, progress_seq, last_checkpoint_ref, observed_at。不要把完整 stdout 或 context 塞进 heartbeat。
Timeout 建议分开:
- schedule-to-start:排队过久;
- start-to-close:单次 attempt 过久;
- schedule-to-close:包含所有 retry 的总期限;
- heartbeat timeout:失去进度信号;
- session idle TTL:无活动后休眠/回收;
- absolute deadline:业务最终期限。
Temporal 的 Activity 文档说明,Activity 必须 heartbeat 才能接收 cancellation;heartbeat details 还可在后续 retry 中取回,用作进度恢复。其错误处理文档同时明确 Activity 采用 at-least-once 语义:函数已完成、worker 在向服务端确认前崩溃时可能重试,因此应使用幂等键。Temporal Activity Execution、Temporal Python error handling。这说明 heartbeat 是恢复与取消协议的一部分,不只是监控 ping,但它本身不提供 effect exactly-once。
5.5 Retry storm 与 recovery storm
典型雪崩:provider 失败 → 大量 step 同时指数退避 → 同一时间窗醒来 → provider 继续过载;或 region 恢复 → 数万 session 同时恢复 sandbox 与 MCP。
控制手段:
- full jitter,不只固定指数退避;
- 按 error domain 共享 circuit breaker;
Retry-After进入调度器;- retry token bucket;
- 恢复扫描分片和速率限制;
- capacity-aware resume;
- 避免所有 session 在 TTL 整点到期;
- provider 与 tool 的预算隔离,防一个故障域拖垮另一个。
5.6 Preemption
只有 checkpointable work 才适合安全抢占。优先级高不等于立即杀掉低优先级任务:
- 发出
pause_requested; - 停止接纳新 child work;
- 等待当前 atomic effect / tool 安全点;
- flush journal 与 artifact;
- 写 checkpoint;
- 释放 lease 与资源;
- 超过 grace period 才强制终止,并把 outstanding effect 送 reconciliation。
5.7 Automation / Routine 的 firing contract
Scheduled work 至少拆成五个对象:
automation_definition
trigger_event(fire_id, scheduled_for, received_at, payload_ref)
run/session(run_id, environment_revision, credential_policy)
terminal_receipt(result, evidence_refs, retry_lineage)
review_item(owner, state, expires_at)
Scheduler 必须显式定义:同一 fire_id 的 dedup、missed fire 是否 catch up、时区/DST、jitter、并发重叠策略(skip / queue / replace / parallel)、失败 retry、credential/config 是触发时 snapshot 还是运行时 resolve、daily budget 与人工 review TTL。外部 API/GitHub payload 应作为 untrusted data,不得自动扩张预存 prompt 的 authority。
Claude Code Routines 的公开 contract 是每次 firing 创建新 cloud session,可由 schedule、API 或 GitHub event 触发;Codex app Automation 的结果进入 review queue。这些产品事实支持“trigger definition → run → review result”的对象拆分,但两家未公开 trigger delivery/transaction backend,因此不能声称 exactly-once firing。Claude Code Routines、Introducing the Codex app。
6. Cancellation:一种分布式协议
6.1 Cancel 不是 kill
取消至少有四个阶段:
requested -> propagated -> acknowledged -> quiesced
\-> unknown_effects -> reconciled
requested:事实源记录取消意图;propagated:provider、tool、subagent、sandbox 收到 signal;acknowledged:子系统确认不再开始新业务动作;quiesced:进程树、流、文件句柄与 reservation 已清理;reconciled:不可取消/未知外部 effect 得到最终分类。
UI 断线绝不能隐式等于 cancel。网络层连接、订阅层 stream、业务 Turn 是三个生命周期。
6.2 Structured concurrency
父 scope 应拥有所有 child work:
Turn AbortScope
├── Model Request
├── Tool Call A
│ ├── Process Group
│ └── Output Pump
├── Tool Call B
└── Sub-agent Run
规则:
- child deadline ≤ parent deadline;
- parent terminal 前,所有 child 必须 terminal 或被显式 detached;
- detached background task 获得新的 durable owner,而非遗留 Promise;
- cancel reason 保真传播;用户取消、budget、preemption、shutdown、policy veto 分开编码;
- cleanup 有独立短预算,不能无限阻塞 terminal;
- force kill 后默认进入 effect reconciliation。
6.3 不同对象的取消语义
| 对象 | 取消动作 | 可能遗留 |
|---|---|---|
| LLM stream | abort request、关闭 decoder、补齐 wire terminal record | provider 仍计费、partial tokens |
| Shell | SIGTERM 到 process group,grace 后 SIGKILL | daemon、远程子进程、partial files |
| File edit | 停在 temp file,atomic rename 前可丢弃 | rename 后 effect 已发生 |
| Git push | 尽量中断连接 | server 端 ref 可能已更新 |
| HTTP POST | abort socket | server 可能已提交 |
| Sub-agent | cancel child run,等待 checkpoint | child effect unknown |
| Approval wait | 撤销 pending request | 迟到 approval 必须被 epoch/terminal state 拒绝 |
7. Streaming 与 Backpressure
7.1 四条流不要混在一起
- Provider wire:token、thinking、tool-call delta;要求协议合法与顺序正确。
- Durable domain events:step/tool/turn 的事实;低频、可恢复。
- Client control commands:prompt、steer、follow-up、approval、cancel;要求身份、授权、ordering、dedup 与 admission receipt。
- Client presentation stream:UI delta、进度、日志 tail;允许合并、抽样与断线重连。
如果每个 token 都进入全局 durable journal,成本与 replay 会爆炸;如果一个 token 都不持久化,断线后用户可能看不到已产生的部分结果。常见折中:
- provider delta 在内存 ring buffer;
- 按 chunk / 时间窗写 partial artifact;
- assistant message 完整关闭时写 durable canonical record;
- tool-call args 必须在执行前解析、校验并 durable seal;
- client stream 用 monotonic
stream_seq和 resume cursor; - UI reconnect 优先读取 canonical projection,再追增量。
Remote steering 不能复用 presentation cursor 充当 command identity。客户端应提交稳定 command_id、target session/run、observed offset/epoch 与 input source;Runtime 在 command durable/admitted 后返回 receipt。重连重投相同 command_id 时只能得到原 receipt 或明确 rejection,不能悄悄形成第二个 Turn。pi 对 steer 与 followUp 的区分、Codex/Claude Code 的跨设备 steering 都说明 queued input 是领域语义,不是 socket 实现细节。pi RPC @ c6eb628、Work with Codex from anywhere、Claude Code Remote Control。
7.2 背压链路
必须为每段定义:buffer 上限、high-water mark、overflow policy、可否 drop、是否可重放。自然语言 token 可以合并;tool-call JSON delta 不能随意丢;stderr tail 可 ring-buffer,但完整日志要外置 artifact。
gRPC 的 flow control 明确指出:应用 write 返回不代表数据已发到网络;框架会根据 receiver capacity 等待,手动双向同步读写还可能死锁。gRPC Flow Control。Agent Runtime 要把这种传输层背压继续向上翻译为 provider pause、chunk coalescing、UI degradation 或任务 admission 限制,而不是无限堆内存。
7.3 Slow consumer 策略
| 数据 | 慢消费者策略 |
|---|---|
| assistant text delta | coalesce;必要时跳到最新 canonical snapshot |
| progress heartbeat | 丢旧留新 |
| state transition | 不丢;按 cursor replay |
| tool stdout | UI tail ring buffer;完整内容 artifact |
| permission request | 不丢;带 deadline,确保单次响应 |
| error / terminal | 不丢;独立高优先级通道 |
| telemetry | batch、sample、限速;不能阻塞业务 |
8. Brain / Hands / Evidence:最稳定的三边界
8.1 分离模型
8.2 为什么这比“一个大容器”更可靠
| 耦合设计的问题 | 解耦后的责任 |
|---|---|
| sandbox 死亡等于 session 丢失 | sandbox 可替换;session facts 外置 |
| harness 必须与用户网络同处 | tool/sandbox 通过窄执行接口连接 |
| 模型能读取容器内凭据 | secret broker/proxy 在 sandbox 外注入能力 |
| WebSocket 断线无法区分 harness 与 container 故障 | brain、hands、stream 独立 health/trace |
| context compaction 删除了唯一历史 | session log 保存可恢复事实,harness 自由投影 |
| 模型升级被旧 scaffolding 绑住 | brain policy 可替换,hands/evidence contract 稳定 |
Anthropic 2026 年 Managed Agents 的公开架构将 session 定义为 append-only event log、harness 定义为 loop、sandbox 定义为执行环境,并把 brain、hands、session 解耦;harness 崩溃后可由新实例读取 session log 唤醒,sandbox 死亡则作为 tool error 处理并可重新 provision。Anthropic Managed Agents。其更重要的判断是:durable session 保存可恢复事实,但不替未来 harness 决定模型应该看到哪些 context。
8.3 最小稳定接口
SessionStore:
append(session, expected_offset, events) -> new_offset
read(session, from, limit) -> events
snapshot(session, offset) -> snapshot_ref
ExecutionEnvironment:
provision(spec, workspace_ref, epoch) -> env_handle
execute(env, effect_intent, epoch, signal) -> receipt
inspect(env) -> env_state
checkpoint(env) -> workspace_ref
destroy(env, reason) -> destroy_receipt
EvidenceStore:
put(content, privacy, retention) -> artifact_ref
get(ref, authorization) -> content
verify(ref, hash) -> bool
接口要表达 timeout、cancel、idempotency、fencing 与 partial result;execute(name, input) -> string 可以是概念示意,但生产 contract 不能把所有错误和 effect receipt 压成字符串。
9. Surface、Execution Placement 与 Local/Remote/Cloud Runtime
9.1 先消除“remote”一词的三重歧义
| 正交轴 | 可能取值 | 必须回答的问题 |
|---|---|---|
| Control surface | terminal / IDE / desktop / web / mobile / Slack / automation | 谁提交 command、谁可 approve、连接断开后 work 是否继续? |
| Execution placement | local machine / SSH-devbox / vendor cloud sandbox | 文件、进程、工具与凭据实际在哪?owner 是谁? |
| State authority | local journal / remote control plane / vendor cloud session store | 哪个事实源决定 task、offset、approval 与 terminal state? |
| Workspace source | live checkout / remote worktree / fresh clone / snapshot+overlay | base revision、dirty overlay、merge owner 与销毁策略是什么? |
Codex 手机端和 Claude Code Remote Control 都证明“remote surface → local/remote-machine execution”是成立的;Codex cloud 与 Claude Code on the web 则是“任意 surface → vendor-cloud execution”。这两种拓扑有不同的 liveness、credential、recovery 与 data-residency contract,不能都叫 remote session 后混为一谈。Work with Codex from anywhere、Claude Code Remote Control、Claude Code on the web。
9.2 四种 execution placement
| 维度 | Local machine | Managed remote / SSH devbox | Vendor cloud task | Hybrid / split tools |
|---|---|---|---|---|
| 代码位置 | 用户 live checkout | 持久 devbox checkout/worktree | fresh clone/snapshot/overlay | 多侧各有 revision |
| liveness | 睡眠/关机即受影响 | 取决于远程主机生命周期 | control plane 可另行管理 | 任一侧失联都可能 partial |
| 凭据 | 易接触用户凭据 | 企业主机身份/agent forwarding 风险 | broker/短期 capability | 两侧 authority 最复杂 |
| 隔离 | 依赖本机 sandbox | 依赖 devbox/host policy | container/gVisor/microVM 等 | 两侧均需隔离 |
| 恢复 | local journal + workspace | 主机恢复或外置 checkpoint | journal/workspace/receipt 外置 | 必须同步事实与 effect |
| 数据驻留 | 主要留在本机 | 进入企业远程环境 | 进入 vendor region | 必须逐 tool 标注跨界 |
| 可观测 | 本地 debug 强 | 可集中采集 | control-plane trace 强 | 必须端到端关联 |
9.3 Local runtime
适合:访问大型本地仓库、私有依赖、设备/模拟器、低延迟交互。关键风险:
- Agent 与用户进程共享机器;
- shell 环境和 dotfiles 不可复现;
- 睡眠、VPN、网络切换、磁盘满;
- 用户同时修改文件;
- 凭据与 SSH agent 暴露;
- App 升级时 session migration。
本地设计应把用户机器当不可靠且高价值环境:workspace root 白名单、realpath/symlink 检查、最小 env、默认网络策略、process group、atomic file edit、pre-edit hash、用户变更冲突检测、本地 durable journal 与可导出的脱敏 debug bundle。
9.4 Managed remote 与 vendor-cloud runtime
Managed remote machine 适合复用企业 devbox、私有依赖和长期环境;vendor-cloud task 适合并行、fresh environment、集中观察与可替换 worker。前者未必是 cattle,后者也不必保留原进程;共同的关键设计是:
- control plane 不持有用户代码明文的无界日志;
- vendor-cloud sandbox 应可替换;managed devbox 即使较持久,也不能让正确性依赖 host affinity,workspace checkpoint 与 session facts 仍需明确归属;
- image/toolchain 可寻址、可复现;
- repo credential 通过短期、窄权限代理;
- egress deny-by-default + allowlist/proxy;
- cold/warm pool 与 tenant 隔离;
- environment dead 之后根据产品承诺从 snapshot + receipts 恢复;若公开 contract 只承诺重新打开 session,就不能擅自宣称 mid-effect recovery。
9.5 Hybrid runtime
Hybrid 只有在 effect routing 显式时才可靠。每个 tool 声明 execution locus:
local_only | remote_only | prefer_local | prefer_remote | split
并记录:代码 revision、input hash、环境 image、tool version、locus、result hash。否则同一个 pytest 在本地通过、远程失败时,没有足够证据解释差异。
Hybrid 的困难不是 RPC,而是共享世界的一致性:
- 本地未提交修改如何同步?
- 远程生成 diff 如何避免覆盖本地新修改?
- 哪边拥有 Git branch/ref?
- 远程 tool receipt 如何投影到本地 context?
- cancel 时两侧是否都 quiesced?
- 本地离线后远程是否允许继续产生外部 effect?
10. Sandbox、Container、Userspace Kernel、microVM、Worktree
10.1 Workspace isolation 与 security isolation 不同
- Worktree:隔离 Git index/HEAD 与工作目录,解决并发修改和可验证性;不是安全边界。
- Container:namespace/cgroup/filesystem isolation;共享 host kernel。
- Userspace kernel(如 gVisor):拦截并重新实现大量 Linux syscall,降低直接 host-kernel attack surface;有兼容性与 syscall overhead。
- microVM(如 Firecracker):独立 guest kernel + KVM,隔离更强;启动、镜像、内存与运维成本更高。
10.2 选择矩阵
| 方案 | 隔离强度 | 兼容性 | 启动/密度 | 适用场景 | 不能解决 |
|---|---|---|---|---|---|
| 进程 + 权限 | 低 | 最高 | 最快 | 可信本地工具 | 恶意代码、kernel attack |
| 普通容器 | 中 | 高 | 高密度 | 内部可信 workload | 共享 kernel 风险 |
| gVisor | 中高 | 中高 | 较高密度 | 多租户不可信代码 | side channel、上层控制面漏洞 |
| microVM | 高 | 高 | 较高成本 | hard multi-tenancy | host/hardware漏洞、错误 egress |
| 独立 VM/host | 很高 | 高 | 最贵 | 极高保障租户 | 身份、应用逻辑、供应链问题 |
gVisor 官方文档说明其 Sentry 是用户态 application kernel,sandbox workload 不直接把 syscall 传给 host kernel;代价是 Linux 接口重实现造成的兼容性和 syscall 性能成本,并且不防 Spectre 类 side channel 或 sandbox 内应用自身漏洞。gVisor Security Introduction。
Firecracker 以 KVM/microVM 为隔离边界,生产建议配合 jailer 的 cgroup、namespace、seccomp 与降权;在其“不可信多租户代码”威胁模型下,官方强烈建议每个 Firecracker process 只服务单一 tenant,并说明 egress 过滤仍由 host 负责。Firecracker Production Host Setup、Firecracker Design。这是威胁模型下的部署建议,不是 microVM 自动具备的租户语义;更强沙箱也不意味着网络、密钥和控制平面自动安全。
10.3 Sandbox spec 应可寻址
image_digest
kernel/runtime version
cpu/memory/pids/disk/io limits
mounts {source_ref, target, mode}
network policy / DNS policy / proxy
toolchain lockfile / package cache policy
secret capabilities, never raw secret values
workspace base revision + overlay ref
tenant / session / epoch labels
ttl / idle timeout / checkpoint policy
只记录 ubuntu-latest 或 node:latest 无法重现历史运行。
10.4 Worktree 的正确边界
Git 官方文档说明 linked worktree 共享仓库的大部分对象,但拥有独立 HEAD、index 等 per-worktree 文件;worktree metadata 可 lock、prune、repair。Git Worktree。Agent 平台应在其上补足:
- task → worktree identity 与 base commit;
- 单 branch 单 writer;
- per-worktree ports、DB、cache、logs、metrics;
- dirty state / untracked files 作为 checkpoint;
- cleanup 前先保存需要的 artifact;
- stale worktree GC 有 lease 与保留策略;
- submodule、LFS、sparse checkout 和 shared repo maintenance 的已知限制。
OpenAI 2026 Harness Engineering 报告其应用可按 worktree 启动独立实例,并为每个 worktree 暴露临时 logs、metrics、traces,任务结束后一起回收;公开经验还显示单次 Codex run 可持续六小时以上。OpenAI Harness Engineering。这里 worktree 的价值是“隔离且可观测的验证环境”,不只是避免 Git checkout 冲突。
10.5 Workspace snapshot
至少区分:
- base:仓库 commit / immutable image;
- overlay:Agent 产生的修改;
- external mutable state:数据库、服务、package cache;
- ephemeral:进程、socket、PTY、内存;
- evidence:diff、test output、screenshots、logs。
恢复不应假装可以 snapshot 一切。通常应恢复 base+overlay,重建进程和服务,再用 health/verification 校准。对外部数据库要用独立 snapshot/fixture 或显式环境 contract。
11. Long-running Agent:可续接性比上下文长度重要
11.1 三种“长”
| 类型 | 核心问题 |
|---|---|
| 长 wall-clock | 等待构建、审批、外部系统、夜间任务 |
| 长 decision horizon | 多轮探索、实施、验证、修复 |
| 长 context horizon | 信息超过单模型窗口,需要投影/压缩/检索 |
它们需要不同机制。长上下文不能替代 durable wait;durable wait 也不能替代目标与证据交接。
11.2 可续接 checkpoint
一个高质量 handoff 至少包含:
goal + acceptance criteria
constraints + user decisions
current plan / completed / remaining / blocked
workspace base + current revision + dirty overlay
commands run + key receipts
verification status + failing evidence
outstanding effects / approvals / background tasks
budget used / remaining / deadline
next safe action + why
journal offset / run lineage / schema version
不要只保存自然语言 summary。它会丢失精确文件状态、test receipt、effect operation ID 与 budget。结构化 checkpoint 保存事实,summary 只是 context projection。
11.3 交接协议
11.4 长任务常见认知失败
- one-shot:一开始做太多,context 结束时留下半成品;
- false completion:看到已有进度就宣布完成;
- progress amnesia:重复探索已验证路径;
- stale plan:计划没有随证据更新;
- context handoff loss:compaction 丢掉约束;
- environment drift:下一 run 的依赖、端口、数据不同;
- checkpoint illusion:有 Git commit,却没有测试与外部 effect 状态。
Anthropic 2025 的长期 Agent 实验显示,仅有 compaction 仍会出现 one-shot、半实现与提前完成;其解决方向包括初始化环境、结构化 feature list、progress artifact、Git checkpoint、增量推进与端到端验证。Effective Harnesses for Long-running Agents。这些做法是当时模型/任务上的公开证据,不应被固化为永远必需的 scaffolding;新模型上必须做消融。
12. Multi-tenant Isolation 与 Noisy Neighbor
12.1 七个隔离面
| 隔离面 | 必须隔离的对象 | 常见失败 |
|---|---|---|
| Identity | user、service、agent delegation | agent 继承过宽用户权限 |
| Control plane | session metadata、queue、lease、config | tenant 可枚举他人任务 |
| Data | repo、journal、artifact、cache、backup | content hash 全局可猜即越权读取 |
| Compute | CPU、memory、pids、GPU、sandbox | fork bomb / OOM 影响其他租户 |
| Network | ingress、egress、DNS、metadata service | SSRF、横向移动、DNS rebinding |
| Secret | provider key、Git token、MCP OAuth | secret 进入 sandbox/env/log |
| Observability | logs、trace、metrics、debug bundle | 高基数字段或内容泄露 |
Namespace 只是命名/管理隔离,不自动等于 hard tenancy。Kubernetes 官方多租户指南明确指出:namespace、RBAC、quota、NetworkPolicy、storage、node isolation 与 sandbox 必须组合;默认 Pod 网络可互通,container 共享 kernel,hard multi-tenancy 可能需要 userspace kernel、VM、独立 control plane 甚至独立 cluster。Kubernetes Multi-tenancy。
12.2 每租户资源 contract
- concurrent sessions / agents / tool calls;
- queued work 与 journal write QPS;
- token/cost daily and burst quota;
- CPU/memory/disk/pids/network;
- artifact bytes 与 retention;
- provider/model allowlist;
- sandbox class 与 region;
- max log/trace cardinality;
- human approval load。
Quota 只限制“最多多少”,fair scheduler 决定“争用时谁先”。两者缺一不可。
12.3 Cache isolation
最容易漏掉的跨租户面:
- prompt prefix cache;
- repository embedding / symbol index;
- package/build cache;
- container image layer;
- DNS / HTTP proxy cache;
- tool result cache。
每个 cache entry 都要有 security partition key。内容相同不代表授权相同;content-addressed storage 也必须在读取时校验 tenant/session authorization。
12.4 Secret broker
推荐能力模式:
effect intent
-> policy checks tenant/session/tool/resource/action
-> broker obtains short-lived credential
-> proxy performs narrow operation
-> sandbox receives receipt, never raw credential
短期 token 不是全部答案:若 token 仍进入可执行不可信代码的环境,Agent 可以在 TTL 内外传。更强边界是让 credential 与 sandbox 物理不可达,只暴露窄代理操作。Anthropic Managed Agents 公布的 Git/MCP 路径采用 sandbox 外 vault/proxy,明确把 token 与不可信生成代码分离。Anthropic Managed Agents。
13. 可恢复性与证据链
13.1 “恢复成功”的分级
| 级别 | 含义 |
|---|---|
| R0 | 进程重启,任务丢失 |
| R1 | 恢复 transcript,但 workspace/effect 不保证 |
| R2 | 恢复 loop state 与 workspace checkpoint |
| R3 | outstanding effects 可 reconcile,budget/取消/approval 保真 |
| R4 | 跨 worker/region 接力,旧 owner 有 fencing,证据链完整 |
| R5 | 在目标 SLO 内自动恢复,并通过 fault injection 持续验证 |
很多“支持 resume”的产品只到 R1:重新把消息发给模型。对 Coding Agent,R3 才开始接近工程可靠性。
13.2 Evidence chain
每条边都应有 causation_id;每个大对象有 hash。终态至少能回答:
- 根据哪个用户目标与版本化验收标准?
- 模型做了哪些决定,使用了什么 context/tool catalog/model config?
- 哪些副作用实际发生?谁授权?
- 哪个 workspace revision 被验证?
- verifier 运行在什么环境、执行了哪些命令、exit code/输出是什么?
- 哪些项未验证或状态未知?
13.3 Journal、Trace、Audit、Transcript 的区别
| 数据 | 目的 | 完整性 | 内容敏感度 | 是否事实源 |
|---|---|---|---|---|
| Domain journal | 恢复业务状态 | 高 | 高 | 是 |
| Distributed trace | 定位延迟/因果 | 采样或部分 | 中高 | 否 |
| Security audit | 谁在何时授权/访问 | 高 | 中 | 对审计事件是 |
| Transcript | 用户体验 | 投影 | 高 | 否 |
| Metrics | 聚合 SLO/容量 | 聚合 | 低 | 否 |
| Debug bundle | 离线诊断 | 按需 | 极高 | 否 |
“trace 可 replay”通常只是指诊断重放,不应取代 domain journal。反之,journal 也不适合承载所有 span、token delta 和高频系统指标。
13.4 Tamper evidence 与真实性
高保障场景可使用:
- append-only/WORM retention;
- record hash + previous hash;
- artifact content hash;
- signer identity / service attestation;
- verifier environment digest;
- clock source 与 receipt timestamp;
- access audit。
但 hash chain 只证明“记录未被静默改动”,不证明工具输出是真、verifier 覆盖充分或模型结论正确。真实性仍依赖 effect authority、隔离环境和验收器。
14. 故障矩阵
| 故障 | 可观测症状 | 不正确处理 | 正确控制面 | 恢复后的证据 |
|---|---|---|---|---|
| orchestrator crash | stream 中断、lease 不续 | 从头重跑 | 新 owner 获取 epoch,snapshot+tail replay | run lineage、old/new epoch |
| journal append 失败 | UI 已显示,恢复后消失 | 只 log error | ack 前必须 durable;或明确 degraded/fail | append error、last durable offset |
| journal 尾部半写 | parse error | 丢整个 session | checksum/record framing、截断到 last good、repair event | repair generation、bad offset |
| unknown event schema | restore 失败/状态缺 | 无条件跳过 | 按兼容等级:skip+alarm、migration 或拒绝恢复 | schema version、skipped record |
| snapshot corrupt | restore hash mismatch | 使用部分 snapshot | 回退前一 snapshot + replay | selected snapshot、verification |
| reducer nondeterminism | replay state 不同 | 接受新状态 | replay test、版本化、阻止发布 | state hash divergence |
| lease split-brain | 两个 worker 推进 | 相信本地 lease | epoch fencing at write/effect boundary | rejected stale epoch count |
| provider timeout | 无 model receipt | 无限 retry | bounded retry + same logical request lineage | attempts、cost、error code |
| provider 返回后崩溃 | response 可能已计费 | 重新请求且不记录 | 若 response 未 durable,只能按 contract 决定重试;计费单独核对 | provider request id、usage unknown |
| partial tool-call stream | JSON 不完整 | 猜参数执行 | 不执行;写 interrupted message/tool-call terminal | partial artifact、parse error |
| tool dispatch 丢 ack | intent outstanding | 新 key 重试 | query/same idempotency key/reconcile | operation ID / unknown |
| shell 父进程被杀 | child daemon 继续 | 只杀 PID | process group/cgroup + post-kill scan | remaining pids、kill receipts |
| disk full | journal/artifact 写失败 | 丢 output 继续 | reserve、backpressure、fail before effect when needed | disk metric、write result |
| artifact upload 后 journal 失败 | orphan blob | 永久泄漏 | pending namespace + TTL GC / two-phase reference | orphan GC record |
| journal 写后 artifact 失败 | dangling ref | 继续投影 | artifact state pending/failed,禁止完成 | artifact error |
| sandbox OOM | tool exit ambiguous | 当普通 tool error 重试 | classify infra vs workload;checkpoint/reconcile | OOM reason、resource usage |
| node lost | heartbeats停止 | 立即双跑 | lease expiry + fencing + controlled resume | node/lease transitions |
| network partition | old worker still active | 只靠 cancel RPC | lease/fencing,old writes rejected | stale commit rejects |
| MCP disconnect | tool unavailable | 重放所有调用 | reconnect discovery;仅按 effect semantics 重试 | server version、call state |
| user cancel during POST | client abort | 标 cancelled 且假设未执行 | cancelling → reconcile | remote operation status |
| late approval | 已 cancel 后到达 | 继续执行 | terminal/epoch guard 拒绝 | approval rejected reason |
| UI disconnect | 用户看不到进度 | cancel session | stream 可重连、业务继续 | cursor、last canonical state |
| remote steer ack 丢失 | 用户重发、形成两个 Turn | 按 socket message 每次新建 | stable command ID + admission receipt + observed epoch | original/replayed command receipt |
| automation fire 重复/漏投 | 重复 PR 或计划任务未运行 | 假设 cron exactly-once | stable fire ID、dedup、misfire/overlap/retry policy | trigger receipt、run lineage |
| slow UI | 内存增长 | 无界 buffer | coalesce/drop policy + durable terminal | dropped/coalesced counters |
| provider outage recovery | 同时 retry | 固定 backoff | jitter、breaker、retry budget | breaker state、retry queue |
| region recovery storm | sandbox 冷启动爆发 | 全量 resume | 分片扫描、capacity gate、priority/fairness | recovery backlog age |
| dirty workspace conflict | 覆盖用户改动 | force checkout/reset | expected hash/CAS、暂停并请求决定 | conflict diff、base/current hash |
| stale verifier | 测试过期 | 以 pass 宣布完成 | verifier version + contract revision | test digest、coverage limits |
| secret in logs | telemetry 泄露 | 事后删 dashboard | sandbox 外 broker、redaction、content opt-in | access/redaction audit |
| tenant noisy neighbor | p99 延迟/oom | 全局加机器 | quota+fair queue+isolation | per-tenant saturation |
| GC 删除活跃 workspace | resume 失败 | 重新 clone 丢 overlay | lease/retention/refcount + tombstone | GC decision record |
故障处理应按照“事实是否已提交、effect 是否可知、owner 是否仍有效、预算是否允许”决策,而不是按照异常类名简单 retry。
15. Observability:看到真正的控制路径
15.1 Trace 拓扑
invoke_agent(session_id, run_id, epoch)
└── turn(turn_id, admission_kind)
├── context.materialize(step_id)
├── chat(request_id, attempt)
│ └── provider.http
├── authorize(tool_call_id)
├── execute_tool(tool_call_id, effect_id, attempt)
│ ├── sandbox.exec / mcp.call / fs.edit / git.push
│ └── artifact.write
├── reconcile(effect_id)
├── verify(verifier_id, workspace_revision)
└── checkpoint(offset, workspace_ref)
截至 2026-08-03,OpenTelemetry GenAI 语义约定已覆盖 invoke_agent、chat、execute_tool 等 operation,并定义 token、model、finish reason 等属性;官方示例的 span tree 也是顶层 invoke_agent,下挂 model 与 tool spans。OpenTelemetry GenAI Observability、GenAI semantic attributes。但这些约定仍处于 active development,不能当作跨厂商稳定不变的最终 contract;内部 domain IDs、effect semantics 与隐私策略仍须由 Runtime 自己定义。
15.2 关键结构化字段
每个 log/span/event 只带其层级必要的稳定键:
tenant_id (内部不可逆 ID)
workspace_id / session_id / agent_id
run_id / owner_epoch
surface_id / command_id / input_source
automation_id / fire_id / scheduled_for
execution_placement / environment_id / environment_revision
turn_id / step_id / request_id / tool_call_id / effect_id
event_type / state_from / state_to / reason_code
attempt / queue_name / worker_id / sandbox_id
model/provider/tool/version
budget_reserved / budget_used
journal_offset / checkpoint_ref / workspace_revision
duration_ms / queue_delay_ms / bytes / token counts
error_type / retryable / reconciliation_state
不要默认记录 prompt、源码、绝对路径、tool arguments/results、token、email 或 secret。OpenTelemetry 的官方示例也明确指出内容捕获默认关闭,因为 prompt 与 tool arguments 可能敏感;metadata 与内容应分开授权和保留。OpenTelemetry GenAI Observability。
15.3 Runtime RED/USE 指标
Rate / Errors / Duration:
- turn/step/tool/effect started/completed/failed/cancelled;
- queue delay、run/step/tool/model duration;
- retry rate、retry success、wasted retry;
- reconciliation backlog、unknown effect age;
- resume count、resume latency、resume failure;
- journal append/flush/replay latency;
- stream reconnect、dropped/coalesced delta。
Utilization / Saturation / Errors:
- worker/provider/sandbox slot utilization;
- queue depth、oldest age、tenant fairness lag;
- CPU/memory/disk/pids/network;
- artifact/journal throughput与错误;
- lease renewal lag、stale epoch rejects;
- per-tenant quota consumption;
- open file/process/PTY count。
15.4 推荐 SLO
不能只设“服务 99.9% 可用”。Agent Runtime 至少按以下用户可感知承诺定义:
| SLO | 示例定义方式 |
|---|---|
| Admission | p99 交互 Turn 在目标时间内被接纳或明确拒绝 |
| Cross-surface command | 同一 command ID 重投不产生第二次 admission;过期 epoch/approval 被拒绝 |
| Automation fire | trigger-to-start、漏投/重复、overlap policy 与 review delivery 满足 contract |
| Durable acknowledgement | 已向用户确认的输入/决定在恢复后不丢失 |
| Resume | 可恢复故障后,p95 在目标时间内回到 safe-to-progress |
| No duplicate harmful effect | 高风险 effect 的重复可观测发生率低于阈值 |
| Cancellation | p95 可取消 child 在目标时间内 quiesce;unknown effect 单独计 |
| Queue fairness | 每 tenant oldest-age / service share 满足权重 contract |
| Evidence completeness | terminal success 具备要求 receipt 的比例 |
| Workspace integrity | 未授权覆盖/跨任务污染为零容忍 incident |
| Isolation | 跨租户数据/secret 泄露为零容忍 incident |
15.5 Error budget 不应掩盖高严重度事件
普通 provider transient failure 可以进入可用性 error budget;跨租户泄露、重复付款、未授权 push 等不可用平均成功率稀释。安全与副作用完整性需要独立 incident SLO / zero-tolerance guardrail。
16. Eval 与 Fault Injection
16.1 Runtime eval 不是只看任务 pass rate
评测矩阵:
| 维度 | 指标 |
|---|---|
| Outcome | verified completion、regression-free、用户接受 |
| Durability | state loss、resume success、replay equivalence |
| Cross-surface control | command dedup/ordering、approval freshness、reconnect continuity |
| Automation | fire dedup、misfire、overlap、trigger-to-start、review receipt completeness |
| Effect safety | duplicate、unknown、reconciliation success、compensation |
| Control | cancel latency、budget overshoot、deadline adherence |
| Efficiency | wall time、compute/token/cost、checkpoint overhead |
| Fairness | tenant share、tail latency、starvation |
| Isolation | escape、cross-tenant read、secret exposure、noisy neighbor |
| Evidence | receipt completeness、artifact integrity、trace correlation |
16.2 必做的故障注入点
对每个边界,在“前/中/后”杀进程或断网:
- journal append / flush;
- snapshot write / rename;
- provider response stream;
- tool intent append;
- effect authority commit;
- receipt append;
- artifact upload;
- workspace checkpoint;
- lease renewal / owner handoff;
- remote steer/approval admission 与 ack;
- automation trigger accept/dedup/enqueue;
- local/SSH/cloud environment disconnect or eviction;
- cancel propagation;
- UI stream ack;
- verifier start/result。
故障注入后断言:
- reducer state 与无故障基线等价,或进入显式 degraded/unknown;
- 无重复有害 effect;
- budget 不重置;
- old epoch 写入被拒绝;
- terminal claim 与 evidence 一致;
- tenant isolation 未破坏;
- recovery 在 SLO 内且不会引发 storm。
16.3 Replay testing
- golden journal → state hash;
- 新 reducer 对历史 journals 的 backward compatibility;
- random event prefixes + crash + resume;
- duplicate/reordered/corrupt record fuzz;
- snapshot N + events N+1..M 与 full replay 结果一致;
- old/new version mixed worker;
- unknown event 与 partial migration;
- property:terminal absorbing、budget monotonic、one owner、effect closure。
16.4 Chaos cohort
不要只随机杀 Pod。按真实 failure cohort 设计:
- provider 429/5xx/slow stream;
- artifact store 高延迟/磁盘满;
- sandbox OOM/eviction/node loss;
- MCP capability 变化/transport 断连;
- clock skew/lease delay;
- tenant burst 与恶意 fork bomb;
- client reconnect storm;
- late approval / double submit;
- external API 接收请求但丢 response。
17. 关键设计决策表
17.1 自建 journal 还是 durable workflow engine
| 条件 | 轻量 journal + state machine | Durable workflow engine |
|---|---|---|
| 单机/本地优先 | 更简单、延迟低 | 可能过重 |
| 跨 worker/region | 需自建 lease、queue、timer、recovery | 原生能力更强 |
| 超长 durable wait/HITL | 需持久 timer/message | 通常更自然 |
| 高度动态 Agent loop | 自定义灵活 | 要适配确定性 orchestration 模型 |
| 大量低延迟 token delta | 更易本地处理 | 不宜每 token 进 history |
| 副作用语义 | 无论哪种都必须自定义 idempotency/reconcile | engine 不会替外部 API 保证 exactly-once |
| 运维复杂度 | 应用内复杂度 | 平台依赖与新编程模型 |
选择 durable engine 不能消灭业务 effect reconciliation;选择自建也不能省略 timer、lease、versioning、backpressure 和 replay tests。
截至 2026-08-03,Temporal 的正式文档已提供 Task Queue Priority 与 Fairness:fairness key 可形成 virtual queues,并由 weighted round-robin 控制共享 worker capacity;其官方首页还列出 Replay 2026 发布的 Serverless Workers、Standalone Activities、Workflow Streams,以及 Google ADK / OpenAI Agents SDK integrations。Temporal Task Queue Priority and Fairness、Temporal official site。这是可核验的产品能力与方向信号;它既不证明这些能力都已在每个部署形态中等价可用,也不替 Agent 自动解决 effect、证据或上下文语义。
17.2 Event sourcing 还是 mutable row state
| 选择 | 优点 | 风险 |
|---|---|---|
| Event log + reducers | replay、审计、多投影、first bad transition | schema/migration、日志增长、reducer discipline |
| Mutable state + audit side log | 查询简单、低写放大 | audit 与状态易分叉、难重建 |
| Hybrid | 核心 facts evented,热点索引 mutable | 所有权边界必须清楚 |
Agent 的决策、effect 与证据天然适合 event facts;quota counter、lease、队列索引可用 CAS mutable state。不要为了“纯 event sourcing”把所有高频 token 与资源计数塞进一个 session log。
17.3 单 writer 还是多 writer
- 同 Agent/Turn 默认 single logical writer,降低上下文和状态冲突;
- 工具 execution 可并行,但 results 通过一个 sequencer/admission 回到 loop;
- subagents 拥有独立 journal/agent identity,通过窄 contract 交接;
- 多设备输入作为 commands 排队,不直接并发改 reducer state;
- 真正多 writer 需要 per-object conflict semantics、CRDT/CAS 或事务,不靠“最后写入胜出”。
17.4 Sticky worker 还是 stateless worker
最佳通常是:状态 durable,缓存 sticky,计算 replaceable。
- sticky:保留 model prefix cache、workspace hot state、MCP connection,降低延迟;
- stateless fallback:任何 worker 能从 snapshot/journal 恢复;
- affinity 是优化,不是正确性前提;
- worker version 进入 placement 与 replay compatibility;
- drain 时先停止 admission,再 checkpoint/handoff。
17.5 Snapshot sandbox 还是重建 sandbox
| Snapshot | Rebuild |
|---|---|
| 快,保留进程/内存可能性 | 可复现、干净、升级容易 |
| 版本/CPU/内核兼容复杂 | 重启服务成本高 |
| 可能保留 secret 与损坏状态 | 必须显式恢复外部服务状态 |
Coding Agent 多数时候应优先保存 workspace/artifact 并重建进程;只有冷启动极贵且 snapshot compatibility 可控时保存 VM/process state。
18. Frontier reference:跨 surface 产品 contract 与极简 Runtime kernel
这里的 frontier 不是“谁的 feature 更多”,而是两条同时成立的轴:
- 产品轴:一个 task 能在 local、remote machine、cloud sandbox 之间拥有明确 execution placement,并从 terminal、IDE、desktop、web、mobile、Slack 或 automation 入口被创建、观察、steer、approve 与验收;
- kernel 轴:session、message admission、tool loop、persistence、compaction、branching 与 embedding contract 足够小、明确、可替换,不让 surface 逻辑侵入核心状态机。
Codex 与 Claude Code 是第一条轴的一手产品 reference;pi 是第二条轴的公开源码 reference;Kimi 公共源码适合用来逐行观察机制,但不是定义 frontier 的唯一或主要基准。
18.1 Codex:Thread 是跨 surface 的工作对象,machine/cloud 是 execution placement
截至 2026-08-03,OpenAI 公开资料能够直接确认:
- Codex cloud 从 2025 年开始就把每个 task 放进独立 cloud sandbox,并支持多 task 并行;后续公开产品将 terminal、IDE、web、GitHub、mobile 与 cloud 连接到同一 ChatGPT account 下,并允许 IDE 创建、跟踪、审阅 cloud task。Introducing Codex、Introducing upgrades to Codex。
- Codex app 以 project/thread 组织多个 Agent;不同 Agent 可在内建 Git worktree 中并行修改同一 repo,用户可以在线查看 diff、评论、切回 editor;app 还读取 CLI 与 IDE extension 的 session history/configuration。Introducing the Codex app。
- 手机端可连接运行 Codex 的 laptop、devbox 或 managed remote environment,读取 active threads、approval、plugin 与 project context 的 live state;用户能从手机启动/steer、批准命令、换模型并审阅 terminal output、diff、test result。Remote SSH 则让 thread 直接运行在受管远程机器上。Work with Codex from anywhere。
- Codex app 的 Automation 可把 instructions 与 optional skills 绑定到 schedule,后台运行后进入 review queue。其 2026-02 发布文仍把 cloud-based triggers 描述为后续建设方向;在没有更新一手 contract 前,不能把所有 Automation 都宣称为“已脱离本机的 durable cloud scheduler”。Introducing the Codex app。
由此抽象出的 frontier contract 是:surface 不是 session owner,WebSocket 不是 task,手机也不是远程桌面;它们是同一受控工作对象的多个 control/observation surfaces。 execution authority 仍留在实际 machine 或 cloud environment,surface 只提交命令、审批与观察。
但 OpenAI 公共资料没有披露以下后端细节,状态必须标为 unknown:thread/event 的具体 durable schema、local machine 断电后的 active-turn 恢复级别、relay 的 ordering/dedup contract、cloud scheduler 的 lease/fencing、Automation trigger delivery semantics、跨 local/cloud handoff 是否迁移同一 run,及任意外部 effect 的统一 reconciliation 协议。产品表现不能替这些机制作证。
18.2 Claude Code:明确区分 local Remote Control、cloud session 与 cloud Routine
Claude Code 的公开 contract 对 execution locality 的边界更显式:
- Remote Control:执行始终留在用户机器,claude.ai/code 与 mobile 只是同步窗口;terminal、browser、phone 可交替发消息。连接中断可重连,但机器/进程仍是执行前提。server mode 可以按
same-dir、worktree或 single-session 创建会话,并限制并发 capacity。Claude Code Remote Control。 - Claude Code on the web:每个 session 在 Anthropic-managed cloud VM 中 fresh clone repo、工作、测试并推 branch;session 跨设备保留、断开页面仍继续,可同时运行多个独立 session/branch,并可在执行中 watch/steer。Claude Code on the web。
- Parallel worktrees:CLI
--worktree、desktop 自动 worktree 和 subagent worktree 都把文件修改隔离开;transcript/session 与 cwd 的重新绑定有显式规则。Worktree 解决 workspace collision,不解决租户安全或外部 effect 冲突。Claude Code worktrees。 - Routines:cloud Routine 可由 schedule、API 或 GitHub event 触发,每次 run 创建一个新的、可审阅的 cloud session;web、desktop、CLI 写入同一 cloud account。它与 session-scoped
/loop不同:后者依赖当前 CLI session,关闭进程就停止,不能冒充 durable automation。Claude Code Routines、Claude Code scheduled tasks。
这个对照揭示一个重要对象模型:
Remote Control = remote surface → local execution owner
Cloud Session = web/mobile/CLI surface → Anthropic cloud execution owner
Routine = durable trigger definition → new cloud session per firing
Worktree = per-session workspace isolation, not session durability
同样,Anthropic 公共资料没有披露 cloud session/Routine 的内部 journal schema、queue implementation、lease/fencing、VM crash replay granularity、trigger delivery guarantee 或 external-effect reconciliation;这些均为 unknown。文档写“session persists across devices”只证明产品可恢复访问,不等于中断任意指令后具备 exactly-once resume。
18.3 pi:用小而明确的 kernel 反证不必要复杂度
在线复核的 pi 公共仓库提交为 c6eb628(2026-08-03)。它提供另一种 frontier reference:不是云端规模,而是最小可解释 Runtime。
- README 把 pi 定义为 minimal terminal coding harness;默认只有
read、write、edit、bash四个工具,并刻意不内建 subagent 与 plan mode,把差异化能力留给 extension、skill、prompt template 与 package。pi coding-agent README @c6eb628。 - Session 是一份 JSONL;entry 通过
id/parentId形成树,因此同一文件内可 branch、回到旧节点。README 明确说明 compaction 有损,但完整历史仍留在 JSONL,可经 tree 回看;这使 context projection 与事实历史分离。pi session format @c6eb628、pi coding-agent README @c6eb628。 AgentSession管理单 session 的 lifecycle、history、model state、compaction 与 event stream;AgentSessionRuntime单独负责newSession、switch、fork、import 等 active-session replacement,并重建 cwd-bound resources。这是很干净的“对象状态”与“承载机制”边界。pi SDK @c6eb628。- pi 把 mid-run 输入分成
steer与followUp:前者在当前 assistant turn 的 tool calls 结束后、下一次 LLM 前投递;后者等整个 Agent 停止后再投递。相同 contract 同时出现在 SDK 与 LF-delimited JSONL RPC mode,而不是由 TUI 临时解释。pi SDK @c6eb628、pi RPC @c6eb628。
pi 给 Kimi 面试准备的真正启发不是“照抄四个工具”,而是:核心 loop、session tree、queued input 与 embedding protocol 可以非常小;subagent、planner、UI、provider 与 workflow policy 不必都烧进 Runtime kernel。
其边界也必须诚实:这些公开资料证明 local session JSONL 与恢复 API,不证明 fsync/power-loss contract、跨 worker lease、cloud queue、hard multi-tenancy、worktree scheduler 或通用 external-effect reconciliation。pi 是 simplicity reference,不是 distributed durability reference。
18.4 四个 reference 的正确定位
| Reference | 一手证据最强的层 | 对 Runtime 的关键启发 | 不能据此推出 |
|---|---|---|---|
| Codex | 跨 app/CLI/IDE/web/mobile/cloud/SSH 的 product orchestration | thread 独立于 surface;多 Agent/worktree;remote steering/approval | 私有 journal、lease、crash/effect semantics |
| Claude Code | local RC / cloud VM / Routine / worktree 的显式 placement contract | locality、trigger、session、workspace isolation 分对象建模 | Anthropic cloud backend 的内部实现 |
| pi | 极简公开 session/runtime/SDK/RPC | 小 kernel、tree history、steer/follow-up、resource replacement | 分布式 durability 与多租户生产能力 |
| Kimi Code | 公开 client engine 的 loop/wire/reducer 源码 | 可逐行审视 Agent-scope ownership 与 persistence boundary | Kimi 云端产品 frontier 或 Moonshot 私有后端 |
因此,面试中不应说“Kimi public repo 已经代表当前 frontier”。更准确的表述是:用 Codex/Claude Code 校准最终产品 contract,用 pi 校准 kernel simplicity,用 Kimi public code 做 mechanism audit;三者分别回答产品形态、最小抽象和当前可见实现。
18.5 从 frontier 产品反推的七条 Runtime 不变量
- Stable task identity:surface、connection、process、machine、sandbox 都可以变化,task/thread/session identity 不能跟着漂移。
- Placement explicit:每个 run 明确标记
local | ssh-host | vendor-cloud、environment revision 与 execution owner;“远程”不能同时指远程 UI、远程机器和 vendor cloud。 - Steering is admission:steer、follow-up、approval、cancel、schedule fire 都是带 identity/ordering 的 command,不是往 socket 塞字符串。
- Parallelism owns isolation:parallel session 至少拥有独立 workspace/branch、budget、evidence 与 merge contract;worktree 只解决其中的文件层。
- Automation creates durable work:trigger definition、fire event、run/session、receipt 与 review item 分开;不要把一个永不退出的 chat loop 当 scheduler。
- Surface reconnect ≠ run recovery:UI 恢复访问、进程恢复、workspace 恢复、effect 恢复是四级不同 guarantee,必须分别测试和对外表述。
- Kernel stays small:session state、loop、tool protocol、persistence 与 event stream 是深模块;product surface、planner、subagent topology 与具体 provider policy 是可替换层。
18.6 已形成的结构性共识
- 长任务从交互变成 durable work unit:OpenAI 2026 的公开数据将 Agent 描述为可运行分钟/小时的委托任务;其重度用户通过并行 Agent 产生远超一天墙钟的累计 Agent runtime。OpenAI: How agents are transforming work。这是 OpenAI 自有产品与用户样本,不能直接外推为全行业分布。
- Brain、Hands、Session/Evidence 解耦:Anthropic Managed Agents 将其作为可替换基础接口,解决 container/harness 故障与 credential boundary。Anthropic Managed Agents。
- Worktree-local 可观测环境成为 Agent 的感官:OpenAI 公开实践把 app、logs、metrics、traces 置于每 task/worktree 的隔离环境,单 run 持续数小时。OpenAI Harness Engineering。
- Durable workflow 生态主动适配 Agent:Temporal 官方已公开 Workflow Streams、priority/fairness,以及 Google ADK / OpenAI Agents SDK integrations 等方向。Temporal official site、Temporal Task Queue Priority and Fairness。这只是平台能力,不能推出具体 Agent 已获得端到端 durable semantics。
- GenAI trace 语义开始标准化:OpenTelemetry 已定义 agent/model/tool 层操作,但规范仍在 active development,content capture 的隐私与兼容策略仍需谨慎。OpenTelemetry GenAI Observability。
18.7 仍在演进,不能过早固化
- cross-surface identity、delegated authority 与 approval receipt 的标准表达;
- local run 与 cloud run 是 handoff、fork 还是独立 execution 的统一语义;
- workflow engine deterministic history 与高度动态、多模型 Agent loop 的最佳边界;
- token stream 进入 durable history 的粒度;
- remote sandbox warm pool 的安全/成本最优点;
- multi-region Agent session 的 active-active 是否值得其冲突复杂度;
- VM snapshot、workspace snapshot、application checkpoint 的统一 contract;
- Agent 级 SLO 的行业共同定义。
18.8 应保持怀疑的说法
- “跨端能看到同一 thread,所以后端一定 event-sourced”;
- “手机能 steer,所以 local process 断电后仍能继续”;
- “cloud task 会后台运行,所以任意 effect exactly-once”;
- “每个 Agent 有 worktree,所以并行修改不会语义冲突”;
- “Automation 有 schedule,所以 trigger 不会漏投或重复”;
- “用了 workflow engine 就 exactly-once”;
- “容器就是 sandbox”;
- “支持 resume 就支持 crash recovery”;
- “有 event log 就可审计”;
- “长 context 让 checkpoint 不再需要”。
19. Kimi Code 公开源码:glass-box mechanism sample,不是 frontier benchmark
在线复核点:Kimi Code 公共仓库
main提交29c9e2ab20a1646ad33f2b7c999b450152f9c01a,提交时间 2026-08-03 15:42:09 +08:00;官方 changelog 的最新发布版为0.31.1(2026-07-31)。以下代码观察固定到该提交,而不是会移动的main链接。Kimi Code changelog。公共实现只证明本地/客户端 Agent engine 中可见的 mechanism;Kimi/Moonshot 云端的 task store、scheduler、execution placement、remote steering、automation、lease/fencing、multi-tenant isolation 与 effect reconciliation 均为 unknown,不应从客户端源码外推。
19.1 生命周期与 loop
公开 agent-core-v2 基于 DI × Scope,区分 App / Workspace / Session / Agent。其 loopService 绑定 Agent scope,拥有 Turn FIFO 与每 Turn 的 StepRequestQueue;只有队头 Turn 推进,下一 Step 由 continuation、goal、external hooks、task 等 aspect 显式 enqueue,而 loop 自身不暗中递归。agent-core-v2 guide @ 29c9e2a、loopService @ 29c9e2a。
这一版源码还把 snapshot boundary 写得很明确:nextReservedTurnId、lastRequestTraceId、disposing 等 plain-data loop state 注册到 IAgentStateService;持有 AbortController、controlled promise、StepRequestQueue 的 pendingTurns / activeTurnJob,以及其他 mechanism resources 则明确不进入 snapshot。这个边界是正确的资源建模信号,但也意味着不能仅凭 loop state snapshot 推断进程崩溃后可从任意 in-flight 指令中点继续;活跃 Turn 的重建、重新 admission 与 effect reconciliation 必须由更高层持久事实和恢复协议证明。
这对应本文的:
- session/agent 生命周期所有权;
- Turn admission 与 Step queue 分离;
- 用户 cancel 通过 Turn/Step abort channel 传播;
- error handler 认领 step error 后自行 re-enqueue continuation;
- max steps、retry、compaction 是不同控制路径。
但公共 loop 是 Agent 内 logical scheduler,不等于分布式 worker scheduler;源码不能证明其具有跨机器 lease、epoch fencing、tenant fair queue 或 region recovery。
19.2 Wire journal 与 reducer
公开 WireService 是每 Agent wire aggregate 的唯一 runtime owner,把 reducer engine 与 wire.jsonl 协议结合,支持 metadata、protocol migration、atomic healing rewrite、blob dehydration/rehydration 与 ordered post-restore hook;恢复时按 record replay reducer,unknown/malformed record 被报告并跳过。WireService @ 29c9e2a。
可映射为:
- Agent scope append-log 是恢复事实源;
- model state 是 reducer projection;
- 大 content parts 外置 blob;
- schema/protocol version 与 migration;
- restore phase 明确;
- transcript/context 等可由 wire models 派生。
需要独立审视的边界:
- dispatch 先更新内存 model,再通过 append store 持久化;append error 由 error handler 报告。面试时应追问“对外 acknowledged state 与 durable append 的一致性 contract 是什么”,而不是仅凭代码宣称强 crash consistency;
- unknown/malformed record 被跳过适合可降级记录,但关键 effect/permission/terminal record 是否允许 skip,需要按 record criticality 分级;
- atomic healing rewrite 解决本地日志迁移/修复,不自动提供跨 writer CAS 或分布式一致性;
flush()只说明等待 persist queue/store flush;底层 fsync、atomicity、power-loss contract 需看具体 store。
19.3 Brain / Hands / Evidence 映射
| 本文边界 | Kimi 公开模块/机制 | 判断 |
|---|---|---|
| Brain | loop、llmRequester、contextMemory/projector、compaction、aspects | 已有清晰领域拆分 |
| Hands | toolExecutor、permissionGate、workspace/tool/MCP 层 | 有多阶段 tool pipeline |
| Evidence | wire journal、blob、telemetry、transcript projection、inspect | 已有本地证据基础 |
| Distributed owner | 公共源码未证明跨机 lease/epoch | 不应过度推断 |
| Effect reconciliation | retry/dedupe/error paths 可见,但任意外部 effect 的统一 intent/receipt/reconcile contract 未由这些文件证明 | 面试重点追问 |
| Multi-tenant scheduler | 公共客户端 engine 非充分证据 | 面试重点追问 |
| Cross-surface task identity | 公共 client engine 不能证明 app/CLI/IDE/web/mobile 是否共享同一 durable work object | 云端 contract unknown |
| Cloud task / automation | 公共源码不能证明 trigger、queue、remote execution 或 review inbox | 云端 contract unknown |
19.4 Kimi 面试中最有价值的架构问题
wire.jsonl的最终定位更偏 local recovery、product state source 还是 audit evidence?三者保留与一致性要求不同。- append 失败后,内存 reducer 已推进的状态如何对上层暴露?哪些事件要求 durability-before-ack?
- effect intent 与 receipt 是否有跨 tool 的统一 envelope?Git push、MCP mutation、shell 与 file edit 的 unknown window 如何分类?
- Kimi 的产品级 work object 是 session、thread 还是 task?CLI、IDE、云端与移动端若跨 surface 接入,identity、execution placement 与 authority 怎样保持一致?
- remote session 是否引入 run/epoch 与 fencing,还是 single owner 由更上层平台保证?
- UI/WebSocket 断线、agent loop、sandbox 与 session store 的健康信号如何区分?
- background task 或 automation fire 恢复时,如何证明旧 owner 已失效、trigger 未漏投/重投、外部结果未重复提交?
- blob upload 与 wire append 的孤儿/dangling reference 怎么修复?
- unknown wire record 的 skip policy 是否按 criticality 分类?
- App/Workspace/Session/Agent scope 中,provider client、MCP connection、sandbox 与 secret broker 分别属于哪层,为什么?
- 当前本地 engine 向 Codex/Claude Code 这类跨 surface、local/remote/cloud 并存的产品 contract 演进时,哪些 kernel 接口保持稳定、哪些必须重画?
19.5 一个成熟的 Kimi 回答方式
我会把 Kimi 公开的 v2 loop 与 wire 看成两个深模块:loop 拥有 Turn/Step admission 和推进语义,wire 拥有 Agent aggregate 的可恢复事实与 reducer。它们已经避免了把 transcript、context、状态和 telemetry 混成一个 messages 数组。但本地 append-log recovery 与分布式 durable execution 不是同一个 claim。若扩展到 remote multi-tenant runtime,我会在外层补 run/epoch、lease/fencing、tenant fair scheduler、sandbox lifecycle 和 effect reconciliation;同时明确哪些 wire events 必须 durability-before-ack,哪些只是可降级 projection。这样既尊重公开实现,也不把未知内部系统臆测出来。
20. 二十一组面试深追问与专家回答框架
1. “设计一个 crash 后可恢复的 Coding Agent,你最先定义什么?”
先定义对象、事实源、状态机和副作用边界,不先选数据库。明确 Session/Run/Turn/Step/Tool Call/Effect;journal 记录 intent/receipt/terminal;workspace 与大 artifact 外置;owner 用 lease+epoch;恢复是 snapshot+replay+reconcile,最后才重新 admission。补一句:如果 effect authority 无 query/idempotency,恢复必须允许 unknown 与人工接管。
2. “为什么 snapshot 不等于 checkpoint?”
Snapshot 是某时刻状态副本,主要优化 replay;checkpoint 是“可从这里安全继续”的语义承诺。后者必须包含 source offset、workspace revision、outstanding effects、budget、owner epoch、schema/reducer version 与验证状态。一个进程内存 dump 没有这些信息,不能保证不会重放副作用。
3. “Agent 的 replay 为什么不能再次调用 LLM?”
崩溃恢复要重建已经发生的历史,重新调用 LLM 会产生新决定、成本和 tool calls,不是 replay。应记录 model request/result 的 canonical facts,reducer replay 只读结果。只有在明确隔离的 counterfactual eval 中才重新调用模型,并生成新 run lineage。
4. “如何做到 exactly-once tool execution?”
先挑战题设:任意外部 effect 无法由 orchestrator 单方面保证 exactly-once。生产上用 at-least-once dispatch + stable operation identity + authority-side dedup + durable receipt + reconciliation。没有 idempotency/query 时进入 unknown,选择补偿、人工确认或禁止自动重试。必须写清 guarantee scope。
5. “tool intent 已记录,Git push 可能成功,但 receipt 丢了,怎么办?”
不盲重推。用目标 remote/ref、expected old SHA、新 SHA 和 push operation metadata 查询;若 ref 已到目标,补写 recovered receipt;若仍是 old SHA,且 lease/branch owner/expected-old 都满足,做条件 push;若 ref 已被第三方推进,进入 conflict/replan。stable effect identity 与 CAS 是关键。
6. “为什么 lease 不能解决 split brain?”
旧 worker 可能因网络分区或暂停错过续租,恢复后仍以为自己是 owner。需要存储和 effect gateway 校验单调 fencing epoch;新 owner 取得更大 epoch 后,旧 epoch 的 append、checkpoint 和 effect commit 都被拒绝。lease 决定候选 owner,fencing 阻止 stale owner 造成伤害。
7. “Turn、Step、request retry 如何编号?”
Turn/Step 是逻辑推进身份;provider request 是一次外部调用,attempt 是该逻辑 request 的尝试。retry 保持 turn/step/logical request lineage,增加 attempt/request ID;不能把 retry 当新 Step,否则 budget、trace 和 first bad decision 被污染。若重新规划产生新 decision,才是新 Step。
8. “用户点取消后 UI 显示 cancelled,就结束了吗?”
没有。cancel 是 requested→propagated→acknowledged→quiesced 的协议。模型流可 abort,shell 要杀 process group/cgroup,HTTP POST 可能 server 已提交,Git push 可能更新 ref。UI 应区分 cancelling、cancelled、cancelled_with_unknown_effects;unknown effects 继续后台 reconcile,但不允许新业务动作。
9. “如何设计长任务 heartbeat?”
Heartbeat 不是输出流,而是小而有界的 progress/checkpoint 信号:work ID、epoch、progress seq、checkpoint ref。设置 heartbeat timeout 检测失联;取消可在 heartbeat response/控制通道传播。不能只看活着,还要检测 progress stall;heartbeat 频率在检测延迟、服务压力和误判间权衡。
10. “一个 tenant 发起一千个 Agent,怎么不拖垮别人?”
分层 quota + weighted fair queue/DRR + per-resource admission。模型 slot、sandbox、artifact、CPU/内存/网络分别 backpressure;tenant 有 burst token bucket 与 concurrency cap;interactive/background 分级并 aging 防饿死;retry/recovery 独立限速。namespace 解决命名,不解决公平与 data-plane noisy neighbor。
11. “为什么 sticky session 既好又危险?”
好处是保留 prefix cache、workspace、MCP connection 和热状态,延迟低;危险是把 correctness 绑定单 worker,形成 pet。正确设计是 durable state + replaceable compute,sticky 只是 placement optimization;随时能从 snapshot/journal 恢复,worker drain 有 checkpoint,版本兼容进入调度。
12. “大模型流怎样持久化,才能断线续看又不打爆日志?”
三流分离:provider delta、durable domain record、client presentation stream。delta 用有界 buffer/partial artifact,message/tool call 完整关闭时写 canonical record;UI stream 有 seq/cursor、coalesce 与 snapshot catch-up;tool-call JSON delta不可丢,普通文本可合并。terminal/error 独立高优通道。
13. “Container、gVisor、microVM 怎么选?”
先看威胁模型和兼容/性能。可信内部任务可普通 container;运行不可信多租户代码需要 userspace kernel 或 microVM;极高保障可独立 VM/host。说明 gVisor 降低直接 host syscall surface 但有兼容/性能成本,microVM 隔离更强但冷启动和运维更重。无论哪种都要独立 egress、secret broker、resource limit 和 control-plane auth。
14. “Git worktree 能当 sandbox 吗?”
不能。它隔离 working tree、HEAD/index,适合并发 Agent、独立启动与验证,但共享用户身份、host kernel、网络、进程和大部分 repo objects。应把它视为 workspace concurrency primitive,再叠加 process/container/microVM security boundary。
15. “如何跨本地与远程恢复 workspace?”
用 base revision + content-addressed overlay + environment spec,不同步一个模糊目录。每次 tool receipt 绑定 workspace revision;远程结果回本地用 expected base/hash 做三方合并或冲突;Git ref owner 单一;本地离线后远程继续 effect 的 policy 显式。进程/端口通常重建,不假装都能 snapshot。
16. “Event sourcing 有什么真正代价?”
schema evolution、reducer determinism、日志增长、snapshot、unknown event、敏感数据删除、跨 aggregate transaction、debug 工具都变复杂。收益是恢复、审计、多投影和 first bad transition。我的选择通常是 hybrid:决策/effect/evidence 做 event facts;lease、quota counter、queue index 用 CAS mutable state。
17. “怎么证明 Runtime 真的可恢复?”
不是演示重启。对 journal/snapshot/provider/tool effect/receipt/artifact/lease/cancel/verifier 每个前中后故障点做 fault injection;断言 state hash 等价或显式 unknown、无重复 effect、budget 不重置、old epoch 被拒、workspace hash 与 verifier evidence 一致;长期看 resume SLO、unknown backlog 和恢复 storm。
18. “Observability 最小需要哪些 ID?”
tenant/workspace/session/agent/run/epoch/turn/step/request/tool-call/effect/attempt,再加 trace/causation/correlation、journal offset、workspace revision。不是所有 span 都塞所有字段,而是逐层继承。内容默认不进 cloud telemetry;prompt/tool args/result 走 opt-in、脱敏、短保留 debug path。
19. “Codex、Claude Code 的跨端与云端能力,对 Runtime 最关键的启发是什么?”
不是“再做几个入口”,而是把 work object 与 surface、connection、execution placement 解耦。Codex 展示 thread 可从 app/CLI/IDE/mobile 观察和 steer,并运行在 local、SSH host 或 cloud;Claude Code 更明确地区分 local Remote Control、cloud session、Routine 与 worktree。Runtime 必须让 task identity、command admission、approval receipt、workspace ownership 和 evidence 跨 surface 稳定,同时诚实区分 UI reconnect、process recovery、workspace recovery 与 effect recovery。两家的私有 journal/lease/effect backend 未公开,不能反向脑补。
20. “Kimi Code 的 wire 已经解决 durable execution 了吗?”
它解决了重要但有限的部分:Agent scope append journal、version migration、reducer replay、blob offload/rehydrate 与 healing,为本地可恢复状态提供深模块。它本身不能从公开文件证明跨机 queue、lease/fencing、multi-tenant isolation 和通用 external effect reconciliation。要评价 durability,必须继续看 append ack/fsync contract、effect intent/receipt、remote owner 与 recovery tests。
21. “如果只能优先补一个 Runtime 能力,你选什么?”
不直接报 feature。先按真实 trace 找高频高损 failure cohort;若目标是长任务可信度,我优先建立统一 effect envelope 与 outstanding-effect reconciliation,因为它跨 shell/Git/MCP/API,决定 crash/cancel 后能否安全继续。定义 intent/dispatch/receipt/unknown、stable ID/idempotency/fencing,配 fault injection 与 SLO。若现有数据表明问题主要是状态丢失或 queue starvation,则优先级会改变。
21. 一页自检
能在白板上不看资料回答以下问题,才算真正掌握这一 Part:
- 能区分 session/run/agent/turn/step/model request/tool call/effect/receipt;
- 能写出 Runtime 状态 tuple、reducer 与十条不变量;
- 能解释 state machine、journal、snapshot、checkpoint、replay、resume 的边界;
- 能画出 tool intent → effect → receipt 的崩溃窗口;
- 能说明 exactly-once 的保证范围与 impossibility boundary;
- 能为六类 effect 选择 idempotency/reconciliation/compensation;
- 能解释 lease 与 fencing epoch 为什么都要有;
- 能设计 tenant-fair queue、resource admission 与 retry/recovery storm 控制;
- 能把 cancellation 讲成 requested→quiesced→reconciled 协议;
- 能设计 provider/domain/client 三条流及 backpressure;
- 能说明 brain/hands/evidence 三边界及稳定接口;
- 能比较 local/remote/hybrid 的信任与恢复模型;
- 能比较 process/container/gVisor/microVM/worktree;
- 能设计可续接 checkpoint 与 handoff;
- 能把 cross-surface、remote control、cloud task、Routine/Automation 与 worktree 映射为不同对象,而不是一个“远程 Agent”;
- 能用 Codex/Claude Code 校准产品 contract、用 pi 校准 kernel simplicity、用 Kimi 公共源码做 mechanism audit;
- 能列出 multi-tenant 七个隔离面与 cache/secret 陷阱;
- 能构造完整 evidence chain,但不把 hash 当真实性;
- 能从故障矩阵决定 retry/resume/reconcile/fail;
- 能定义 Runtime SLO,而不只报 pass rate;
- 能设计 fault injection 与 replay property tests;
- 能准确映射 Kimi 公开实现,并明确哪些分布式能力无法由公开源码证明。
22. 一手资料索引
Agent Runtime 与长任务
- Anthropic — Scaling Managed Agents: Decoupling the brain from the hands(2026-04-08)
- Anthropic — Effective harnesses for long-running agents(2025-11-26)
- OpenAI — Harness engineering: leveraging Codex in an agent-first world(2026-02-11)
- OpenAI — How agents are transforming work(2026-06-25)
Frontier product surfaces 与 Runtime simplicity
- OpenAI — Introducing Codex / parallel cloud sandboxes(2025-05-16)
- OpenAI — Introducing upgrades to Codex / local-cloud product continuity(2025-09-15)
- OpenAI — Introducing the Codex app / threads, worktrees, Automations(2026-02-02)
- OpenAI — Work with Codex from anywhere / mobile steering, secure relay, Remote SSH(2026-05-14)
- Anthropic — Claude Code Remote Control
- Anthropic — Claude Code on the web
- Anthropic — Claude Code parallel worktrees
- Anthropic — Claude Code cloud Routines
- Anthropic — Claude Code session-scoped scheduled tasks
- pi — verified public snapshot
c6eb628(2026-08-03) - pi — minimal coding-agent README @
c6eb628 - pi — session tree JSONL @
c6eb628 - pi — AgentSessionRuntime SDK @
c6eb628 - pi — JSONL RPC and steering contract @
c6eb628
Durable execution、effect 与 messaging
- Temporal — History Service architecture
- Temporal — Workflow Definition and deterministic replay
- Temporal — Events and Event History
- Temporal — Continue-As-New
- Temporal — Activity Execution, heartbeat and cancellation
- Temporal — Python error handling and Activity at-least-once
- Temporal — Task Queue Priority and Fairness
- Temporal — Official site / Replay 2026 launches
- Microsoft — Durable Task programming model
- Google Cloud — Pub/Sub exactly-once delivery
- Stripe — Idempotent requests
Scheduler、隔离与执行环境
- Kubernetes — Leases
- Kubernetes — Coordinated Leader Election
- Kubernetes — API Priority and Fairness
- Kubernetes — Multi-tenancy
- Kubernetes — Pod Lifecycle
- gVisor — Security introduction
- Firecracker — Design
- Firecracker — Production host setup
- Git — git-worktree
- gRPC — Flow Control
Observability 与 Kimi
- OpenTelemetry — GenAI Observability(2026-05-14)
- OpenTelemetry — GenAI semantic attributes
- MoonshotAI — Kimi Code public repository
- Kimi Code — verified public snapshot
29c9e2a(2026-08-03) - Kimi Code — official changelog / release
0.31.1(2026-07-31) - Kimi Code — agent-core-v2 guide @
29c9e2a - Kimi Code — Turn/Step loop @
29c9e2a - Kimi Code — Wire journal/reducer @
29c9e2a