
Pi 迎来了今年规模最大的一次更新:项目升级到 1.0,Code Mode 与原生 MCP 正式进入稳定版;同一天,团队还推出了一套全新的 Harness——Pi Durable。这些变化已经酝酿了一段时间。过去一年,MCP 协议经历了六七轮调整,逐渐发展到真正可用的阶段;Pi Durable 的架构也前后经历了八轮迭代。一个曾被 Pi 公开拒绝的协议进入核心,一套反复打磨的长时 Agent 框架同时亮相,标志着 Pi 开始从终端编程 Agent 向完整的 Agent 基础设施延伸。对开发者来说,Pi Durable 最直观的价值是省掉大量重复代码。过去在 Pi 上构建个人助理、Slack Bot 或其他 Agent 应用,开发者需要自己设计数据库保存消息,再处理 Agent 的启动、任务调度、进程崩溃和状态恢复。有开发者估计,Pi Durable 可以直接替代自己一半的代码,因为这些外围细节都由框架接管。这也解释了为什么有人认为,Pi Durable 会成为许多 Agent 工作流和应用的底座。过去每家公司都在重复实现对话记录、任务持久化、故障恢复和会话分叉,Pi Durable 正好填补了这个空缺。它会保存用户消息、模型回复、工具执行结果和任务状态;进程崩溃后,Agent 可以从中断的位置继续。能够安全重放的操作会重新执行,可能产生重复副作用的操作则不会贸然重跑。Mario Zechner 对它的概括很简单:Agent 启动、调用工具,进程突然挂掉;重新启动后,它应该准确地从原处继续,不需要人再次输入“继续”,工具结果和流式输出也不能丢失。Armin Ronacher 更关注它背后的可靠性:模型本身已经足够不可预测,当 Agent 开始脱离人的实时监控,外层的任务编排和故障恢复至少应该稳定、可以理解。另一项引发争议的变化来自 MCP。过去一年,Pi 创始人 Mario Zechner 和 Flask 创始人 Armin Ronacher 一直是 MCP 最直言不讳的批评者。Pi 官网甚至曾经自豪地写着“不支持 MCP”。他们公开批评 MCP 臃肿、浪费 Token,并认为 Agent 使用 Bash、CLI 工具和代码往往更加高效。如今,模型已经接受了更多与 MCP 有关的训练,MCP Server 和协议也逐渐成熟,Pi 最终决定正式接入。但它没有把所有工具名称、参数和说明一次性塞进上下文,而是通过工具搜索和渐进式披露按需加载。与 MCP 一起进入稳定版的 Code Mode,则允许 Agent 在 QuickJS 沙箱中编写并运行一段 JavaScript 程序。它可以并行调用工具、过滤数据、去重和计算,最后只把真正有用的结果送回模型,大量中间数据都会留在沙箱中,由此降低 Token 消耗、运行成本和上下文负担。Code Mode 还有一个很有意思的能力:它可以直接在 JavaScript 循环内部调用 System 1 模型,例如 Jev。假设 Pi 通过 MCP 获取了 200 条 GitHub 评论,Code Mode 可以逐条交给 Jev 判断用户是否不满、问题是否紧急、应该归入哪个类别。GPT 或 Claude 最终只需看到经过分类和汇总的结果。MCP 负责获取数据,Code Mode 负责编排和处理,Jev 承担大量快速判断,前沿模型专注于高层推理。但一些 Pi 用户并不高兴。有人评论:“所以 Pi 现在也开始堆积垃圾了。”这句话代表了极简主义阵营的担忧:随着 MCP、Code Mode 和更多能力进入核心,Pi 会不会慢慢变成自己过去试图避免的那种臃肿 Harness?Armin 回应称,Pi 默认加载的内容没有比以前增加。Code Mode 也并非“绕了一圈的 Bash”:Bash 运行 Shell 工具,Code Mode 允许模型直接在 Harness 内部搜索、组合和编排工具。Pi 接受了 MCP 的生态,同时仍在控制它给上下文带来的负担。有意思的是,Pi 团队一边让 Agent 使用更多工具、运行更长时间,一边依然不愿把所有工作放心地交给它。Mario 坦言,Agent 可以修复很多小问题,一旦涉及设计和架构,它经常只会在局部堆叠代码,“往你的代码库里拉一坨屎,让情况变得更糟”。当 Agent 终于可以跨越崩溃,连续运行数小时甚至数天,新的问题也随之出现:它不会轻易停下来了,但谁来保证它没有一路把代码库修成屎山?近日,Mario Zechner 和 Armin Ronacher 在一档播客中详细谈到了 Pi Durable 的设计、AI 编程的能力边界,以及 Pi 接下来为什么不想只做编程 Agent。 翻译并整理了这场对话,以下为经编辑的完整内容。太长不看版Q:为什么不让 Coding Agent 修 bug? Armin:因为它几乎不可能在解决问题时不动代码。你越信任全自动流程,代码库就越会随着每一次 bug fix 自然生长。 Q:AI 写的代码到底能不能用? Mario:看层次。Pi 的 TUI 库里大量东西就是纯 slop,我到今天没看过 markdown 组件和 text 组件的哪怕一行代码,我不在乎,只要测试通过、渲染正确就行。但一旦涉及设计或架构,还是得靠人,因为 Agent 只会在代码库里“就地拉一坨”,把事情变得更糟。 Q:模型架构能力到底有没有进步? Armin:没有,甚至可能退步了。它们输出的东西越来越复杂,说话方式越来越怪,满嘴同义词词典里翻出来的技术术语。 Q:为什么架构这件事模型学不会? Mario:因为架构是编程里唯一没有被编码成文本、因而 LLM 学不到的部分。你可以轻松为网络安全、建网站、做前端搭训练数据,但“构建”这个过程本身,也就是设计和架构一个东西的过程,没有训练数据。 Q:那什么任务模型能做得特别好? Mario:有 Oracle 的、二元的、能被 fuzz 的。如果你有一个 Oracle 能告诉 LLM 它做的是对是错,那你基本上就赢了。Bun 的 Rust 重写就是靠这个,让测试套件跑起来就行。 Q:Pi Durable 是啥? Mario:Agent 在进程里启动,调用工具,进程挂了,重启,从断点精确继续。但 Pi Durable 不做事件溯源,用的是“意图、执行、结果”的效果三明治,加上版本化文档存储应用状态。 Q:个人 Agent 这事靠谱吗? Armin:数百万人在用 Grok Bot 之类的东西,把所有东西都登录到机器上,我觉得那是一场灾难,所有这些公司都面临一场灾难。 Q:Earendil 接下来想做什么? Armin:不想成为一家 Coding Agent 公司。两条线:一是做产品,让非工程师也能找到乐趣;二是做基础设施,让每个人都能构建自己的 Agent。 Q:Pi 的未来方向是什么? Mario:我最近在 PIM(Pi Mobile)。不再是“我和 Clanker”,而是很多 Clanker 在很多机器上,和很多人对话。Agent 会修 Bug,也会往代码库里“拉一坨屎”0xSero:为什么决定收编 Pi? Armin:其实在收编 Pi 之前,我们试了很长一段时间想把 Mario 拉进来。在 OpenClaw 那波疯狂之后,机会来了,Mario 对这件事变得可以接受了。我们做的是“可塑软件(malleable software)”,而 Pi 是这方面早期实验的一个很好的版本,所以收编它就顺理成章了。 Mario:我是个白痴才会做 Pi,现在我被困在这儿种地了。 0xSero:你真的觉得自己被这个项目困住了吗?它这么成功,停掉又不合理。 Mario:我和 Armin 一样,也有很长的开源经历,只是我们来自不同领域。一旦我做出的开源项目有了用户,我就会像刚才说的那样,傻乎乎地一直替大家维护,哪怕他们一分钱都没付。有时候,那些负面反馈确实很消耗人。 不过,我现在的目标不是把 Pi 交出去,而是让更多人参与到 Pi 的开发中来,这样“必须我在场”的因子就会降低。到目前为止我们把这个目标实现得相当不错,即使我明天死了,Pi 依然会落在可靠的人手里。 0xSero:说到寻找贡献者,这方面有什么变化?越来越多人开始使用 AI。我知道你以前不喜欢别人随手糊出一堆 AI 代码。现在的体验怎么样? Mario:很糟。换个方式讲,如果我没有从 2 月到大约 7 月把大部分时间都花在维护 Pi、检查和修复 Issue 上,Pi Durable 本来可以早得多发布。 问题在于,Agent 目前还帮不上你修 issue 的忙,至少对我的项目来说是这样。我缺乏信任,没法让 Agent 去判断哪个被报上来的 issue 真的值得我们花时间、需要修。所以最起码,我还是得亲自过一遍所有提交上来的 issue。 Agent 能不能修 Issue?当然能。关键在于它修得好不好。很多问题确实可以交给 Agent,尤其是很小的问题。但只要涉及设计或架构,仍然需要人参与,因为 Agent 往往只会在代码库的局部拉一坨屎,让情况变得更糟。对吧,Armin? Armin:Agent 的问题还在于,它肯定会解决眼前的问题,但几乎不可能在不增加代码的情况下修好它。这其实很奇怪,因为很多问题修完后,代码库的净代码量本来不应该增加。 当然,这话从我嘴里说出来也很讽刺,因为我经常提交一次改 200 个文件、增加 2 万行代码的 PR,简直吓人。我自己也是滥用“机器仔”(clanker,对 AI 的戏称)的受害者。但软件不应该这样发展。尤其是一个完全自动化维护的代码库,几乎必然会随着每次修 Bug 不断膨胀。AI 垃圾代码何时可接受0xSero:DHH 已经彻底投身于这种“AI 糊代码”的工作方式了。我管我自己的工作就叫“slop operations”,因为我基本上什么事都用模型。某种程度上我确实觉得自己比以前笨多了,但另一方面,效率又非常高。如果你的工作不是要造一个会被几百万人复制、使用的东西,我觉得随便糊个脚本出来没什么坏处。比如我最近在做的,就是给特定的硬件组合创建 Docker 容器,让模型在某种随机的 VRAM、RAM 配置上跑到最优。这招一直很好用,设计、架构没那么重要,只要结果能跑、能做它该做的事就行。但你们没有那种特权,你们做的是要被几百万人用的东西。 Mario:我们当然也有。Pi 里面很多东西都是纯粹糊出来的。区别只在于,你在哪一层让人介入,在哪一层相信 Agent 能产出可用的东西,并且不在乎它具体怎样实现。 举个例子,Pi 的 TUI 库,最初的设计是我 2025 年初为另一个项目手写的。那个设计相当稳健、极简,我知道它大概率能扛住真实世界的接触,即便不完美,也够用。但后来我真正开始搭 Pi 的时候,我没有进去说“给我写个 markdown 组件、写个 text 组件、写个 editor 组件”,我直接告诉 Agent:这是 API,对着这个 API 写,把这些组件全给我搭出来。我根本不在乎它们长什么样,只要能跑,并且有一堆测试保证渲染正确就行,其余的我不关心。 到今天为止,我没看过 markdown 组件或 text 组件的哪怕一行代码。我不在乎,这不重要。我唯一在乎的时候,是性能下降了。而那时候,Agent 很擅长识别出一堆问题,但它非常不擅长给出一个泛化的解决方案。它会进去局部修一个东西,让那一个边缘场景的性能变好,但它不会从大局思考,不会去识别架构本身导致整体变慢、并进而催生这个慢的边缘场景的根本问题。我觉得自己目前还有价值,大概就体现在这里。 0xSero:我记得你的流程,比如创建接口、把玩 API、试图先对你要构建的东西建立感觉。这个流程变了吗? Mario:没有。 0xSero:模型整体上做事情的能力变强了很多,但在架构层面还是乱糟糟的没进步,你有没有注意到什么不一样的地方? Armin:我有时甚至觉得它们变差了。更准确地说,它们在架构方面可能确实差了一点。最终结果之所以变差,也可能是因为我们给了模型更多控制权。几乎每次新模型发布,我都会拿它做点东西,而我对它们独立完成工作的结果越来越不满意,主要原因可能是我比以前更信任它们了。 模型本身或许仍在进步,但把我的预期和使用方式一起算进去,净结果反而下降了。我每次都会让模型用 C 写一个游戏,因为我以前很喜欢写 C,这算是我的固定测试。我感觉它们越来越差。也可能是我自己投入的注意力减少了,但至少可以肯定,结果没有明显变好。 0xSero:不是说它们构建东西的方式,而是它们跟我们沟通的方式变得更怪了:说话的方式越来越复杂,用了多得多的技术术语,会在回复里钻进各种奇怪的小众技术话题。 Armin:不过 Opus 确实变好了。两个 Codex 账号破解了我的软件Mario:Fable 5 点几的版本,还有之前那版 Opus,就因为它们说话的方式,我一度完全停用,它每个词都像是从同义词词典里新翻出来的一样,实在受不了,Astra 也很糟。但我对 Sol 6.1 和 Opus 5.5 挺满意的,它们把那个调调又降下来了,现在就像正常的机器。 有一个提升我确实感受到了,是在网络安全方面。去年,我用 Clanker 来加固一些桌面端的软件,当时它根本不行,完全理解不了发生了什么。 今年,一个中国人用两个 Codex 账号破解了这款软件。随后,我使用一个“逆向机器仔”重放攻击,弄清楚他是怎样突破软件防御的。整个过程极其惊人。世界上没有哪个人工逆向工程师能深入到那个程度,更别说在那么短的时间里完成,简直疯狂。 稍微讲得底层一点:这是一套 JVM 系统。JVM 上面有 Java 字节码,字节码最终会通过即时编译器编译成机器码。我把这些都保护得很好,别人没法简单地提取字节码或者注入自己的字节码。但在 native 那一侧有一个很小的逃逸路径,没有任何人类能够识别并利用它。而那个 Clanker 直接进去,把 JVM 内部的 native 结构给逆向了,开始直接读进程内存,把它映射回正确版本的 JVM,识别出 native 内存里的哪个结构对应 Java 表示里的哪个部分。这就像科幻小说一样,太不可思议了。 Armin:我有一个小东西,我总拿出来展示,是一个 USB 芯片,中国的 CarPlay 适配器。它自己就搞明白了怎么解密本该保护新 root 镜像上传的小玩意儿,还在 Web 界面上找到了一个 CGI 文件,可以从那里绕过一些东西。我什么都没做,就是把它插上,让它跑起来。大概花了五百美元之后,整个东西就归我了,这真的非常厉害。 0xSero:我现在家里囤了一堆硬件,就用来跑这些模型,从最小的 Qwen 27B 一直到 DeepSeek 和 GLM,它们在处理这类事情上都变得非常强。我给了它们一个 Nintendo DS 的 ROM hack,一个 ROM 游戏,让它从零开始构建一个 Nintendo DS 模拟器。它可以参考 Dolphin 和其他东西,但必须用完全不同的方式写,它居然真的跑起来了。我发现每当任务是非常二元化的,要么完成要么没完成,它们最终都会把它搞定。Agent 能重写 Bun,却学不会架构Mario:如果你有一个 Oracle,能告诉 LLM 它做的是对是错,那你基本上就赢了。比如说 Bun,Bun 有大量的测试。我敢肯定它不是百分之百覆盖了所有需要测试的东西,但足以让 Jared 能够告诉一堆 Agent:我们按这个方式、那个方式来移植,我会在关键点上给你指方向。基本上你只需要让测试套件在你的 Rust 重写版 Bun 里跑起来就行,这套方法效果非常好。 刚才说的模拟器那件事,其实我也做过类似的。各种系统都有海量的模拟器,而且这些东西全都在训练数据里,多到疯狂,包括那些系统的规格说明。所以这也是一个非常适合用 Oracle 来测试的领域,训练数据里塞满了相关信息。 Armin:而且它也很容易被模糊测试(fuzz test),我觉得任何可以被 fuzz 的东西都适用。我最近就拿了一堆各种格式的示例文件,TOML、CBOR、MessagePack、JSON……然后直接说:这是我的序列化库,把所有格式都给我实现出来。它最终确实做完了。然后我说:好,现在给我往死里 fuzz。结果它找出了一大堆问题。虽然以前 fuzz 库也不算太难,但现在这简直是理所当然的操作。你只要让它一直跑,跑到你花好几个小时才能找到下一个回归为止。 Mario:我觉得这是一个非常棒的用例。尤其是做 fuzzing 的时候,你可能已经有了一些自动化的 fuzz 生成,但在它之上再加一个 LLM,它还能推理出你的 fuzz 生成器没有覆盖到的额外情况。这就像是给所有测试工作加了火箭燃料,非常惊艳,非常有用。 但接下来就说到我们之前提到的那些东西了,比如架构。我记得 DHH 说过类似的话,大意是:你以为你很特别,因为你会架构设计?想清楚吧,模型也会把那个干掉。我觉得 DHH 根本没理解机器学习到底在做什么。 Armin:如果你跟模型讨论一个问题的正确架构是什么,它们其实挺擅长的。但它们给出的那条“最可能解决问题”的轨迹,最终会落到权重空间里完全不同的另一个地方去。 Mario:这一切,基本都能用训练数据解释清楚。我可以很轻松地为网络安全类任务搭建训练数据,为“构建一个已经存在、有标准答案的东西”搭建训练数据,为建网站、做前端、做任何你想要的东西搭建训练数据。 但没有训练数据的,是“构建”这个过程本身,是设计和架构一个东西的过程。这是编程里唯一一个通常不会被编码成文本形式、因而 LLM 学不到的部分。正是构建某样东西的架构的这个过程,让我们卡在了这里。 Armin:这就是为什么我们现在要把所有会议都录下来,以后可以两百万美元卖给 OpenAI。 0xSero:我在德国遇到一个人,他有一家机器人公司,他们的主营业务其实是卖训练数据。他们付钱让人戴上帽子、套上机械臂之类的东西去干活,然后把采集到的数据卖给那些实验室,这是门非常好的生意。但我确信,一切都藏在这些轨迹里。所以如果你在跟模型讨论架构,那些对话轨迹就应该被赋予更高的权重。但问题是怎么分配?你怎么决定哪些数据该获得更高的权重? Armin:这里缺少明确的信号。比如 Pi Durable 经历了多少轮迭代? Mario:八轮。 Armin:对,它经历了很多轮迭代。那么训练系统怎么知道,那些对话中的哪一次最终真的变成了我们发布的那个版本?这理论上是可能的,你可以训练它,给它打标签,有一些方法可以做到,但这是一个显著更难的问题,而且这类对话的数量本身就少得多。 Mario:我倾向于认为这基本上就是一个分类问题。你拿到一堆轨迹,不管你的零数据保留政策怎么说,OpenAI、Anthropic、DeepSeek,手里都有海量的轨迹,现在你想从中挑出真正高价值、高质量的那些。 怎么做?不可能靠人工。他们确实也会手动标注一些,但那不可扩展。所以退而求其次的方案就是用一个机器学习模型把轨迹分类成高质量和低质量。 0xSero:我觉得他们有机会做一件事:就像你在用 Claude Code 时,它会自动在 GitHub 仓库和 commit 里打标签。所以如果你不仅构建对话轨迹,还构建仓库历史本身,那可能是个好办法。因为你可以直接映射,哪些仓库还在被用户使用,哪些 PR 被合进去...