上一篇把 Codex 修 Bug 的过程拆开以后,Agent Loop 这件事,我算是有了一点具体的感觉。
模型先看任务,再决定要不要读文件、跑命令;工具执行完,结果重新交给模型;模型拿着新的信息,继续判断下一步。这个过程说清楚以后并不复杂。
问题是,真让我自己从一个空目录开始写,我还是不知道该从哪里下手。
模型怎么接?工具放在哪里?消息来回传的时候,状态又是谁管的?
这些问题靠画图还能继续讲,但再往下讲,估计连我自己都会觉得有点虚。我需要找一个已经跑起来的项目,看看别人到底是怎么把这些东西接到一起的。
我前后翻了几个 Agent 项目,最后留下的是 Pi,github地址在这:https://github.com/earendil-works/pi
我写这篇时,它大约有 7.9 万个 Star。这个数字当然很显眼,也会让人下意识觉得:这么多人关注,拿来学应该不会错。
但我没有马上决定用它。
因为项目很火和适合初学者拆是两回事。有些 Agent 项目首页看着很完整,点进源码却会发现里面同时放着工作流、知识库、多 Agent、监控、评测和各种模型适配。功能确实多,可我现在连最基本的循环都刚弄明白,进去以后大概率只是在目录之间来回跳。
我想找的项目不用什么都有,但最好能让我看到一条完整的线:底下怎么调用模型,中间怎么让 Agent 跑起来,最外面又是怎么变成一个真正能用的程序。
Pi 的仓库刚好能顺着这条线往下看。
我原本以为 Pi 就是另一个 Codex
刚知道 Pi 的时候,我把它理解成一个终端里的 Coding Agent。安装以后输入 pi,然后就可以让它读代码、改文件、运行命令。
这个理解也没错,只是说的是最外面那一层。
翻仓库时,我看到它把几个核心包分开了:
pi-ai
pi-agent-core
pi-coding-agent
pi-tui
名字看着有点多,不过顺着一次实际使用过程想,就没那么绕了。
我们在终端里直接使用的是 pi-coding-agent。对话、会话、文件操作,还有执行命令这些功能,最后都在这里组成了一个可以运行的 Coding Agent。
继续往里看,会碰到 pi-agent-core。它负责 Agent 运行时、工具调用和状态。上一篇反复提到的那个循环,主要就在这一层发生。
再下面的 pi-ai 用来处理不同模型的调用。OpenAI、Anthropic、Google 的接口各有差异,上层如果每接一个模型都自己适配一遍,很快就会变得很乱,所以 Pi 单独做了一层。
pi-tui 比较好理解,它管的是终端界面。
我现在脑子里的关系大概是:
pi-coding-agent 最后拿来使用的 Coding Agent
↓
pi-agent-core 让 Agent 和工具循环起来
↓
pi-ai 和不同模型打交道
pi-tui 把交互显示在终端里
这也是我最后选 Pi 的主要原因。它有成品,可以先跑起来看看;里面的关键部分又没有全搅在一起。以后写到模型调用,就去对照 pi-ai;自己开始写 Agent Loop,再去看 pi-agent-core。
不需要现在就把整个仓库读一遍。
还有一个细节我挺喜欢。Pi 默认给 Coding Agent 的工具只有四个:read、write、edit 和 bash。
读文件、写文件、修改文件、执行命令。
数量不多,但已经足够完成不少编程任务。正因为工具少,第一次观察它时,反而容易看清模型为什么选这个工具、工具结果回来后又做了什么。要是一上来就有几十个工具,我估计又会把注意力放到功能列表上。
先别读源码,我决定把它跑起来
仓库结构大致看完后,我本来想直接打开 pi-agent-core。
后来还是忍住了。
一个程序连实际界面都没见过,就开始追它的状态和事件,很容易把自己追晕。先用一次,至少以后在源码里看到某个工具调用时,知道它最后会出现在什么地方。
Pi 可以直接通过 npm 安装:
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
装好以后,可以先确认一下版本:
pi --version
注意最好node版本要 >= 22.19.0才能安装最新的pi版本
接着进入准备好的实验目录,输入 pi,按照界面提示输入apikey,就可以接入AI模型了,我这次选择的是接入deepseek的api。
更具体的环境配置可以直接参考 Pi 的官方文档:(https://github.com/earendil-works/pi/blob/main/packages/coding-agent/README.md),这里不展开。
第一次就让它做件很小的事
环境准备好以后,我单独建了一个实验目录,没有直接拿现有项目来试。
这么做还有一个原因。Pi 在仓库说明里专门提醒过,它默认没有一套内置的权限系统去限制文件、进程、网络或者凭据访问。它能做什么,很大程度上取决于启动它的用户本来就有什么权限。如果需要更严格的边界,要另外使用容器或者沙箱。
这一点和我平时使用 Codex 时看到的权限确认不太一样。
第一次尝试没必要上来就挑战真实项目。目录里放一个测试文件,跑错了也没什么损失。
我准备的 input.txt 内容如下:
这是我第一次运行 Pi。
这次实验只验证三件事:
1. Pi 能读取当前目录里的文件;
2. Pi 能根据文件内容完成一个简单任务;
3. Pi 能在当前目录创建一个新文件。
DeepSeek 接好以后,接下来要发给 Pi 的任务是:
读取当前目录里的 input.txt,把内容整理成 summary.md。summary.md 需要包含一个标题和三条要点,不要修改 input.txt。完成后告诉我你使用了哪些工具。
这次不考验模型能不能写出多好的总结。我只想看它会不会先调用 read,拿到文件内容后再调用 write,最后把文件留在当前目录。

整个过程非常顺利,也符合我们的预期,我发现pi的速度非常快,几乎我刚发送他就秒回我并且完成任务了,没有过多的思考。
接下来才轮到源码
选定 Pi,并不等于下一篇就要冲进 pi-agent-core 逐行读代码。
我现在只知道它大致分成哪几层,也把程序装了起来。真要看懂 Agent Loop,还得先把最底下那件事补上:一次普通的模型调用,究竟传了哪些消息,又拿回了什么。
所以下一篇我准备先不碰工具,只写一个最小的模型调用。
等我自己把 System Prompt、用户消息和模型输出接起来,再回头看 pi-ai,里面很多代码应该才会从“项目作者的写法”,变成我能对照着理解的东西。
夜雨聆风