Pi 深读:一个可以被你改造成任何样子的 coding agent harness

一、为什么"harness"比模型更值得关注

过去两年,大家习惯用"模型行不行"来解释一个 coding agent 好不好用。但真正上手之后会发现:同一个模型,放进不同的 harness(智能体外壳),产出质量可以差出一个数量级。原因很简单——模型只负责"想",harness 负责决定它能看到什么(上下文怎么拼)、能做什么(工具怎么给)、做过什么(会话怎么存)、允许做到哪一步(权限与信任)。

Pi 就是在这个位置上做减法的开源实现:它不追求内置一切,而是把"可扩展"当成第一设计目标。用官方的话说——

Pi is a minimal, extensible agent harness that you can make your own.
把 Pi 改造成适配你工作流的样子,而不是让你的工作流去适配 Pi。

二、Pi 是什么

Pi 是一个跑在终端里的编码智能体:给它一个目标和一个工作目录,它会自己读文件、执行命令、修改内容、多步推进任务。它不只能写代码,也可以用来做资料整理、写作项目、数据处理。

  • 开源协议:MIT,仓库 github.com/earendil-works/pi,作者 Mario Zechner(badlogic)
  • 官网:pi.dev,包名 @earendil-works/pi-coding-agent(当前版本 1.4.x)
  • 运行环境:Node.js ≥ 22.19,macOS / Linux / Windows 均可
  • 内置工具:read(读文件)、bash(执行命令)、edit(精确编辑)、write(写文件)
  • 刻意不做的事:默认不内置 sub-agent、不内置 plan mode。Pi 的判断是——这些属于"工作流选择",应该由扩展和包来解决,而不是强塞给所有人

三、设计哲学:三个层次的自定义

Pi 把"自定义"拆成了由轻到重的三层,你可以只选最小够用的那一层:

  • 轻量层:prompt templates(可复用的提示词模板)、themes(终端配色与外观)
  • 中间层:skills(按需加载的指令包,包含脚本、参考资料、资产,遵循 Agent Skills 规范)
  • 重量层:extensions(TypeScript 模块,可以注册工具、斜杠命令、快捷键、UI、事件钩子、甚至模型 provider)

再往上还有 Pi packages:把 prompt、skill、extension、theme 打成一个包,通过 npm 或 git 分发。团队里想统一"大家都用同一套流程",打包是最省事的方式。

换句话说:想要 sub-agent?装一个包,或者让 Pi 自己给你写一个扩展。Pi 不预设你的工作流,它提供的是组装工作流的能力。

四、架构:一次请求到底发生了什么

1. Agent loop

你提交的消息被加入当前分支,Pi 用「系统提示词 + 当前分支历史 + 可用工具定义 + 技能描述」组装出模型请求,交给所选 provider。模型流式返回文本与工具调用,Pi 记录响应、逐个执行工具、记录结果,完成一轮(turn)。只要还有工具结果或排队中的消息需要模型处理,就继续下一轮,直到跑完。

2. 上下文组装

模型看到的不是"整份聊天记录",而是活动分支重建出来的历史。系统提示词来自基础指令和自动发现的上下文文件;技能只加载描述,正文按需读取;prompt template 在变成用户消息前展开;扩展也可以改写上下文或追加指令。

3. 会话是一棵树,而不是一条线

这是 Pi 比较有辨识度的设计。会话持久化为 JSONL 文件,每个 entry 都有 ID 和 parent 指针,当前 entry 决定"活动分支"。因此:

  • 回到早先某条消息继续提问,不会删掉原来的分支
  • /tree 在当前会话文件内切换分支;/fork 从某条用户消息开出独立新会话;/clone 复制当前分支
  • 离开一个分支时,Pi 可以给它生成摘要,把关键结论带到新分支,避免"重新解释一遍"

4. 上下文压缩(compaction)

接近模型上下文上限时,Pi 会自动压缩:插入一条摘要 entry 替代较早的消息,原始记录仍然保留在会话文件里。/compact 可以手动触发,还能附上"这次要保留什么"的指令。压缩失败(比如 provider 不可用)不影响手动重试。

5. 信任与权限

Pi 在加载项目级设置、技能、扩展之前会先做 project trust 决策。但要注意:project trust 只是"是否加载项目资源",它不是沙箱。工具和扩展都以 Pi 进程的操作系统权限运行,这一点在跑不可信仓库或无人值守自动化时必须自己评估。

五、五种用法,一套内核

接口 怎么用 适合场景
交互 TUI pi 日常开发、边看边改
一次性执行 pi -p "总结这个仓库" 脚本、CI、批处理
JSON 事件流 pi --mode json "..." > events.jsonl 需要结构化消费每一步事件
RPC pi --mode rpc 由外部进程/别的语言控制
TypeScript SDK 在应用内创建并控制 agent session 把 Pi 嵌进自己的产品

关键点:五种接口共用同一套 agent 与会话机制,不存在"交互模式能用、自动化模式缺功能"的割裂。这也是 Pi 能被别的应用(比如各种 GUI)接进去的基础。

六、扩展体系实操

1. Extension:一个 TypeScript 文件就是一个扩展

// ~/.pi/agent/extensions/hello.ts
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";

export default function (pi: ExtensionAPI) {
  pi.registerCommand("hello", {
    description: "Show a greeting",
    handler: async (name, ctx) => {
      ctx.ui.notify(`Hello, ${name || "world"}!`, "info");
    },
  });
}

开发期直接用 pi --extension ./hello.ts 加载即可。Pi 通过 jiti 直接跑 TypeScript,不需要单独编译;要分发就用 Pi packages 带上依赖。扩展还能注册工具、事件监听、自定义渲染、provider,甚至 MCP server。

2. Skill:给智能体的"操作手册"

pdf-tools/
├── SKILL.md
├── scripts/extract.sh
├── references/formats.md
└── assets/template.json
---
name: pdf-tools
description: Extract text and tables from PDF files. Use when reading, converting, or inspecting PDFs.
---

# PDF tools

Read `references/formats.md` before converting a document.
Run scripts relative to this skill directory.

技能遵循 Agent Skills 规范:启动时只加载 name/description,真正用到时再读正文和附属文件,避免把上下文浪费在"可能用不上"的说明上。

3. MCP:接外部工具服务

pi mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem .
pi mcp add docs --url https://example.com/mcp --bearer-token-env-var DOCS_TOKEN
pi mcp list

用户级配置在 ~/.pi/agent/mcp.json,项目级在 .pi/mcp.json(需先通过 project trust)。会话内用 /mcp 查看连接、登录、改暴露范围;外部改完配置用 /reload。

4. codemode:让模型"写脚本调工具"

开启后模型拿到一个 codemode 工具:输入是一段 JavaScript,在 QuickJS 沙箱里用 tools.xxx() 并行调用其它工具、调用分类/图像等非 LLM 模型,只有脚本的最终输出回到模型。沙箱里没有 Node API、文件系统、网络和定时器——外部世界只能通过工具访问。对"要批量处理几十个文件、又不想来回几十轮"的任务,这个设计能省大量 token 和时间。

5. Pi packages:一套配置走天下

把 prompt、skill、extension、theme 打包,pi install <source> 从 npm 或 git 安装,pi list 查看、pi update 更新。团队可以维护自己的"公司标准 agent 包"。

七、模型与凭据:不绑定任何一家

  • /login 支持浏览器 OAuth / device flow,也支持直接填 API key,凭据存在 ~/.pi/agent/auth.json
  • 也支持环境变量方式(CI 友好),以及 --api-key 临时覆盖
  • models.json 可配置自定义 provider、兼容 OpenAI/Anthropic 的端点、本地模型(llama.cpp),以及分类模型、图像模型
  • 选模型支持模糊匹配:pi --model sonnet:high,thinking 档位从 off / minimal / low / medium / high / xhigh / max

这意味着:同一套工作流可以在不同模型之间切换做对比,也可以用私有部署模型跑敏感数据——这是"harness 归你、模型也归你"的组合。

八、十分钟上手

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

# Windows(PowerShell)
powershell -c "irm https://pi.dev/install.ps1 | iex"

# 或者用 npm(不锁定传递依赖)
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
cd /path/to/project
pi                 # 进入交互界面
/login             # 连接订阅或 API key
# 然后直接给任务,例如:把这个模块的测试补全,跑通后提交到新分支
# 会话
pi --continue      # 继续当前目录最近一次会话
pi --resume        # 打开会话选择器
# 常用斜杠命令
/session /tree /fork /clone /compact /export /share /model /mcp /reload
# 自动化
git diff | pi --print "Review this change"
pi --mode json "Inspect this repository" > events.jsonl
pi --mode rpc     # JSONL 命令走 stdin,事件走 stdout

九、Windows 桌面体验:Pi-Flash

Pi 原生是终端 UI。如果希望在 Windows 上有原生桌面窗口、又不想牺牲速度,社区项目 Pi-Flash(PF) 是一个可选方案:用 Rust + GPUI 重写界面,把"快"当成第一指标(启动、首帧、输入、渲染热路径都禁止同步重活),并把 pi 直接 vendor 进安装包,通过 RPC 驱动,不依赖系统里装的 pi。

它把 Pi 的能力搬进了桌面:

  • 模型管理:设置面板内完成 provider 登录与 API key 管理(OS 凭据库加密),模型白名单与通路测试
  • 技能 / 扩展 / MCP:技能管理、扩展装载、内置扩展市场、MCP 配置
  • 会话管理:按项目分组,可恢复、重命名、置顶、删除,逾期清理,上下文用量与费用,自动/手动压缩,跨项目全量搜索
  • 消息级分支:任意一条回复上点"新分支",从该处复制出独立会话继续,原会话不动
  • 项目工具:文件树浏览编辑、文件名+全文搜索、一键在内置终端跑脚本、Git 状态与 diff
  • 内置终端:多标签(alacritty + ConPTY),与文件树、会话同窗协作
npm install -g pi-flash@latest   # 需要 Node.js ≥ 22.19
pi-flash

也可从 GitHub Releases 下载绿色包,解压双击即用(仅 Windows x64)。许可证为 GPL-3.0-or-later(继承自 Zed 项目);项目同时声明了名称与商标边界:fork 需更名并标注"基于 Pi-Flash 的非官方 fork",不得指向官方更新通道。使用和二次分发前建议读一遍它的 LICENSE 与 README。

十、把 Pi 嵌进自己的系统

Pi 的 RPC 模式是纯 stdio 上的 JSONL:外部进程写命令、读响应与事件,任何语言都能控制它。SDK 则更进一步,在 TypeScript 进程内直接创建、配置、订阅 session 事件。

一个真实例子是 DeepSeek Harness(DSH)的 pi-agent 插件:它在侧边栏放一个 π 面板,选择工作目录与模型后运行 pi,把 pi 的文本、思考、工具调用流式渲染到页面里;同时把同一能力暴露成模型工具 pi_agent(参数 prompt / cwd / model)。这说明 Pi 不只是"一个 CLI",它更像一个可被复用的 agent 运行时。

十一、适合谁,不适合谁

适合:希望把 agent 调成自己流程的开发者;需要模型自由切换或私有端点的团队;要把 agent 嵌进自己产品的工程师;喜欢终端、重视会话可回溯与可审计的人。

不适合:想要"开箱即用的全自动开发团队"(那需要自己配扩展与包);完全不想碰配置的用户;以及需要强沙箱隔离的多租户场景——Pi 的信任机制不负责隔离,这类场景要上容器化方案。

十二、和同类工具怎么选

维度 Pi 的特点
定位 极简内核 + 可扩展 harness,而不是功能全家桶
扩展性 TypeScript 扩展、技能、MCP、包分发,层次清晰
可嵌入性 交互 / print / JSON / RPC / SDK 五套接口共用内核
模型自由度 订阅、API key、兼容端点、本地模型都可以
会话模型 树状会话,分支、fork、压缩都不丢历史
上手成本 需要一点配置和习惯终端;换来的是可控性

如果你更看重"安装即用、功能覆盖广",可能倾向 Claude Code、Codex CLI 这类产品;如果你更看重"我能改、我能嵌、我能换模型",Pi 的性价比很高。两者并不冲突——Pi 的 MIT 协议和 SDK 允许你把它当成基础设施来用。

十三、安全提醒(务必读)

  • 不是沙箱:bash 工具与扩展以 Pi 进程权限运行,扩展更是直接跑在进程里。不要对不可信仓库、来源不明的扩展随意授予信任
  • 凭据保护:auth.json 里可能是 API key 或 OAuth token,注意权限,别提交进 Git
  • 导出与分享要审:/export、/share 出来的内容可能包含完整 prompt、命令输出和文件内容
  • 无人值守要收紧:CI/服务器上跑时,尽量限制工具集与目录范围,必要时用容器化方案
  • 协议边界:Pi 本体 MIT;Pi-Flash 是 GPL-3.0-or-later 的第三方桌面封装,再分发时注意许可证与名称商标约定

十四、结语

Coding agent 的竞争,正在从"模型谁更强"转向"harness 谁更懂工作流"。Pi 的选择是:内核做小,接口做全,扩展点做透,把决定权交给使用者。它不是一个替你做完所有决定的工具,而是一套让你自己组装工作流的积木——这既是它的门槛,也是它最值钱的地方。

相关链接: