详细拆解 Pi Agent:产品经理搞懂 Agent 的最佳实践

0 评论 104 浏览 0 收藏 32 分钟

OpenClaw 背后真正负责思考和动手的,是一个叫 Pi 的极简框架。拆完整个项目,作者把 Agent 的循环、上下文工程、工具系统与状态管理,讲成了一套可以迁移的产品原则。

如果你正在学习 Agent,或者要面向 Agent 优化迭代你的产品,强烈建议深度使用、拆解、学习 Pi Agent 这套开源项目。

我前段时间要复用 Pi Agent 的 durable 那套实现,顺手用 DSH 把整个项目拆了一遍,花了我 1 个亿 Token,整理了一套 4 万+字的文档。

本文是基于那套文档的精简版,希望能帮你更好的理解 Agent 设计。

Context:了解一点 Pi Agent

2026 年最火的个人 AI 助手是 OpenClaw。但很少有人知道,OpenClaw 早期背后真正负责“思考和动手”的核心框架,是一个叫 Pi 的极简项目——在 OpenClaw 的系统架构里,Pi 位于底层 Gateway 网关控制层,掌控着所有 agent 的推理与工具调用。

Pi 的作者是奥地利开发者 Mario Zechner,有长期开源经验,此前写过 Java 跨平台游戏框架 libGDX(GitHub 两万标星)。他做 Pi 的理由非常“产品经理”:受够了工具的不确定性。

他在多个场合讲过同一件事。他博客里的说法是:Claude Code 功能越加越多,“其中 80% 的功能我完全用不上”。在另一场主题演讲里,他的说法换了个口径:“你可能只用了其中 5% 的功能、知道 10% 左右,剩下 90% 都是没人说得清的黑箱”。而更让他受不了的是,系统提示词和工具定义每次发版都在变——你 9 点开始工作、工作流跑得好好的,10 点就坏了,模型没变,变的是 harness。他需要的是确定性:确定的工具、确定的提示词、确定的行为,改了什么自己知道。

于是 Pi 的定位只有一句话:minimal, extensible agent harness——一个最小、可扩展的 Agent 宿主。它把稳定通用的部分留在内核,把其余一切交给使用者。

Pi 的这个选择在市场层面得到了验证。在 Terminal Bench 2.0 这个专门评测 Agent 完成真实计算机任务的榜单上,Pi 与 Codex、Cursor、Windsurf 一同排进了前五(;GitHub 上的 star 数从 2026 年初的约 2.4 万、148 位贡献者,涨到 2026 年 10 月的约 11.8 万。

我个人是 Pi Agent 的重度用户,原因也是因为它的极致简化:Pi 的系统提示词加上所有工具定义,加起来不到 1000 token(Claude Code 的系统提示词就超过 10000 token);默认只给模型四个工具:read(读文件)、write(写文件)、edit(改文件)、bash(跑命令)。

其他 Agent 各种咔咔塞的功能,Pi 也明确声明不内置:

主流配 Pi 理由
内置 MCP(模型上下文协议,给模型挂外部工具的标准) 不进内核 一个 Playwright MCP 就有 21 个工具、占 13700 token,还没干活上下文就少了 7%–9%。Pi 把 MCP 做成”内置扩展 + 独立客户端包(pi-mcp)“,默认不连接任何 server;更常用的替代做法是”写 CLI 工具配 README”,用到才读,成本降到 225 token
Plan 模式 不做 直接说“我们先想清楚,别改文件”就够了。要跨会话的计划,就写进 PLAN.md,能读、能改、能随代码版本化
待办清单 不做 待办列表往往让模型更困惑——它增加了模型需要追踪和更新的状态,也就增加了出错机会
后台 bash 不做 进程追踪、输出缓冲、退出清理、向运行中的进程发输入,复杂度极高、可观测性极差
子 Agent 不做 主 Agent 在背后偷偷起一个子 Agent 收集上下文,对用户是“黑箱里的黑箱”。Mario 的态度是:需要就先单独开一个会话把上下文收集完,产出 artifact,再带着干净上下文开工
权限弹窗 不做 详见第八章——他的原话是“大部分编程 Agent 的权限系统都是安全剧场”

看清这份清单,你就理解了 Pi 的产品哲学:它不预设你需要什么,而是让你自己决定需要什么。

这套哲学还长出了一个不小的生态。仓库之外,社区自发维护着扩展与资源目录、一键接入 GitHub 的 action、开箱即用的容器镜像,以及按领域拆分的扩展集合——这恰好印证了“最小内核”这条路线:当内核足够小、接口足够清楚时,能力会从外面自己长出来。

Why:为什么 Pi 是最适合用来学 Agent 的项目

学 Agent,其实没啥太多要学的知识点,关键是搞明白把 LLM 串进循环的流程。

Claude Code、Cursor 这类成熟产品,为了开箱即用,会把大量“产品判断”预置进内核:什么时候该问用户、什么时候该起子 Agent、什么时候该自动压缩、权限怎么弹。

这些判断非常好用,但它们藏在黑盒里——你观察到一个效果变差,很难判断是模型的问题、是上下文的、还是这段产品逻辑的。

Pi 反过来:它把不确定的产品判断全部拆掉,只留下最确定的那副骨架。于是:

  • 你看到的每一个行为,都能对应到一条明确的机制。 模型为什么“忘了”?因为压缩发生了,你可以去会话文件里看到那条摘要。模型为什么“插话时机不对”?因为纠偏和追加任务走的不是同一条队列。
  • 它的架构层次非常干净。 一个 monorepo、11 个包,依赖方向一路向下:接口层(TUI / 命令行 / JSON / RPC / SDK)→ Harness(会话编排、上下文、工具)→ Agent 内核 → 模型接入层。每一层都能单独拿出来看。
  • 它是可运行的工业级实现,不是教学玩具。 它在真实榜单上跑进前五,被 OpenClaw 这样的生产系统当作核心框架用。你学到的不是“某个教学项目的简化模型”,而是真东西。
  • 它把“设计取舍”摆到了台面上。 上文那张“主动不做”的清单,每一条背后都有具体理由。对产品经理来说,理解一个产品“为什么不做”比理解它“做了什么”更有价值——那才是判断力。

所以这篇文章我们沿着这条主线拆解 Pi Agent:一次任务从你按下回车,到结果落到你面前的完整旅程。

这条旅程上有五个关键站点,每个站点都是 Agent 产品的一个设计杠杆。

图 1|一次任务的一生:从你按下回车,到结果落到你面前

Overview:一个 Agent 由什么组成

先建立一张地图。Pi 的 11 个包,按职责可以归成下面几层:

层 包 它管什么
接口层 pi-coding-agent 的 modes、pi-tui、SDK 交互式终端界面、一次性 print、JSON 事件流、RPC(进程间调用协议)、TypeScript SDK——同一套内核的五种外壳
Harness 层 pi-coding-agent 会话编排、系统提示装配、上下文文件与技能、压缩、内置工具、扩展系统、项目信任
Agent 内核 pi-agent-core 与产品无关的通用循环:状态、事件流、工具调用协议
模型层 pi-ai 统一的多 Provider LLM API、模型目录、鉴权(含订阅式登录)、图像模型
持久化与底座 pi-durable、pi-env、chord、pi-mcp、pi-codemode、pi-telemetry 可持久化运行时、远程执行环境、插件宿主、MCP 客户端、沙箱脚本、遥测
研发设施 pi-evals 评测集,不参与运行时

内核不认识“文件”和“命令行”:pi-agent-core 只依赖模型层,它接收一份系统提示、一组工具定义、一个“怎么调模型”的函数,就开始跑。

是 Harness 层把“读文件、跑命令、改代码”这些具体能力注入进去的。

这给 Pi 带来了无限扩展的可能性:它意味着同一个 Agent 内核,可以被复用来做聊天机器人、客服、SaaS 后端,而不用重写循环。

整条主干拆开包含五个可以独立优化的环节:装配上下文 → 请求模型 → 执行工具 → 写回历史 → 判断要不要再来一轮。

环节 决定什么 产品经理该问的问题
装配上下文 模型“开牌”时手里有什么 常驻的信息能不能变成按需的?
请求模型 成本与稳定性 提示词前缀稳定吗?缓存命中率多少?
执行工具 能力的上限与安全的下限 工具够通用吗?危险动作在哪里拦?
结果回注 失败后能不能自我修正 错误是变成信息,还是变成中断?
写回历史 能不能回退、分叉、压缩 用户敢不敢让 Agent 试错?

下面我们逐个环节拆解(终于进入到正文了……)。

Loop:循环——Agent 的心跳

大多数人对 Agent 的第一印象是一条直线:用户提问 → 模型思考 → 调用工具 → 返回结果 → 结束。

真实情况是两个 while 循环套在一起:

  • 内层循环:模型 ↔ 工具。模型说“我要读这个文件”,循环执行工具、把结果喂回去,模型再说“我要跑这个测试”,如此往复若干步。
  • 外层循环:等你下一条消息。内层跑完了,不代表这一轮结束——你可能还想追问、纠偏、或者丢一个新任务进来。

图 2|双层循环:为什么"纠偏"和"追加任务"走的是两条通道

为什么要分两层?因为两种输入的最佳生效时机根本不同。

  • 你说“等等,方向错了,别改那个文件”——这是纠偏(steering)。它必须尽快生效,最好在当前这一轮工具调用结束后立刻插入。
  • 你说“顺便再把 A 也重构一下”——这是追加任务(follow-up)。它必须等当前这轮彻底干完再插进来,否则会把模型正在做的事搅乱。

如果产品把这两种输入合成一条队列,你只能在“太早打断”和“太晚纠错”之间二选一。

Pi 分成两条通道,还额外保留了一个中止(abort):你按了停止,那些排队没发出去的消息不会被丢掉,而是回到输入框里还给你。

循环里最重要的一条设计原则:失败也是数据

Agent 会频繁失败:文件不存在、命令报错、参数格式不对。

过去传统产品的设计是“出错了就抛异常、中断循环、弹个错误给用户”。

Pi 及大部分 Agent 会把错误内部消化:所有工具错误都被降级成一条工具结果消息,回注给模型。

这条设计有两层理由,第二层更重要:

1. 协议层:模型每次发出的工具调用都必须在下一轮有一条对应的结果。缺一条,整个请求就会被模型服务方拒绝。所以“抛异常跳过”在协议上根本走不通。

2. 产品层:错误信息是模型自我修正最重要的输入。你把它丢了,模型就只能在原地打转。

Context:上下文工程——效果的分水岭

如果说循环是心跳,上下文就是呼吸。Agent 产品 80% 的效果差异,来自每一轮到底给模型看了什么。

系统提示词的拼接策略

Pi 的系统提示很短,但它一点都不“简陋”——它是分层的,而且顺序固定:

图 3|系统提示的分层装配:为什么它很短,却什么都知道

顺序 层 内容 什么时候进上下文
1 基础指令 Pi 刻意写得极短的人设与总则 每次都在
2 工具清单 当前可用的工具定义 每次都在(且顺序稳定)
3 行为规则 少量硬规则 每次都在
4 上下文文件 AGENTS.md

/ CLAUDE.md,从当前目录逐级向上找

启动时扫描
5 技能目录 只有技能名和一句话描述 每次都在(但只挂索引)
6 项目上下文 工作目录、项目特定的约定 每次都在
7 扩展注入 扩展可以按名字覆盖上面任意一段 由扩展决定

说明:上表为了便于理解做了归并。源码里的具名段落实际有 8 段:preamble / tools / rules / docs / addendum / project_context / skills / cwd。上表前 3 行与第 5 行分别对应 preamble、tools、rules、skills;第 4 行“上下文文件”对应 project_context,第 6 行“项目上下文”对应 cwd;docs(Pi 自身的文档索引)与 addendum(APPEND_SYSTEM.md 的追加位置)在上表里没有单列。另外,SYSTEM.md 的作用是替换 preamble。

两个值得单独注意的点:

第 5 层的技能目录,只挂索引不加载正文。 一个技能可能有几千字的操作手册,但 Pi 在系统提示里只写它的名字和一句话描述。模型判断“这个任务需要那个技能”时,才会去把正文读进来。这叫渐进披露——地图给你,手册按需取。

第 7 层的扩展注入可以覆盖同名段落。 也就是说,“系统提示长什么样”本身是可编程的。一个团队完全可以注入自己的段落,替换掉默认的行为规则。

这套设计回答了“为什么提示词可以很短,却又什么都知道”。答案是——短的不是信息量,是常驻的信息量。你把不常用的知识从“常驻成本”改成了“按需成本”。

压缩策略:文件化保留会话文件

Agent 聊久了,上下文一定会满。主流做法是把旧消息总结成一段摘要然后丢掉。Pi 的做法有个关键区别:

压缩只插入一条新条目,原始记录一直在会话文件里,从不删除。

这里要分清两个视角,很多产品讨论会混淆它们:

  • 存储视角:会话是一份只追加的日志,历史永远完整——这是“证据链”。
  • 请求视角:模型这一轮看到什么,是沿着当前分支“现算”出来的一个投影。

压缩改变的是第二个,不是第一个。所以会出现一个很好的性质:压缩之后,你依然可以回到压缩之前的状态,因为压缩前的每一条记录都还在。

缓存:前缀稳定就是省钱

还有一个容易被产品经理忽略的工程点。大模型的提示词缓存(prompt cache)是按前缀逐字节匹配的:只要前缀稳定,这部分 token 就能以极低的成本复用;前缀一变,全部按全价重算。

Pi 为此做了三件事:系统提示按“段落级差异”只追加变化的部分、工具定义的顺序保持稳定、以及在缓存快过期时主动预热(只在这笔账算得过来时才做)。有用户反馈日常使用时缓存命中率经常很高,甚至能到 100%。

上下文不只是“效果参数”,它同时是成本参数。一个“常驻 3000 token 的功能说明”,在每天几百次调用下就是实打实的钱。这就是 Pi 把技能改成按需加载的经济学动机。

Tools:工具系统——”你看到的”不等于”模型看到的”

Pi 默认只给模型四个工具。很多人第一次看到会震惊:四个够吗?

答案是够,而且这不是极限操作的取巧。有个更极端的例子:Terminal Bench 榜单上有个叫 Terminus 的 harness,只给模型一个 tmux 会话——模型只能发按键、读终端返回的字符,几乎没有比这更原始的接口,但它长期排在前三名。

这给 Mario 的启发是:模型经过大量强化学习后,天然就知道 coding harness 是什么,不需要在上面堆太多东西。

read / write / edit / bash 这四个足够基础、足够通用,模型可以自己编排它们去搜索、修改、验证。

不过这一章真正的主角不是“四个工具”,而是一条工具结果要拆成三份。

图 4|一条工具结果为什么拆成三份:给模型看的、给人看的、给程序看的

一次工具执行(比如跑了个测试、或者读了个几万行的日志)会产生三类去向完全不同的输出:

面向 内容 约束
给模型看 截断后的结果 + “怎么继续读”的提示 默认约 2000 行 / 50KB。超了就截断,但要告诉模型“还有更多,你可以这样读下一页”
给人看 diff、行号、耗时、统计信息 完全不占模型上下文,随便多详细
给程序看 结构化字段 供脚本或自动化流程消费

这个拆分看起来是工程细节,其实是一个非常重要的产品洞察:

“用户看到的界面”和“模型看到的输入”,是两条完全独立的管道。它们可以、也应该有不同的信息量和不同的呈现方式。

反过来看很多 Agent 产品的问题:把工具结果原样打印到界面上(用户被信息淹没),同时又原样塞进上下文(模型被噪声淹没)。两侧都难受,因为没人做这个拆分。

State:状态与记忆——可回退比记得多更重要

会话是一棵树,不是一条线

Pi 把会话存成 JSONL 文件(每行一条 JSON 记录的日志格式),每条记录带一个 id 和一个 parentId。这两个字段让历史形成一棵树,而不是一条线。

这个设计的价值,在一个非常具体的场景里体现得最清楚:

你让 Agent 实现一个功能,它选了一条路走到一半,你觉得方向不对,但不想丢掉已经探索出来的信息,想从“当初那个决策点”重新分叉出第二条路试试。

在树结构下,这件事是一等公民:

操作 结果 什么时候用
/tree 在当前会话文件里跳到任意历史节点继续,原来后面的记录仍然保留 想保留两种尝试,来回对比
/fork 从某条用户消息出发,创建新的会话文件 这条新路线应该变成独立的工作
/clone 把当前活动分支完整复制到新会话 想把当前状态整个带走

Agent 的工作方式是“试错”,而试错的前提是回退成本足够低。如果回退=重来,用户就会变得保守,不敢让 Agent 探索——这直接压制了产品的上限。

压缩:改变的是”看到什么”,不是”留下什么”

图 5|会话树:为什么压缩不等于删除

把上面两件事连起来看,Pi 的整套状态设计可以概括成一句话:

会话是事实的唯一来源;模型上下文只是从当前分支现算出来的一个派生结果。

这个抽象同时买到了三个能力:

  1. 可回放:任何时刻的上下文都能重新算出来,因为原料都在。
  2. 可分叉:换一条分支就是换一条投影,不需要复制整个世界。
  3. 可压缩:压缩只是换一个投影方式,不会毁掉证据链。

顺带说一个反直觉的产品判断:Mario 认为编程 Agent 不需要额外的长期记忆系统——“代码库就是 source of truth”。

传统做法是写文档、做向量索引,但文档一周就过时了。让 agent 每次从零开始、探索代码库的当前状态,反而是目前最好的做法。

Sandbox:安全围栏——不要用交互来伪装边界

Pi 在安全上做了一个非常“不讨喜”的决定:不内置权限系统,不做逐次工具调用的确认弹窗。

理由值得每个做 Agent 产品的人读三遍:

只要你的 Agent 能读本地文件、能执行命令、又能访问网络,你就已经“游戏结束”了。Simon Willison 把这类组合称为 lethal trifecta(致命三件套)——他的原始定义是“访问私有数据 + 处理不可信内容 + 对外通信”三项同时成立;Mario 把这套逻辑翻译成了编码 Agent 的三项能力:读本地文件、执行代码、访问网络。而权限弹窗解决不了这个问题——它制造的是 permission fatigue(权限疲劳):用户被不断打断,最后一路 yes yes yes,甚至干脆勾选“跳过所有权限”。

Mario 的原话更直接:大部分编程 Agent 的权限系统都是“安全剧场”。

Pi 的替代方案是把边界下推到操作系统:需要保护宿主环境,就把 Pi 放进容器、只挂载它需要的数据。

它同时还保留了一个轻量的“项目信任门”——首次进入一个带有 .pi 配置、扩展、技能等资源的目录时会问你信不信任,用来防止“打开一个陌生仓库就被静默加载陌生扩展”。

但 Pi 的文档非常诚实地写明:信任门不是安全边界。

它只控制启动时加载哪些项目资源,不限制任何一次工具调用能碰什么。而且像 AGENTS.md / CLAUDE.md 这类上下文文件,无论你是否信任都会加载——因为它们是“仓库里的说明书”,模型需要读。

不要在 Harness 层假装解决一个必须在环境层解决的问题。 假装解决的代价,是用户以为自己安全了。

Core:产品留白的艺术

最后一个站点,也是 Pi 最核心的产品决策:什么该进内核,什么该留白。

Pi 的分层很清晰:

  • 内核保持最小:Agent 循环、工具执行、上下文装配、会话存储。稳定、通用、不轻易变。
  • 扩展层可编程:扩展(TypeScript 模块,可以挂钩 41 种生命周期事件、提供 20 余项注册能力:工具、命令、快捷键、Provider、渲染器、拦截器……)、技能、提示模板、主题、以及用来分发它们的 Pi 包。
  • 接口层是同一内核的多种外壳:交互式终端、一次性 print、JSON 事件流、RPC、进程内 SDK。同一套 Agent 与 Session 机制,五种用法。

这带来一个很实际的效果:你想要的绝大部分“功能”,不需要改内核,而是以扩展的形式装上去。

留白不是偷懒,而是一种把不确定性外包给生态的产品策略。

它的收益是内核可以保持稳定,当然也会延伸出风险:用户要自己判断该加什么、该信任哪些第三方包。

所以 Pi 并不适合所有人:想要开箱即用的用户,选功能更完整的成熟产品更省心;已经形成自己工作流、希望从小到大自己长出来的团队,Pi 更合适。

Summarize:给 Agent 产品经理的 7 条可迁移原则

把上面五站压缩成可以贴在你工位上的七句话:

  1. 上下文是每轮现算的,不是攒出来的。 别把“上下文”当成一个不断累加的仓库,它更像每次出牌前重新洗好的一手牌。
  2. 把“给人看的”和“给模型看的”分开设计。 这两条管道的信息密度、格式、详略都应该不同。混在一起,两边都难受。
  3. 失败要变成信息,不要变成异常。 错误文本是模型自我修正最主要的输入;把它吞掉,模型就只能在原地打转。
  4. 可回退、可分叉,比“记得更多”更重要。 Agent 的价值来自敢试错,而敢试错的前提是回退足够便宜。
  5. 知识按需加载,不要一次性灌进去。 常驻的每一个 token 都在每次调用里重复付费;把“手册”换成“地图 + 按需取手册”。
  6. 最小内核 + 可编程扩展。 你还不确定的产品判断,不要写进内核;把它变成扩展点,留给生态和时间去回答。
  7. 不要用交互伪装安全边界。 权限弹窗带来的是疲劳,不是安全。真正的边界在操作系统、容器和凭据管理那一层。

如果只能记住一条:做 Agent 产品,你调的不是一个模型,而是一个循环。模型只是这个循环里最显眼的那一环。

系统化补齐 Agent

这篇文章讲的是 Pi 这一个项目的架构。但你在实际工作里遇到的问题,几乎不会长成同一个形状——

  • 为什么同样的模型,换个 Agent 产品效果差一半?
  • 为什么我的 RAG 检索得挺准,答出来还是不对?
  • 为什么提示词写得挺清楚,模型还是不稳定?
  • 面试官问“这个场景怎么用 AI 赋能”,我该怎么拆?

这些问题背后是同一套东西:大模型原理 + 上下文工程 + 产品拆解能力。它们不是靠读几篇拆解文章就能拼齐的,需要有人按顺序一次讲透。

我的《AI 产品经理技能特训课程》就是为此设计的——3 年、9 轮迭代,把过去三年 AI 产品一路进化过来的必备技能做成了体系:

  1. 开篇建立全局认知:整个 AI 行业的生态图景、AI 业务类型、AI 岗位职责——像你第一轮刷 JD 一样,先找到明确的方向;
  2. 4 节课把大模型底层原理讲扎实:浅显易懂(只要你会玩狼人杀就能听懂),但确保你跟面试官聊基本认知时不露怯;
  3. 13 节课讲透四个实战必学技能:提示词工程、RAG 知识库、Dify、微调;
  4. 4 节课带你真正落地 Vibe Coding:亲手开发一个自己的 MCP 出来;
  5. 从需求到产品设计上线的全流程串讲:面试最常被问的“这个场景怎么用 AI 赋能”,有一整节课专门教你怎么拆解——就像这篇文章拆 Pi 一样;
  6. 最后一章手把手教你筛 JD、改简历、准备面试,附 100 道 AI 面试真题解析。

除了课程本身,还有实训项目带教帮没有项目经验的同学补短板:每月两场直播带教,以下是过去一年直播过的项目(均有回放),这些项目已经被大量同学验证有效,可以直接写进简历:

详细的课程大纲、学习计划和更多成功学员案例,私信班主任了解。

本文由人人都是产品经理作者【张佳的AI实战笔记】,微信公众号:【喜新】,原创/授权 发布于人人都是产品经理,未经许可,禁止转载。

题图来自 Unsplash,基于 CC0 协议

更多精彩内容,请关注人人都是产品经理微信公众号或下载App
海报
评论
评论请登录
  1. 目前还没评论,等你发挥!