本文永久链接 – https://tonybai.com/2026/10/03/pi-1-0-durable-agent-harness-release

大家好,我是Tony Bai。

【导读】

OpenClaw 的声量似乎已不复当初,但它背后的 Agent 引擎 Pi 却在加速。10 月 1 日,Pi 正式发布 1.0,同时抛出一个实验性新包 Pi Durable:一个进程崩了、机器睡了、容器重新部署了,Agent 也能从断点接着干活的底座。更有意思的是,当初高调宣布“不支持 MCP”的 Pi,这次把 MCP 收进了核心。这是怎么回事?

【文章要点】

  • Pi 1.0 重磅发布:OpenClaw 核心运行底座 Pi 正式发布 1.0 版本(GitHub 突破 11.1 万 Star),并同步推出专为长时间运行、可崩溃恢复与多人协作设计的全新底座 Pi Durable;
  • MCP 态度历史性反转:告别过去的排斥立场,将 MCP 正式收编进核心,并推出核心利器 Codemode——让 Agent 在安全 JS/WASM 沙箱中以脚本编排工具调用,实测 331 次连续工具交互实现零上下文浪费;
  • 虚拟模型动态分流:支持在扩展中定义虚拟模型(例如 Claude Opus 负责规划、Jev 负责决策、GPT 负责落实现),实现跨模型透明切换与 Token 账单的精确追踪;
  • Pi Durable 的六大“不死”原语:
    1. 全环境运行:解绑 Node 原生 API,自带 SQLite/JSONL 适配器,可直接部署在 Bun 或 Cloudflare Durable Object 上;
    2. 崩溃断点自愈:通过检查点机制与 requestId 幂等保证,区分只读工具安全重放与高危操作阻断,确保意外宕机后无缝接棒;
    3. 无拷贝会话分叉:支持对话在任意位置零成本分支(如 Slack 频道与线程隔离),各分支拥有独立权限且并发互不阻塞;
    4. 持久化扩展与所有权树:状态变更带记忆留存,子任务构成所有权树,实现级联取消与防重复确认;
    5. 无感后台异步压缩:上下文逼近上限时后台静默压缩,对话全程不停顿,历史记录全量留存可追溯;
    6. 应用状态原子化与多人协同:业务文档与对话记录同批次提交,支持运行时扩展热更新与多人多端实时接入。
  • 极简工程哲学:全部源码精简至 1.5 万行,专为让 Agent 自己能读懂而设计;坚决拒绝假安全感,通过严格的依赖锁定(Supply Chain Hardening)与外部专业沙箱守牢安全边界。


热闹散去之后,引擎还在转

回看这一年的 Agent 圈,“热”和“冷”切换得很快。

前几个月风靡一时的 OpenClaw,如今已明显安静下来。但它背后的 harness runtime Pi,节奏反而越来越快。

截至发稿时,Pi 的 GitHub 仓库(已经从 https://github.com/badlogic/pi-mono 迁移到 https://github.com/earendil-works/pi)已有约 11.1 万 Star、1.4 万 Fork。官方称,全球每周有数十万人在使用它。

10 月 1 日,Earendil 团队发布了 Pi 1.0。官方的措辞很朴素:一个“加固的、极简的、可以变成你自己的”Agent Harness。

同一天,团队还放出了一个实验性新包 Pi Durable,目标是让 Agent 能长时间运行、扛得住崩溃、能被多人同时操控。

先说明一个概念:什么是 harness?

一句话:模型之外,让模型能真正干活的那一整套东西,包括对话存储、工具调用、执行环境和任务调度。

Pi 1.0:7 项更新,每一项都“扛过了墙”

Pi 的一个鲜明特点是克制。

官方说,Agent 工具每周都在变,但大多数变化留不下来。Pi 的做法是:等一个东西被证明有用,再权衡它带来的复杂度,最后才决定收不收。

团队这样形容 1.0 的新特性:它们被“扔到墙上,粘住了”,而掉下来的东西要多得多。

最终留在 1.0 里的有这些:

更新 说明
Codemode 原生支持 MCP,同时支持 Jev 这类非 LLM 模型和图像模型
虚拟模型的扩展支持 扩展可以定义“虚拟模型”,在背后调度多个真实模型
延迟工具加载 工具不必一股脑塞进上下文
Anthropic 缓存预热 针对 Anthropic 模型优化缓存
对话中途的系统消息 在保持对话记录感知的前提下,修改提示词和工具
全新 TUI 主题 界面焕新
默认全屏模式 终端体验升级

最大的反转:说好的“不支持 MCP”呢?

这一部分最值得细说。

过去,打开 pi.dev 能看到一句很骄傲的声明:Pi 不支持 MCP。团队成员在播客里也不止一次吐槽过 MCP,Mario 还专门写过文章,标题大意是“如果你其实不需要 MCP 呢”。

结果 1.0 里,MCP 成了核心功能。官方专门写了一篇《You Said No MCP!》自我解释,我们提炼成三层逻辑。

第一层:世界变了。

MCP 今天的样子,和一年前不同。

第二层:为 MCP 做的改造,本身就通用。

官方说,MCP 其实可以做成扩展,事实上之前也确实有人做过。但团队在重新思考后发现,支持 MCP 需要的改动,对 Pi 整体都有价值。比如要让 Pi 区分“这个工具是给模型看的,还是只给 Codemode 用的”,就得重新设计工具装载方式。这套改造顺带让 Jev 这类模型更容易接入。

第三层:与其站在场外,不如参与塑造。

官方观点是,MCP 最大的痛点依然是难以组合。很多 MCP 服务器还是为“把工具全部倒进上下文”的 harness 设计的,返回的是文本。在他们看来,MCP 应该更接近“带智能工具发现的 OpenAPI”:返回结构化数据,工具能通过文档和描述被发现。

那么,解法是什么?Codemode。

Codemode 是什么

Harness 执行工具通常有两个位置:

  • bash 所在的地方:不太受信任的沙箱;
  • Agent 循环所在的地方:通常是受信任的环境。

Codemode 运行在后者。它是一个让 Agent 用 JavaScript 来编排和组合工具调用的沙箱。因为它跑在 harness 一侧,所以它的状态是保存在会话记录里的,而不是文件系统里。

官方选 JavaScript 的理由是:小型 JS 引擎可以编译成 WASM 二进制,能提供合理程度的隔离。

官方演示:331 次调用,零上下文浪费

官方给了一个例子。开发者对 Pi 说:用 Jev 通过 Codemode,找出问题追踪器上最沮丧的评论者。

Pi 写了一段脚本,大致做了三件事:

  1. 通过 Linear 的 MCP 拉取 Pi 项目的所有未关闭 issue;
  2. 开 4 个并发 worker,逐个读取评论,交给 Jev(Cloudflare Workers AI 上的分类模型)判断情绪;
  3. 汇总、排序,只把最终结果返回。

整个过程跑了 331 次以上的工具调用,而这些中间结果没有占用模型上下文。最终结论是:167 个未关闭 issue 里,156 个情绪中性,11 个轻度沮丧,0 个重度沮丧。

用大白话说,Codemode 的价值在于:让模型写一段“编排脚本”,而不是一轮一轮地来回调工具。上下文省了,组合能力也上来了。

虚拟模型:Opus 规划,GPT 实现

1.0 的另一个亮点,是扩展可以定义“虚拟模型”。

官方的演示是:让 Pi 给自己写一个扩展,创建一个叫 router/auto 的虚拟模型:

  • 规划阶段用 Claude Opus;
  • 进入实现阶段后,由 Jev 判断是否该切换,交给 GPT 6 Luna 去写代码。

然后重载、新开会话、选择 router/auto,整个切换自动发生。最后用 /session 命令还能看到每个模型分别花了多少钱、缓存命中情况如何。

既然 Pi 已经够好,为什么还要造 Pi Durable?

要回答这个问题,先看 Pi 编码 Agent 的使用场景:跑在你的(远程)机器上,在终端里,被一个人驱动。进程挂了,你看看发生了什么,让它继续就行。

官方明确说:这一点不会变,Pi 1.0 就专注做好这件事。

但 Earendil 想把这套技术带给更多人、更多形态。这就需要一个 harness,满足:

  • 能跑在任何地方;
  • 能被不同界面触达;
  • 支持无限长的对话;
  • 能扛住灾难性故障;
  • 能让多个人同时操控同一批 Agent。

官方没有把 Pi 强行改成它不是的样子,而是另起一个新包:Pi Durable。

它不替代 Pi 编码 Agent,而是一个用来构建任何 Agent 应用的框架,编码 Agent 只是其中一种。它与 Pi 共享底层代码(比如 pi-ai),也共享两条原则:极简、可塑。

官方还透露了一个策略:在 Pi Durable 上探索新设计,不会干扰 Pi 编码 Agent;验证有效的经验,再反哺回 Pi。

Pi Durable 里的 Harness 长什么样

官方给出的定义是:Harness = 存储 + 并行运行多个对话所需的机制 + 工具 + 执行环境。

关键点在于:每个对话可以拥有自己的工具集和执行环境。主 Agent 可以在本机跑,评审 Agent 可以用更便宜的模型、只读工具和独立的代码检出。

Pi Durable 的六个“不死”能力

官方文章的结构很有意思,每一节都以“We want…”开头,我们挑最关键的几个来讲。

1. 到处都能跑,一直都能跑

“任何地方”目前的定义是:任何有 JavaScript 运行时的地方。

Pi Durable 自带 Memory、SQLite、JSONL 三种存储,并附带一套一致性测试和基准,方便你实现自己的后端。其中 SQLite 和 JSONL 的代码没有使用 Node API,只需一个小适配器,就能跑在 Bun 或 Cloudflare Durable Object 上。

内存里只保留工作集:活跃对话、运行中任务、待处理提交。其余留在磁盘。因为活跃对话本来就受模型上下文窗口约束(压缩会在溢出前总结旧消息),所以即使一个对话有几万条消息,也能舒服地装进内存。

2. 崩溃之后,接着干

这是 Pi Durable 最硬的承诺。

每一步运行都是一个任务,且在推进前会先存检查点。进程死了,新进程打开同一个存储,找到未完成的任务,从各自的检查点继续。

具体规则很细:

  • 被切断的模型请求:重新发送,已有的半截回答保留在对话里,标记为“已中止”;
  • 被切断的工具调用:如果工具声明“重跑是安全的”就重跑,否则告诉模型“这次调用被中断了”,由模型决定怎么办;
  • 排队中的消息:依旧排着;
  • requestId 保证提交是恰好一次:客户端崩溃重试时,拿到的是原来那次提交,而不会重复提问。

用代码看,核心就这几行(节选改写):

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 searchIssues = defineTool({
  name: "search_issues",
  replay: "safe", // 只读,崩溃后重跑没问题
  // ...
});

const deploy = defineTool({
  name: "deploy",
  // 没声明 replay:部署被中断后只会告知模型,绝不会重复执行
  // ...
});

读操作可以放心重跑,部署这种有副作用的操作,宁可告诉模型“被打断了”,也绝不自动重放。这是对生产环境非常务实的考虑。

3. 多个对话同时跑,还能分叉

一个 harness 可以并发运行任意多个对话,每个对话都享有同样的保证。对话可以在对话记录的任意位置分叉,子对话能看到父对话到分叉点为止的历史,而不必复制。

官方举的例子很形象:一个 Slack 频道里,Agent 回答任何人的 @。有人在某条回答下开了一个线程,那么频道是一个对话,线程就是它在那条消息处的分叉。两者同时跑,互不阻塞。线程里还可以单独设置:只能搜索,不能部署。

4. 扩展、钩子、任务:一切皆可插拔,且都“耐久”

在 Pi Durable 里,扩展是一个具名的集合,包含系统提示片段、工具、钩子和任务。每个对话只存“选了哪些扩展和工具”的名字。

几个值得一提的设计:

  • 系统提示每次请求前重建:改动会被记录在对话记录的对应位置,所以重启或分叉后,看到的就是模型当时看到的。对支持中途修改的模型,只发送变化的部分,提示缓存不会失效。
  • 钩子(Hook):可以介入模型请求、工具调用和压缩。比如部署前需要人工审批:钩子在 Slack 里询问,答案存进“备忘(memo)”,首次写入为准。重启后不会重复询问。
  • 任务(Task):拥有检查点、跨重启的定时器和等待其他任务的能力。官方的例子是多卡分摊付款:几张卡同时扣款,一张被拒,其他自动中止并退款。
  • 所有权树:任务与对话构成一棵树,中止一个任务,会自底向上中止它拥有的一切,每一层先清理自己的副作用。

官方还提到,Pi Durable 没有内置子 Agent,但几行代码就能做出来:一个工具创建一个自己拥有的对话,给它更小的模型和独立指令,等它回答。这个子 Agent 同样能扛崩溃,同样独立计费,UI 里还能把它挂在那次调用下面展示。

5. 压缩不停手,交接可以搜

长对话最烦人的是:Agent 突然停下来“总结上下文”。

Pi Durable 的做法是压缩本身也是一个任务,后台运行,对话继续。上下文接近上限时,后台压缩开始,摘要在下一个回合边界放进去。只有在下一次请求放不下时,才会等摘要。如果服务商仍然拒绝,harness 压缩后重试一次。

而且旧消息永远留在存储里。reset() 能开启一个全新的上下文,可以带一份交接笔记,再加一个搜索历史的工具,就能得到一个“自己交接给自己、需要时再查旧账”的 Agent。

6. 应用状态也要耐久,还能热更新,还能多人一起玩

  • 文档(Document):待办列表、计划、工单、沙箱状态,这些应用状态以带类型的 JSON 存在对话旁边,和对话在同一个原子提交里变更,因此状态永远不会和产生它的对话记录“对不上”。
  • 热更新:注册表在对话运行时可以变化,用同名安装即可替换扩展。正在运行的工具调用用旧代码跑完,下一次调用用新代码。
  • 多人协作:UI 需要的一切都是已提交状态,所以任意数量的客户端都能附着在任意对话上,后加入的客户端先拿到当前视图,之后只收增量。任何客户端都可以中途引导(steer)运行中的对话,消息会在当前工具调用后加入。

15000 行代码,是写给 Agent 自己读的

Pi Durable 有一个很特别的设计目标:让你的 Agent 能读懂它。

官方给出的数据:不含测试,全部源码约 15000 行,约合 15 万 token(GPT 分词)或 25 万 token(Claude 分词),这还是最坏情况。因为要在它上面开发,Agent 通常不需要读全部,仅存储后端就占了 3000 行,往往可以跳过。

官方推荐的上手方式也很“Pi”:把你的 Agent 指向仓库里的 packages/durable,让它读 README、三十多个示例和两个 Demo,然后开干。

其中那个休假规划器,只有约 1300 行 TypeScript,大部分还是 TUI。它看起来像个编码 Agent,只是因为复用了 Pi 编码 Agent 的 TUI 组件。

稳定性不是喊出来的:供应链硬化与安全边界

“加固”这个词,在仓库首页有不少实证。

供应链方面:

  • 直接依赖固定到精确版本;
  • .npmrc 设置 min-release-age=2,避免解析到当天刚发布的依赖;
  • 以 package-lock.json 为依赖的唯一事实来源,预提交钩子拦截误提交;
  • 发布的 CLI 包带 npm-shrinkwrap.json,锁定传递依赖;
  • CI 使用 npm ci --ignore-scripts,并定时运行 npm audit 与签名校验。

社区治理方面:

新贡献者的 issue 和 PR 默认会被自动关闭,维护者每天人工复核。

安全边界方面:

官方说得很直白:Pi 没有内置权限系统,默认以启动它的用户和进程的权限运行。需要更强边界,就自己做容器化或沙箱。文档给了三种模式:

  • Gondolin 扩展:Pi 和认证留在宿主机,内置工具和 ! 命令路由到本地 Linux 微虚拟机;
  • 普通 Docker:整个 Pi 进程跑在本地容器里;
  • OpenShell:整个 Pi 进程跑在受策略控制的沙箱里。

这是个坦诚而务实的取舍:不做假的安全感,把边界交给更专业的隔离层。

冷静看:值得关注,但别神化

作为技术文章,我们也得说几点保留意见。

1. Pi Durable 仍是实验性质。

官方明确写了“API 可能还会变”,生产环境采用需要谨慎。

2. 目前只有 TypeScript。

官方 FAQ 的回答颇有趣:为什么又是 TypeScript?因为这是最容易启动的方式;至于用 Rust 或汇编重写,“众所周知很容易”,目前不排除,但现阶段专注 TS。

3. 有些细节还没公开。

比如 Jev 的更多信息、Codemode 的完整设计,官方都说“稍后再讲”;Slack 机器人和 GitHub 分诊机器人等基于 Pi Durable 的小工具,也是“未来几周”才会展示。

4. “极简”需要付出的代价。

没有权限系统、新贡献者默认被拒,这些都是极简和聚焦的另一面,是否适合你的团队,需要自己评估。

不过,从方向上看,有两点值得所有做 Agent 的人参考:

  • “耐久”正在成为 Agent 基础设施的一等公民。

检查点、幂等提交、所有权树、崩溃后按声明重放,这些都是分布式系统和工作流引擎里的老概念,如今被系统地搬进了 Agent 世界。

  • “让 Agent 能读懂框架本身”是一条值得重视的设计原则。

代码量、token 量、可跳过的模块边界,都被当成了设计指标。

动手试试

安装 Pi 1.0:

curl -fsSL https://pi.dev/install.sh | sh

安装 Pi Durable(实验性):

npm install @earendil-works/pi-durable @earendil-works/pi-ai @earendil-works/chord

从源码跑两个 Demo:

npm install && npm run build
node packages/coding-agent/src/experimental/durable/main.ts
node packages/coding-agent/src/experimental/vacation/main.ts

两者均为 MIT 协议。

小结

OpenClaw 的热度可以起落,但 Pi 这条线上,有两件事很清楚:

一是它没有追着每周的新概念跑,而是把一个特性放上墙,看它能不能粘住;二是当终端里的一个人用的 Agent 不够用时,它没有把自己撑成大而全,而是另起一个新包,继续保持克制。

Pi 1.0 回答的是“一个可以依赖的 Agent 工具长什么样”,Pi Durable 回答的是“一个扛得住现实世界的 Agent 应用该怎么搭”。它们是否会成为行业标准,还需要时间检验,但这套“先验证、再收纳、保持小”的方法论,已经值得我们学习。


参考资料

  • Pi 1.0 发布文:https://earendil.com/posts/pi-1-0/
  • Pi Durable 详解:https://earendil.com/posts/pi-durable/
  • 《You Said No MCP!》:https://earendil.com/posts/you-said-no-mcp/
  • GitHub 仓库:https://github.com/earendil-works/pi
  • 官网与文档:https://pi.dev

还在为写 Agent 框架频频死循环、上下文爆炸而束手无策?我的新专栏 《从0 开始构建 Agent Harness》 将带你:

  • 抛弃臃肿框架,回归“驾驭工程 (Harness Engineering)”的第一性原理
  • 用 Go 语言手写 ReAct 循环、并发拦截与上下文压缩引擎等,复刻极简OpenClaw
  • 构建坚不可摧的 Safety Middleware 与飞书人工审批防线
  • 在底层实现 Token 成本审计、链路追踪与自动化跑分评估
  • 从“调包侠”进化为掌控大模型边界的“AI 操作系统架构师”

扫描下方二维码,开启从 0 开始构建Agent Harness 的实战之旅。


还在为“复制粘贴喂AI”而烦恼?我的新专栏 《AI原生开发工作流实战》 将带你:

  • 告别低效,重塑开发范式
  • 驾驭AI Agent(Claude Code),实现工作流自动化
  • 从“AI使用者”进化为规范驱动开发的“工作流指挥家”

扫描下方二维码,开启你的AI原生开发之旅。


商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。