拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Pi 1.0 拆解:极简 harness 一年只收七个特性,Pi Durable 把崩溃续跑拆成检查点与所有权树

Pi 1.0 拆解:极简 harness 一年只收七个特性,Pi Durable 把崩溃续跑拆成检查点与所有权树

十月一日,Earendil 把 Pi 推到了 1.0,同时甩出一个实验性新包 Pi Durable。

发布当天,Pi 1.0 冲上 Hacker News 榜首,拿下一千二百多赞、近四百条评论。

配套发的 Pi Durable 技术长文也单独上榜,三百七十赞,讨论同样热烈。

Pi 的自我定位很罕见:一个加固过的、极简的、可扩展的 agent harness。

官方说每周有几十万人用它,issue 和 PR 来自全球真实用户。

1.0 不是功能大爆炸,新增清单短得反常,数下来只有七项。

真正的大动作被拆出去单独发,就是主打崩溃续跑的 Pi Durable。

本文基于两篇官方一手原文,拆三件事:1.0 收了什么、为什么克制、Durable 怎么设计。

极简不是口号,是一条过滤流水线

Pi 以极简出名,官方这次把维持极简的过程讲得很直白。

agent 工具每周都在翻新,但大多数变化活不下来。

Pi 的做法是等,等一个东西证明了自己,再考虑采纳。

采纳前还要称一次重:真实功能,对上它天然带来的复杂度。

官方原话是,被扔到墙上又掉下来的东西,比粘住的清单长得多。

这套过滤机制,才是 1.0 只有七项新增的真正原因。

在人人堆功能的时代,克制本身就是一种稀缺工程能力。

1.0 收进来的七项,全部对症长会话磨损

第一项最重:Codemode,原生支持 MCP,还支持非 LLM 模型。

所谓非 LLM 模型,官方点名了 Jev 这类决策模型和图像模型。

第二项是扩展支持虚拟模型,模型本身变成可编程的扩展点。

第三项是工具延迟加载,不再启动时把全部工具塞进上下文。

第四项是给 Anthropic 模型做缓存预热,压低首轮延迟和成本。

第五项是会话中途的系统消息,提示词和工具可以随转录感知地变更。

第六项是新的 TUI 主题,第七项是默认全屏,纯属体验收尾。

单看每一项都不惊艳,合在一起全是长会话的真实痛点。

工具塞满上下文、首轮冷启动慢、中途改提示词失效,都是老用户天天撞的墙。

1.0 新特性解决的实际问题
Codemode(MCP + 非 LLM 模型)模型可直接写代码调工具,决策模型进流水线
虚拟模型扩展模型路由可编程,规划与实现分开用模型
工具延迟加载上下文不被全量工具定义占满
Anthropic 缓存预热首轮延迟与 token 成本双降
中途系统消息改提示词不换会话,转录记录变更位置
新 TUI 主题 / 默认全屏长时间盯终端的视觉疲劳

官方演示里最贵的一分钟

发布页内嵌的演示,值得逐秒拆开看。

Pi 给自己写了一个扩展:一个虚拟模型,规划用 Claude Opus,实现用 GPT。

什么时候从规划切到实现,交给 Jev 这个决策模型来判断。

重载之后,新会话直接选用这个 router/auto 模型。

规划阶段跑在 Opus 上,Jev 嗅到进入实现阶段,把活交给 GPT 6 Luna。

写完的脚本用感叹号直接跑,最后用 /session 按模型拆成本和缓存占用。

这一分钟把 1.0 的三个新能力串成了一条线。

虚拟模型、决策模型介入、成本可观测,全是可编程性的兑现。

模型不再是被调用的黑盒,而是可以被 agent 自己组装的零件。

为什么 Durable 不塞进 Pi,而是单独成包

Pi 编码 agent 的形态很明确:跑在你的机器上、终端里、一个人驱动。

进程死了,你看一眼发生了什么,让它继续,这就够了。

但 Earendil 想把这套能力带出终端,触达不同形态的界面。

这意味着要支持无限长的会话、多人驾驭同一个 agent、跨故障存活。

他们的选择是不让 Pi 长歪,而是把这部分工作合成一个新包。

Durable 与编码 agent 共享代码和原则,但向新的维度延伸。

在 Durable 上验证过的设计,以后会回流到编码 agent。

这是一次教科书级的复杂度隔离:新风险不进稳定内核。

先把 harness 这个词定义清楚

Durable 长文开头先做名词解释,这很少见也很必要。

harness 等于存储,加上并行跑一个或多个模型会话所需的全部机器。

它提供模型调用的工具,以及工具运行所用的执行环境。

会话是你与 agent 的一次交互,被记录为一份转录。

agent 是模型加设定,比如思考等级,再加它能调用的工具。

执行环境可以是你的笔记本、远程虚拟机或内存沙箱。

harness 里跑的一切,从调模型到执行工具,统一叫任务。

概念收敛到这个粒度,后面的设计才能层层咬合。

存储先行:能跑在任何 JS 运行时

Durable 的 harness 开在存储后端之上,自带 memory、SQLite、JSONL 三种。

还附带一致性测试套件和基准,方便你实现自己的后端。

SQLite 和 JSONL 的实现不碰 Node API,加个小适配器就能跑 Bun。

甚至能塞进 Cloudflare Durable Object,边缘运行时也行。

一个进程独占一个存储,其他客户端挂接到这个进程上。

内存里只放工作集:活跃转录、活着的任务、待提交的输入。

其余一切留在磁盘上,用到才读。

活跃转录天然被模型上下文窗口约束,压缩会在溢出前总结旧消息。

所以哪怕几万条消息的会话,也能安稳装进内存。

整个包不含测试约一万五千行,GPT 口径约十五万 token。

这个体积是故意的:你的 agent 能读完并理解它的全部底座。

崩溃续跑:把存活拆成检查点问题

Durable 的核心承诺是,进程死了,agent 从断点接着跑。

笔记本合盖、容器被重新部署、内存被打爆,都算在内。

做法是运行中的每一步都是任务,任务在往前走之前先存检查点。

新进程打开同一份存储,找到没跑完的任务,从最后检查点继续。

被截断的模型请求会重发,半截答案留在转录里,标记为已中止。

被截断的工具调用,只有声明了安全才重跑。

不安全的调用不重复执行,而是告诉模型这次调用被打断了。

已入队的消息保持入队状态,不会因为重启丢失。

一个 requestId 让提交恰好一次,崩溃后重试拿到的是原提交。

恢复运行的代码路径短得惊人,打开存储,调一下 resume。

下面这段把崩溃续跑的核心用法压缩在一起。

const job = { type: "input", content: "Fix the flaky login test", requestId: "job-42", } as const; await root.submit(job, context); // 进程在这里死掉,死在一次工具调用中间。 // 新进程打开同一份存储。 const harness = await Harness.open( await openNodeSqliteStorage("./agent.sqlite"), { models, registry, env }, context, ); harness.resume(); // 继续被打断的运行 const root = await harness.root(context); // 同一个 requestId,拿回的是原提交的答案 const settled = await (await root.submit(job, context)).wait(context);

这套语义的重心不在恢复动作,而在恢复边界被提前声明。

每个工具自己回答一个问题:我被打断后重跑,安全吗。

搜索类工具标 replay 为 safe,部署类工具坚决不标。

幂等不是 harness 替你猜出来的,是你写工具时显式承诺的。

子智能体不是功能,是几行代码的推论

Durable 没有内置子智能体,官方说几行代码就能造出来。

原理是一个子智能体就是一次普通会话,归发起它的工具调用所有。

工具在自己的调用里创建会话,配一个小模型和专属指令。

重跑时先按归属扫描已有会话,找到就等它回答,不会重复建。

因为子智能体也是会话,崩溃后一样从断点续跑。

它自己算成本,界面可以把它挂在父调用下面展示。

官方示例用一个分诊工具演示:给 issue 打 bug、特性或疑问标签。

子智能体被配置成只能回一个词,没有工具,模型换成小档。

复杂度从框架特性降维成了组合用法,这是极简的胜利。

会话可以分叉,历史不用复制

一个 harness 同时跑任意多会话,互不阻塞,保证一致。

会话可以从另一份转录的任意位置分叉,看到父历史但不复制。

官方给的例子是 Slack:频道是一个会话,串聊是从某条消息分叉。

两边同时跑,谁都不挡谁。

每个会话存自己的 agent 配置:模型、思考等级、扩展、工具、工作目录。

于是主 agent 旁边可以放一个评审,用便宜模型、只读工具、独立检出。

多会话在这里不是并发技巧,而是权限与成本的编排手段。

扩展系统:一切能力都是可插拔的

Durable 里,扩展是提示词段落、工具、钩子、任务的命名包。

应用把扩展装进注册表,每个会话按名字选用,只存名字。

系统提示词在每次请求前用段落重建,改了的段落下个请求就生效。

变更被记录在转录里它发生的位置,重启或分叉看到完全一致的画面。

对支持中途改提示词的模型,只发送变化部分,提示词缓存不失效。

同名工具后装覆盖先装,wrap 可以在胜出者外面再包一层。

官方例子是给 bash 包一层计时,不管会话最终用的是哪个 bash。

钩子可以拦在模型请求、工具调用、压缩这些内置任务上。

改参数沿钩链下传,第一个拦截就截停整条链。

钩子在崩溃后可能重跑,所以做决定用 memo:小值随任务存,首写胜出。

审批流因此被写成十几行:问一次 Slack,答案落 memo,重启不重问。

任务系统:把业务流程做成可中止的树

扩展可以带自己的任务,享受与内置任务相同的机器。

每步后存检查点,定时器能熬过重启,任务可以等待别的任务。

官方用分卡支付结账举例:多张卡同时扣,一张失败其余全退。

扣款键用任务 id 派生,崩溃重跑同一阶段也只扣一次。

任务与会话组成一棵所有权树,中止自底向上传导。

每个任务先清理自己的副作用,父任务等拥有的活全部收尾才算完。

任务分前台与后台,Esc 中止会话只波及前台树。

后台任务属于会话但不属于当前工作,适合活到明天的提醒。

这套模型把取消语义从 try/catch 里解放出来,变成结构属性。

压缩与交接:长会话的两个排气阀

压缩在 Durable 里也是任务,而且在后台跑,会话不中断。

上下文逼近上限时,后台先总结旧消息,摘要落在下一个回合边界。

只有两个阈值:后台启动线默认比上限早三万二,等待线留一万六余量。

如果提供商仍拒绝超长请求,harness 压缩后重试一次。

也可以随时手动压缩,附带自己的保留指令。

更激进的是 reset:开新上下文,可以带一张交接便签。

工具能主动要求交接,旧消息全留存储,随时可搜。

配一个搜历史的工具,agent 就实现了自己交接、自己回溯。

几万条消息的会话因此不是负担,而是可检索的资产。

应用状态与会话同命运

建在 agent 上的应用状态,官方要求和会话本身一样耐用。

待办清单、计划、工单、沙箱,全部放进 documents。

documents 是类型化的 JSON,与转录在同一次原子提交里变更。

状态永远不会和产生它的转录对不上,这是原子性直接买的。

每个文档声明分叉策略:取分叉点快照、取当前值、或全新一份。

界面订阅的是已提交的值,不存在中间态闪烁。

可锻性:跑着换代码,会话只记名字

Durable 想做到一件事:不停机改掉运行中 agent 的代码。

注册表可以在会话运行中变更,同名扩展一步替换。

已经在跑的工具调用用旧代码跑完,下一个调用用新代码。

会话存的是扩展与工具的名字,从来不是代码本体。

重启之后,会话自动捡起新进程安装的新版本。

热更新与崩溃恢复因此共用同一条名字解析路径。

多人驾驭:状态即界面

Durable 里界面需要的一切都是已提交状态。

任意多客户端可以挂到任意会话,先看全量当前视图,之后只收增量。

迟到或断线重连的客户端,从当前视图起步,不需要回放历史。

任何客户端都能驾驭运行中的会话,消息插入当前工具调用之后。

远程客户端用 watch 收每次提交的精确操作,小到能走 socket。

想要编码 agent 那种事件流,watchEvents 负责转换,代价是字节更多。

多人共驾不再是产品功能,而是状态模型的自然推论。

两个演示应用把抽象坐实

官方给了两个可跑的示例,一个迷你编码 agent,一个度假规划器。

度假规划器约一千三百行 TypeScript,大部分还是 TUI 界面代码。

演示里子智能体并行跑三个搜索,每个都是耐用任务。

主 agent 同时自由聊天,不用等搜索结果。

然后进程被杀死,天气和博物馆已完成,火车还没搜完。

重启之后,只有标了安全的火车搜索重跑,其余原样保留。

人能切进子智能体驾驭它,再切回主会话继续聊。

研究报告以消息形式抵达,主 agent 顺手把它整理成行程。

崩溃、恢复、并行、驾驭,四个承诺在一个 demo 里全部兑现。

拆完之后的工程判断

Pi 1.0 的真正信号,是 harness 进入收敛期。

当一家以克制著称的团队宣布稳定,说明这个层的接口正在定型。

工具延迟加载与缓存预热进入内核,意味着上下文经济学成了默认约束。

Codemode 把 MCP 与决策模型并列表述,工具生态开始分层。

Durable 的真正信号,是持久化从数据库问题升级成语义问题。

存下来不难,难的是每个工具先回答重跑是否安全。

恰好一次的 requestId、首写胜出的 memo、派生幂等键,都是同一招。

把正确性压进小而显式的承诺,而不是堆大而全的保证。

所有权树让中止有了结构,这在多 agent 系统里是稀缺品。

对照今年频发的智能体越权事故,自底向上的清理顺序恰逢其时。

一万五千行的体量也是声明:底座应该小到你的 agent 能读完。

当底座可被 agent 理解,自我扩展与自我修复才有地基。

为什么用 TypeScript,官方答得坦白:引导最容易,不排除以后换 Rust。

两个包都是 MIT 协议,代码在 GitHub,文档在 pi.dev。

装编码 agent 一行脚本,玩 Durable 三个 npm 包起步。

官方预告接下来会放出基于 Durable 的 Slack 机器人和 GitHub 分诊机器人。

如果你今年只跟一个 agent harness 的演进,这个值得放进清单。

极简守住内核,耐用打开边界,这是 Pi 给 1.0 写下的注脚。

返回列表