12 一文吃透 Pi:10w stars 的极简 Agent harness 280

AI小蝌蚪2026-09-171155 阅读💛 241 收藏

一文吃透 Pi:10w stars 的极简 Agent harness

Hi,我是松柏。

今年 AI 编程 Agent 领域卷得不行,Claude Code、Cursor、OpenCode、Codex CLI 都在疯狂堆功能,宠物、sub-agents、plan mode、MCP、扩展市场,恨不得把能想到的东西全塞进去。

不过有个项目却反其道而行之,它就是 Pi,一个主打极简的 Agent Harness:

它默认只给模型提供了 4 个工具:readwriteeditbash,系统提示词加工具定义一共不到 1000 tokens。

就这么个极简到离谱的东西,GitHub 10 万+ stars,npm 周下载量 120 万+,3 个月从 54k 涨到 98k。不少人已经拿它当日常主力了:

这篇文章我会先带大家快速上手 Pi,然后深入拆解它的核心设计理念和分层架构。看完之后你会对 Agent 框架的设计思路有一个新的认识。

废话不多说,点赞关注,我们直接开始!

快速上手

安装

一行命令搞定:

bash
复制代码
# 推荐方式 curl -fsSL https://pi.dev/install.sh | sh # 或者用 npm npm install -g --ignore-scripts @earendil-works/pi-coding-agent

装完之后终端里直接敲 pi 就能进入交互界面。

配置模型

Pi 支持 15+ 模型提供商,Anthropic、OpenAI、Google、DeepSeek、xAI、Groq、Ollama 这些基本都有。配置方式也简单:

  • 有订阅的话(Claude Pro/Max、ChatGPT Plus 等),直接 /login 走 OAuth
  • 用 API Key 的话,设好环境变量就行,比如 ANTHROPIC_API_KEY

进去之后 /model 切模型,Ctrl+P 快速循环你的常用模型列表。而且它支持会话中途换模型,上下文会自动做跨提供商的转换,这个后面架构部分会细说。

基本使用

跟其他产品类似,打开终端,输入你的需求,Pi 就会帮你完成:

bash
复制代码
# 交互模式 pi # 一行式调用,适合脚本或 CI pi -p "给这个函数加单元测试"

Pi 默认只给模型 4 个工具:

  • read:读文件(支持图片)
  • write:写文件,自动建目录
  • edit:精确文本替换
  • bash:执行任意命令

你可能会觉得 4 个也太少了。不过仔细想想,有了 bash,需要搜文件就跑 rg,需要看 git 日志就跑 git log,需要装依赖就 npm install。 所以大部分需求其实不用专门做 tool,一个 bash 就能实现了,这也是 Pi 的核心设计思路之一。

会话管理

Pi 的会话不是普通的线性记录,而是一棵树。每次对话都会存成树形结构,你可以在任意节点分支出去:

bash
复制代码
pi -c # 继续上次的会话 pi -r # 浏览历史会话列表 pi --fork <id> # 从某个历史节点分出新分支

会话里用 /tree 可以看到完整的对话树,想跳回哪个节点就跳回哪个节点。

四种运行模式

除了终端里直接交互,Pi 还有三种无头模式,方便把它集成到其他地方:

模式命令适合场景
Interactivepi日常开发,完整终端体验
Print/JSONpi -p "query"脚本调用、CI 流水线
RPC--mode rpcstdin/stdout JSON 协议,给非 Node 项目用
SDKTypeScript API嵌入你自己的应用

这四种模式共享同一套 session 格式和事件流,所以不管从终端、Web 还是 CI 调用,看到的都是同一个 Agent。比如 OpenClaw 就是拿 Pi 的 SDK 模式做的一个完整产品。

OK,到这里基本上手流程就走完了。

接下来聊聊更有意思的部分,Pi 为什么要这么设计。

极简的设计哲学

Pi 的作者 Mario Zechner 说过一句话:"if I don't need it, it won't be built",翻译成大白话就是:没用的东西我不做。 整个 Pi 的设计都是围绕这条原则展开的。

极简系统 Prompt

先看 Pi 的完整系统提示词:

markdown
复制代码
You are an expert coding assistant. You help users with coding tasks by reading files, executing commands, editing code, and writing new files. Available tools: - read: Read file contents - bash: Execute bash commands - edit: Make surgical edits to files - write: Create or overwrite files Guidelines: - Use bash for file operations like ls, grep, find - Use read to examine files before editing - Use edit for precise changes (old text must match exactly) - Use write only for new files or complete rewrites - Be concise in your responses - Show file paths clearly when working with files

就这?就这!加上工具定义一共不到 1000 tokens。

为什么系统提示词要这么短呢? 因为现在的前沿模型经过大量 RL 训练,其实已经天生就知道怎么当一个 coding agent。我们不需要在 system prompt 里手把手教它该怎么做,它自己就会选工具、读文件、跑命令。Pi 在 Terminal-Bench 2.0 上的跑分也验证了这一点,极简 prompt 的效果并不比上万 token 的 prompt 差:

而且 prompt 越短越稳定,提供商那边的 cache 就越容易命中,每次请求的成本也更低。

4 个工具

前面提到 Pi 只有 readwriteeditbash 四个工具,这确实和其他 Agent 动辄十几个 tool 的做法很不一样。

Pi 的思路是与其给每个功能都做一个专门的 tool(搜索 tool、git tool、测试 tool……),不如只留一个 bash,让模型自己写命令。

另外工具少还有一个好处,就是模型做决策更快。工具越多,模型越容易纠结用哪个,甚至选错,4 个工具就那么几种排列组合,选择成本几乎为零。

全权限运行

Pi 默认不弹任何权限确认,没有“是否允许写入文件”,没有“是否允许执行命令”,模型拿到工具就直接用。

这听起来挺激进的,不过也不是没道理,因为只要 Agent 能写代码、能执行代码、能联网,那所谓的权限弹窗本质上只是在给你一种安全感,实际拦不住什么。 毕竟就算让我们自己审批,不也是一路确认允许嘛。

当然,如果你的场景确实需要隔离,Pi 也提供了三种容器化方案,Gondolin(本地微虚拟机)、Docker、OpenShell(策略沙箱),按需选用就行。

那些故意不做的功能

这部分我觉得是 Pi 最有意思的地方。很多 Agent 产品当成卖点的功能,Pi 一个都不做,但每个都给了更简单的替代思路:

1)Plan Mode → 写文件

不需要内置计划模式,直接写个 PLAN.md

markdown
复制代码
## Goal 重构认证系统支持 OAuth ## Approach 1. 调研 OAuth 2.0 流程 2. 设计 token 存储 schema 3. 实现认证端点 4. 更新前端登录流 ## Current Step 正在做第 3 步

Agent 能读能改,你也能手动编辑,还能用 git 管版本。比藏在 Agent 内部的 Plan Mode 透明多了。

2)Sub-agents → bash 自调用

Pi 可以通过 bash 启动另一个自己:

bash
复制代码
pi -p "review this PR" --provider anthropic --model claude-sonnet-4-5

还能丢进 tmux 跑,全程都能看到子 Agent 在干什么。相比之下,Claude Code 的 sub-agent 就是个黑盒,你只能看到最后的结果,中间过程完全不透明。

3)MCP → CLI 工具 + README

MCP 的问题在于上下文开销。像 Playwright MCP 一注册就是 21 个 tool、13.7k tokens,不管你这次用不用都占着窗口。Pi 的做法是做成普通的 CLI 工具,配一个 README,Agent 需要的时候用 bash 调,顺便读下 README 看用法,只在真正用到时才付 token 成本。

4)后台进程 → tmux

需要在后台跑 dev server?用 tmux 起一个:

bash
复制代码
tmux new-session -d -s dev "npm run dev"

Agent 随时可以 tmux capture-pane 看日志输出,比内置的后台 bash 功能更灵活,可观测性也更好。

分层架构拆解

聊完设计理念,我们来看看 Pi 的代码是怎么组织的。

Pi 是一个 TypeScript monorepo,核心分成四层,从底到顶依次是:

pi-ai:统一多模型 API

最底层的包,把各家 LLM 提供商的 API 抽象成一套统一接口。底层其实只需要对接四种协议,OpenAI Completions、OpenAI Responses、Anthropic Messages、Google Generative AI,各家提供商基本都是这四种 API 的某个变体。

这一层有几个值得学习的设计点:

首先是跨提供商上下文接力。你可以在会话中途从 Claude 切到 GPT,pi-ai 会把 Claude 的思维链转成 <thinking> 标签塞进消息里,尽量让新模型能理解之前的上下文。代码上大概是这样:

typescript
复制代码
// 用 Claude 开始对话 const claude = getModel('anthropic', 'claude-sonnet-4-5'); context.messages.push({ role: 'user', content: '25 * 18 = ?' }); const claudeResponse = await complete(claude, context); // 中途切到 GPT,上下文自动转换 const gpt = getModel('openai', 'gpt-5.1-codex'); context.messages.push({ role: 'user', content: '对吗?' }); const gptResponse = await complete(gpt, context);

然后是全链路的 Abort 支持。很多 LLM 封装库根本没处理请求中断的情况。pi-ai 从一开始就支持 AbortController,而且中断之后还能拿到已经生成的部分结果,不会因为中断就全丢了。

还有工具结果分离。一个工具执行完,可以分别返回“给 LLM 看的文本”和“给 UI 展示的结构化数据”,不用再从一堆文本输出里费劲去解析了。

pi-agent-core:Agent 循环

中间层,实现 Agent 的核心运行循环:收到用户消息 → 调 LLM → LLM 要用工具 → 执行 → 结果喂回去 → 再调 LLM → 直到不再需要工具为止。

这层的关键类是 Agent,它除了管状态(消息历史、工具列表、当前模型),还提供了两种消息队列:

  • Steering:Agent 干活的时候你插一句话进去,当前工具跑完就会处理
  • Follow-up:排队等着,Agent 这轮忙完了再处理

整个循环是事件驱动的,所有生命周期节点都通过 AgentEvent 暴露出来,上层拿到事件就能构建各种 UI。

pi-coding-agent:编码 Agent CLI

应用层,也就是你实际敲的那个 pi 命令,核心是 AgentSession,在 Agent 循环之上加了这些东西:

  • 会话持久化:JSONL 格式的树形存储,每条消息带 idparentId,分支操作不需要新建文件
  • 自动压缩:上下文快满的时候自动 compaction 旧消息,压缩策略可以通过扩展自定义
  • 工具注册:内置 read/write/edit/bash,另外还有 grep/find/ls 三个只读工具可选
  • 扩展加载:用 jiti 动态加载 TypeScript,写完不用编译直接跑

前面提到的四种运行模式就是在这一层实现的,它们共享同一套 session 和事件流。

pi-tui:差分渲染的终端 UI

Pi 的终端 UI 没有像 Amp、OpenCode 那样接管整个终端画面,采用的是像普通 CLI 一样往下写内容,保留终端自带的滚动和搜索。

渲染方式是保留模式(Retained Mode):每个组件有一个 render(width) 方法,返回带 ANSI 样式的文本行。已经流式输出完的消息会缓存渲染结果,下次直接复用。

更新的时候用差分渲染,新旧两帧逐行对比,只重绘变化的部分,再配合终端的同步输出转义序列(CSI ?2026h / CSI ?2026l),把一帧的所有输出攒起来原子性地刷到屏幕上,在 Ghostty 和 iTerm2 上基本做到了零闪烁。

扩展系统

Pi 整套扩展机制分三层:

Extensions(代码级)

就是 TypeScript 模块,可以注册工具、添加命令、绑快捷键、拦截工具调用、自定义 UI 组件。示例代码:

typescript
复制代码
// ~/.pi/agent/extensions/my-tool.ts import type { ExtensionAPI } from '@earendil-works/pi-coding-agent'; import { Type } from 'typebox'; export default function(pi: ExtensionAPI) { pi.registerTool({ name: 'search_docs', description: '搜索项目文档', parameters: Type.Object({ query: Type.String() }), async execute(id, params, ctx) { const result = await searchIndex(params.query); return { content: [{ type: 'text', text: result }] }; } }); }

保存后 /reload 热加载,不用重启。官方仓库有 50+ 示例,从权限确认、Git 检查点到 Snake 小游戏都有。

Skills(提示词级)

Skills 是 Markdown 文件,定义特定任务的指令和工作流。和 Extensions 的关键区别在于它是按需加载的,平时只在上下文里保留一行描述(几十个 token),等真正被触发时才加载完整内容。

这样即使你装了几十个 Skill,也不会撑爆上下文窗口,也就是我们常说的“渐进式上下文披露”。

Packages(生态打包)

Extensions、Skills、Prompt Templates、Themes 都可以打包成一个 Package,通过 npm 或 git 安装:

bash
复制代码
pi install npm:pi-autoresearch pi install git:github.com/badlogic/pi-doom

Shopify 的 pi-autoresearch

说到 Package,就不得不提目前最出圈的一个,Shopify 工程师 David Cortés 做的 pi-autoresearch。

它是一个自动化性能优化循环:你设定一个要优化的指标(比如构建时间),Agent 就会自动尝试改代码、跑 benchmark、比基线快就保留、慢了就回滚,然后继续下一轮,直到你打断。

最有意思的是,这个扩展本身就是让 Pi 写出来的。

后来 Shopify CEO Tobi Lütke 看到这个东西,直接上手贡献了 32 个 commit。目前 pi-autoresearch 在 GitHub 上有 7900+ star,Shopify 内部用它把单测速度提升了 300 倍,React 组件挂载快了 20%。

结语

我觉得 Pi 这个框架里最值得学习的一点就是不是功能越多越好,把核心的东西做到位就行,你们觉得呢?

这篇文章就到这里了,如果有帮助的话麻烦点个关注吧~

下期再见,拜拜👋🏻

AI
Agent
源码学习
Pi
0个评论
全部评论
最热最新楼层
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
co松柏
co松柏
等级vip
内容推荐
更多
从玩具 Demo 到稳定交付:个人开发者的 3 条 AI 编程工程铁律
12
平替 Codex?AI 工具 Qoder 保姆级教程
4
入职笔记4 月入职一家初创科技公司,忙忙的。经过鱼皮系列产品的锤炼,毫无疑问的成为了这个初创公司最懂 AI 开发的人。天天和头顶 boss 白扯 AI 技术,他是通过抖音学习大模型的,得到的知识都比较片面,辅助他对齐认知也花了不少口舌。也因此被重点“使用”,经历了很多新的技术边界。像是通过自然语言去操作业务和数据库;大模型响应、工具调用等等各个阶段的速度优化、RAG 知识库的搭建以及优化和历史遗留
8
把 AI 训成"原始人"就能省 65% Token 费?扒一扒 GitHub 趋势榜这个十万星的神奇项目
7
千问:我还得亏好几年
2
作者分享
更多
AI+Excalidraw,用自然语言画手绘风格技术图
39
浏览器插件发布上线保姆级流程
16
用 AI 写了个帮我管理浏览器书签的插件
20
程序员必备技能——AI 画技术图技巧
135
到底 MCP 有什么魅力?10分钟让 AI 直接操作数据库!
15

文章评论(6

山问津37 分钟前

收藏了,以后慢慢研究。

回复
一叶知秋4 分钟前

思路清晰,干货满满。

回复
风倚栏44 分钟前

内容翔实,正好需要,先收藏再看。

回复
青柠微凉28 分钟前

很有价值的分享,感谢整理。

回复
一叶知秋刚刚

这篇文章分析得很透彻,收藏了!

回复
空向阳47 分钟前

路过

回复