运行中的修改,到底什么时候生效

拆解 pi(DeepSeek 开源终端 Coding Agent)v0.83.0 的 setter 与 pending writes:调用 setModel() 返回后,「新模型生效」有四个不同的观察面,其中两个还是旧的。源码依据:pi-internals 21 章。

setter 返回了,然后呢

Agent 运行中,你调用了 await harness.setModel(second),它返回了。直觉上「模型已经是 second 了」。

但如果你同时问四个地方,会得到四个答案:

  • harness.getModel():second------setter 已更新 Harness 的最新配置
  • 已经发出的 provider request:旧模型------请求用的是 active turn state,不重读字段
  • 下一次 createTurnState():second------下一份快照会读到新值
  • session.buildContext()(保存点 flush 前):还是旧的 branch 配置------busy 时 setter 只把变更放进 pending queue

一次修改,四个观察面,其中两个还停在旧值。这不是 bug,是设计:当前请求必须用稳定的输入(turn snapshot),修改只对下一轮生效。

setter 的两个时钟

以 setModel() 为例。它先保存 previousModel。phase 为 idle 时,等 appendModelChange() 成功;phase 非 idle 时,只向 pending queue 放入一条 model_change。接着无论哪条路径,都把 this.model 指向新模型,并发出 model_update 事件。

setThinkingLevel() 和 setActiveTools() 结构相同。setTools() 还会先校验工具名唯一、active name 都存在,再决定追加还是排队。setResources() 与 setStreamOptions() 不写 Session entry------它们只改变当前实例,进程重建时需要宿主重新提供。

pending write 为什么不能立即插队

这是这一章最值得细看的地方。assistant message 可能带多个 tool call。低层 loop 要先把 assistant message 和对应的 tool results 形成相邻、完整的对话片段,再进入下一轮。

如果一个 subscriber 在 message_end(assistant) 里追加 custom message,并且立刻写入 Session------这条消息就会落在 assistant 与 tool result 之间。下一次从树构建上下文时,模型 API 所需的工具配对可能被切断:模型看到 tool call,却看不到对应的 result。

所以 Harness 让运行中的 appendMessage() 只排队,idle 时才直接追加。flushPendingSessionWrites() 始终读数组首项,按 entry type 调 Session 对应方法,成功后才 shift()。某项失败不会越过它写后面的内容------简单的 FIFO,没有重试计数、没有 durable queue id、没有跨进程恢复。

Hook 是顺序的,不是并发的

subscribe() 注册全事件观察者,存放在专门的 handler set 里。emit 时按注册顺序等待每个 listener;任意一个抛错,错误被规范成 Hook error,后续 listener 不再执行。它不是 fire-and-forget 的埋点。

on(type, handler) 注册带类型的 Hook,同样顺序等待,保存最后一个非 undefined 结果。所以 context、tool_call、tool_result 这些 Hook 的默认 reducer 是 last-result-wins,不是自动合并所有对象。provider options 和 payload 是例外:链式处理,前一个 handler 改出的结果交给下一个。

失败不会回滚

message_end 到来时,Harness 先 session.appendMessage(event.message),成功后才通知 subscriber。subscriber 抛错,已经追加的消息不会从树上删除。setter 也是先提交自己负责的状态,再发 update 事件;update listener 失败会让 public Promise reject,却没有补偿性回滚。

拆完这章,我的感受是:Agent 框架的「修改」语义,比普通系统复杂得多------因为同一份状态同时活在内存配置、turn 快照、pending queue 和 Session storage 四个地方。pi 的处理是给每个观察面明确的语义:修改立即可见于内存,只对下一轮生效于请求,只在保存点落盘于存储。做 Agent 平台的人,最怕的就是把四个观察面混成一个「当前状态」------那才是真正找不到 bug 的根源。

想看完整拆解(setter 四观察面状态表与 Hook 失败语义源码),这里有 pi-internals 小册子。

源码依据:packages/agent/src/harness/agent-harness.ts L225-L317、L442-L484、L512-L536、L538-L554、L884-L955、L961-L1023,pi v0.83.0,commit 845d6ff1。

相关推荐
高晶1 分钟前
一种小功率锂电池组充电器方案
前端·架构
救救孩子把2 分钟前
Agent面试题-记忆治理-上下文-多Agent协作与工程落地
面试·agent·多agent·agent记忆·agent面试题·上下文治理
孟健7 分钟前
从语音交互到线上交付:理性拆解移动端 Codex 的审查与上下文边界
架构·ai编程
m0_5873830027 分钟前
深圳 24 小时自助健身房系统软件开发实战指南与案例解析
java·spring boot·小程序·架构·需求分析
独孤九剑打醒他1 小时前
【原创开源·修订版】源-栅-漏-栅-源横向双栅MOS:从“被误解的短路”到“电流路径多值逻辑与顶层供电架构”
前端·嵌入式硬件·架构·开源·硬件工程
浮生望1 小时前
Agentic RAG(上):别让所有问题都走检索——查询路由与 Web 兜底
agent
众链网络1 小时前
票务系统的“数据主权“怎么设计:从归属、开放到可迁移
架构
天远Date Lab2 小时前
零信任架构实战:基于天远学籍核验三要素构建自动化竞赛资格审查网关
运维·人工智能·架构·自动化
敲代码的小小酥3 小时前
Agent 运行机制全景:从工具调用到沙箱隔离
ai·agent
鱼饼Y4 小时前
AI Agent 驾驭指南
agent·ai编程