“pi 能不能装几个插件,就变成 Hermes 或 OpenClaw 那样的个人 Agent?”
这个问题很容易把 pi 看错。它的终端界面、文件工具和多模型登录都很像一个完整 Coding Agent;而 Extension、Skills 和 Packages 又看起来什么都能接。于是直觉会变成:底座已经有了,剩下只是找插件。
源码和文档给出的边界恰好相反:pi 有意把核心做小,把工作流特有的行为推给扩展、Skill、Prompt Template 和 Package;它默认不内置 MCP、sub-agent、权限弹窗、Plan Mode、to-do 或后台 Bash。pi 的设计说明写得很直白。所以它可以长成一个 Agent OS,却不会因为安装几个扩展自动成为一个。
先说结论:
pi 更适合被理解为“可编程的 Agent Kernel + Coding Agent 参考实现”。它已经负责模型调用、单 Agent loop、工具、上下文加载和会话树;跨渠道、长期记忆、任务调度、评测闭环、跨 Session 协作和 Graph Runtime 仍是上层 Control Plane 的责任。
这不是在说 pi 功能少。相反,恰好是因为它把边界切得干净,才适合当一个需要长期演化的 Agent 系统的底座。
数据快照
- 最后核验:2026-08-12
- 源码与文档:
earendil-works/pi的main分支及 pi Latest 文档- 阅读边界:本文讨论 pi 公开的单进程运行时、CLI 和扩展接口;不比较不同 Agent 的任务成功率,也不把扩展示例等同于 pi 的默认能力
- 名称说明:npm 包仍使用
@earendil-works/*命名;下文“pi-agent-core”指该运行时包,不把它和整个 CLI 混为一谈
#先把产品外壳和运行时内核分开
把 pi 当成“又一个命令行 Coding Agent”并不完全错,只是观察位置太靠外。pi-coding-agent 是用户直接运行的程序;它把终端交互、文件工具、资源发现和 Session 接到一起。但当前 SDK 允许应用直接创建 AgentSession,用于嵌入自定义 UI、自动化管道、子 Agent 工具与程序化测试。SDK 的定位已经说明它不只为终端而存在。
可以先用下面这张图建立地图。
图 1:从 pi-mono 包边界看,CLI 只是 Agent Runtime 的一个宿主;本文根据公开包名与 SDK 接口绘制
flowchart TB U["终端、Web 或自定义应用"] --> C["pi-coding-agent"] C --> S["AgentSession 与 ResourceLoader"] S --> A["pi-agent-core\n单 Agent loop"] A --> M["pi-ai\n模型与流式协议"] A --> T["内置或自定义 Tools"] S --> R["Extensions、Skills、Prompts、Context"] S --> P["SessionManager\nJSONL 会话树"] C --> UI["pi-tui / pi-web-ui"]
图中最重要的是 AgentSession,不是 CLI。它持有 Agent、模型、消息、上下文压缩和事件订阅;调用方既可以 prompt() 等待一次任务结束,也能在流式过程中 steer() 或 followUp()。这意味着“界面”与“Agent 执行”已经分开,CLI 只是其中一个调用方。AgentSession 的公开接口可以直接核对这些职责。
这也是本文用 Kernel 形容 pi 的原因:Kernel 不是完整操作系统,更不是最终产品;它给上层提供一组稳定而受约束的执行能力。这个类比只用于说明分层,不意味着 pi 提供了 Linux 那样的进程隔离、驱动模型或安全边界。
#pi-agent-core:单 Agent loop 是内核,不是工作流引擎
Agent 最小闭环并不神秘:模型读到当前消息和工具描述,决定生成文本还是工具调用;工具结果写回消息;只要仍有工具调用,循环继续。
// 分析性示例:展示职责,不是 pi 源码原样摘录while (agent.hasNextStep()) { const reply = await model.stream(messages, tools); messages.push(reply);
for (const call of reply.toolCalls) { messages.push(await tools.execute(call)); }}pi 的 AgentSession 把这个循环包进更高一层的运行状态:消息历史、模型选择、thinking level、压缩、流式事件与中止。对于一个“读代码—修改—跑测试—继续修”的任务,这就是足够关键的底座。你不必先造一次模型流式协议、工具结果格式和取消语义,才能写上层行为。
但它的边界也在这里。单个 Agent loop 即使会反复调用工具,也仍然不是 Graph Runtime:它没有把 Planner、Coder、Reviewer、Judge 表达成一等节点,也没有为节点间共享状态、条件边、fan-out/fan-in、checkpoint 和恢复提供通用的图语义。
因此,下面两件事不能混为一谈:
- 在一次 pi Session 内,用 Extension 在测试失败后追加一条“分析失败原因”的消息;
- 运行一张持久的“规划—并行实现—验证—人工审批—回滚”执行图。
前者是改造 loop,pi 已经提供入口;后者是编排多个 loop,需要上层 Graph Controller,或交给专门的图框架。把 pi Agent 当作图里的一个 Node 通常很自然;把单 Agent loop 本身叫成完整 Graph Engine,就把“可以组合”误写成“已经提供”。
#pi-ai:统一模型层是路由插口,不是路由策略
pi 的模型层承接不同供应商的鉴权、模型定义和流式调用。当前文档列出的内置或可配置路径覆盖订阅型 Provider、API Key Provider、Cloud Provider、llama.cpp,并支持通过 models.json 配置 Ollama、LM Studio、vLLM 等兼容端点。Provider 文档给出的重点是“怎样接入”,不是替你决定“此刻该用哪个模型”。
如果需要非标准 API、企业 OAuth 或代理,Extension 可以调用 pi.registerProvider() 注册完整 Provider;自定义流式实现最终仍围绕 pi-ai 的 streamSimple 协议组织。Custom Providers 文档给出了这一层的接口和边界。
这让一个 Local First 系统可以把本地与远端模型接到同一个 Agent Runtime;但“根据任务难度、数据敏感度、预算和延迟选择 Qwen、Codex 或 Claude”仍是一条路由策略。它可以放在 Provider 之前、Extension 里,或放在上层 Control Plane,取决于策略是否要跨 Session、跨渠道或被审计。pi 提供的是插槽,不是默认的策略委员会。
#ResourceLoader 和 Extension:可编程性真正从这里开始
如果只看 pi.registerTool(),容易把 Extension 理解成“给模型多塞几个函数”。实际接口宽得多。
createAgentSession() 通过 ResourceLoader 提供 Extension、Skill、Prompt Template、Theme 和 Context File;默认 Loader 会发现全局与项目内资源。SDK 的加载说明明确列出了这一点。对 Coding Agent 来说,这意味着同一个 loop 可以根据项目加载不同的工具、工作约束与交互层,而不用修改 Agent Core。
Extension 的工厂函数拿到 ExtensionAPI 后,至少可以订阅事件、注册工具、命令和快捷键;文档还提供 UI、动态工具、Provider 与 Session 相关能力。Extension API 概览是最可靠的接口清单。
表 1:pi 的扩展点与 Agent OS 上层能力的分工;pi 列基于 2026-08-12 的公开 SDK 与 Extension 文档
| 需求 | pi 已提供的插口 | 仍需要由系统定义的部分 |
|---|---|---|
| 增加工具 | customTools 或 pi.registerTool() | 工具目录、权限模型、凭据治理与审计 |
| 改变单 Agent 行为 | 生命周期事件、消息注入、工具拦截 | 成功标准、重试预算、评测标准与终止协议 |
| 接入本地/私有模型 | models.json、registerProvider() | 路由规则、成本/延迟策略与 fallback |
| 加载项目知识 | Skill、Prompt、Context File、AGENTS.md | 知识更新、冲突处理、长期记忆的提取与遗忘 |
| 改变终端体验 | 命令、快捷键、TUI UI API | Web/消息渠道、多用户身份和组织权限 |
| 管理会话 | SessionManager 与 Session Runtime | 跨 Session 检索、用户画像、事实校验与保留策略 |
以“测试失败后自动进入反思”为例,Extension 能在工具事件后检查结果,并追加新的约束或工具;官方示例也展示了危险 Bash 先经过确认的拦截方式。工具事件和拦截示例说明了这个方向。
但“能拦截”不是“已经安全”。一个真正的权限系统还要定义:谁能授权、授权多久、哪些对象可写、网络和文件系统的隔离在哪里做、日志能否证明实际副作用。pi 的扩展能力是实现这些策略的接缝,不应被误解为默认完成了安全治理。
#Session 是可分叉的工作记录,不是长期记忆
pi 的会话不是一段简单的聊天文本。当前格式把 Session 存成 JSONL,条目以 id / parentId 形成树,因此可以在同一文件中切换分支;SDK 同时公开 SessionManager.create()、open()、inMemory()、forkFrom() 等入口。Session File Format和 SDK 的会话管理章节都能验证这点。
这对 Coding Agent 特别有用:一个错误的调试方向可以 fork,新的路径不用重新丢掉所有已有上下文;Context compaction 也能把长会话缩到模型还能继续工作的范围内。
不过这仍然不等于“长期记忆”。Session 保留的是一次执行的原始过程和分支关系;长期记忆至少还要回答另外几件事:
- 什么信息值得从一段 Session 提炼为稳定事实;
- 哪些事实属于项目、用户、团队或某个渠道;
- 新证据与旧记忆冲突时,谁可以覆盖、怎样保留依据;
- 检索到的记忆怎样标注来源、时效与置信度;
- 删除、过期与隐私边界怎样处理。
把 Session 文件直接当知识库,短期很省事,长期会得到一个很大的“以前说过什么”的文件夹。它能帮助回放,却不能自动回答“现在还应不应该相信”。
#从 pi 向上长出 Agent OS,缺的是 Control Plane
把前面的模块放回最初的问题,答案就很清楚:pi 并不缺一个新的 Prompt,也不缺更多 Tool;它缺的是一个跨多个执行单元做决策的上层。
图 2:把 pi 放进 Local First Agent OS 时,pi 是执行层,Control Plane 负责跨任务语义;本文解读
flowchart TB CH["TUI、Web、飞书、Telegram、Cron"] --> CP["Control Plane\n身份、任务、权限、预算"] CP --> G["Graph Controller\n路由、并行、重试、停止"] G --> PI1["pi AgentSession"] G --> PI2["pi AgentSession"] PI1 --> TOOLS["Tools / MCP / Sandbox"] PI2 --> TOOLS CP --> MEM["Memory\n提炼、检索、遗忘"] CP --> EVAL["Judge / Eval / Observability"] MEM --> PI1 EVAL --> G
这张图没有试图把所有东西都塞进 Extension。原因很简单:一旦 Scheduler、渠道身份、跨任务 Memory、评测历史和 Graph 状态都只存在于某个终端 Session 的扩展里,它们就很难独立观察、恢复和治理。
一个较稳妥的分层是:
- pi 负责执行:模型交互、工具调用、单任务上下文、项目资源发现和可扩展 CLI/SDK;
- Graph Controller 负责编排:创建哪些 Session、哪些可以并行、结果怎样汇总、失败回到哪里、何时要求人工确认;
- Memory Layer 负责事实:从记录中提炼可复查的记忆,而不是把全部消息再次塞回 Prompt;
- Eval 与 Policy 负责停止和边界:测试通过不一定代表任务完成,模型说“完成”也不应替代权限和验收;
- Channel Layer 负责产品入口:把消息、定时任务、Web UI 或设备事件规范化成可以提交给 Control Plane 的任务。
这也是为什么“pi + 插件 = Hermes”不够准确。插件当然能实现很多单点能力,甚至可以做 sub-agent、MCP 或权限门;而 pi 的 Package 机制也确实能把 Extension、Skill、Prompt 和 Theme 打包分发。但一个 Agent OS 的困难不在于把能力装进去,而在于这些能力怎样共享身份、状态、权限、预算和完成证据。
#源码阅读顺序:先追执行边界,再追产品能力
如果目标是做二次开发,建议不要从 CLI 的命令列表开始。更高效的顺序是:
- 先读
pi-agent-core与AgentSession:确认一次模型回复、工具调用、消息追加、取消与压缩怎样构成单任务 loop。 - 再读
ResourceLoader和DefaultResourceLoader:确认项目的 Extension、Skill、Prompt 与AGENTS.md在什么范围、什么顺序加载。 - 然后读 Extension 事件与
registerTool():找清可插入的生命周期位置,以及工具、Provider、UI 与 Session 的实际能力。 - 接着读
SessionManager的 JSONL 树与 Session Runtime:区分“原始会话持久化”“分支”和“长期 Memory”。 - 最后才设计 Graph Controller、Memory、Policy 和 Eval:这些不应由某个局部 Hook 的方便程度反推架构。
这个顺序的好处是,每一步都先确定 pi 已经承诺的接口,再决定自己的系统要在哪一层加能力。否则很容易先写出一个“自进化 Extension”,最后才发现跨 Session 的状态、失败恢复和评测数据都无处安放。
#总结:pi 不是成品 OS,但正因如此值得作为底座
pi 的价值不在于替你打包了多少“聪明功能”,而在于它把最难复用、最容易被 CLI 外壳遮住的部分做成了可调用的运行时:AgentSession、工具、模型层、资源加载、Extension 和树状 Session。
它能支持 Loop engineering:你可以改变单 Agent 在何时观察、验证、重试或停止。它也能成为 Graph engineering 的执行节点:上层把 Planner、Worker、Judge 和人工审批组织起来,再让每个节点使用 pi 的 loop 和工具。但这两句话都不等于 pi 已经带着完整的 Graph、Memory、Channel、Scheduler 和治理系统。
所以,若目标只是尽快得到一个个人助手,选择已经把渠道、任务和记忆打包好的产品往往更省力;若目标是构建一个可本地部署、可评测、可演化的 Agent OS,pi 的克制反而是一种优势。下一篇可以继续沿着这条边界,具体追 ResourceLoader 与 Extension 如何把“外部能力”接进一次 Agent Session。