架构师(JiaGouX)
我们都是架构师!
架构未来,你来不来?
最近一直在研究不同的 Agent 和 Harness。这个周末,我把 Pi 的仓库又从头翻了一遍。
上一次看 Pi,我的注意力还在那四个默认工具上:read、bash、edit、write。这次顺着主循环、会话、扩展和 Codemode 一路读下来,我反而觉得,“四个工具”已经不是最值得聊的部分了。
今天的 Pi 并不小。仓库里有模型适配、Agent Core、Coding Agent、TUI、MCP、Codemode、会话管理,甚至还有一套实验性的持久化运行时。只看功能清单,它和“极简”似乎已经离得很远。
可它最常走的那条路依然很短:模型拿到上下文,决定是否调用工具,Harness 执行工具,再把结果交还给模型。其他能力都围着这条路接进来,没有把核心循环拖成一个什么都管的控制器。
所以这次我想换个角度。先不数 Pi 有多少功能,直接顺着一次任务走,看看它把什么留在主路径上,又把什么放到了边界外。
极简,先看那条最短的执行路径
Pi 的代码分层很直白。pi-ai 负责抹平不同模型供应商的接口差异,pi-agent-core 负责 Agent 循环,pi-coding-agent 再往上补齐文件工具、会话、上下文压缩、扩展和交互界面。
这几层里,我最关注的是 pi-agent-core。
它并不知道什么是 Git 仓库,也不关心 Markdown、MCP、终端界面和会话文件。它手里只有模型、消息和工具。一次任务大致就是下面这条路径:
用户消息 → 模型响应 → 工具调用 → 工具结果 → 再问模型 → 结束
图 1:Pi 把主路径压短,把会话、MCP、Codemode 和运行隔离放到边界上。
短归短,该处理的异常没有被省掉。
同一条回复里出现多个工具调用时,Pi 默认可以并行执行;某个工具声明必须串行,整批调用就按顺序处理。工具完成的快慢可能不同,但写回模型上下文时仍按原来的调用顺序排列。这样既不必为慢工具白等,也不会让并发完成顺序改变模型刚才表达的意图。
模型的回复如果被截断,工具参数很可能只生成了一半。Pi 不会拿这段残缺 JSON 去碰文件或启动进程,而是把调用标成失败,交给模型重新处理。这是个很小的细节,却是“能跑”和“敢让它跑”的区别。
任务执行中,用户还可能临时插话。
比如 Agent 正在改代码,我补一句“配置文件先别动”。这句话应该尽快改变当前方向。Pi 把这种输入叫 steering message,会在一轮工具执行结束后插进当前任务。另一种情况是 Agent 已经准备收尾,我又说“顺便补一下测试”,它更适合作为 follow-up message,等当前任务自然停下来再开启下一轮。
核心循环没有硬编码这些产品策略,只留下几个位置清楚的接口:prepareRequest() 在请求模型前整理输入,prepareNextTurn() 决定下一轮如何继续,finishTurn() 在一轮结束时判断收口还是续跑。上下文压缩、模型切换和扩展逻辑从这些接口接入,主循环仍然只管“模型—工具—结果”这件事。
图 2:一轮任务里,模型、工具和结果按固定顺序回到上下文;并发和插话都在边界接口里处理。
我觉得 Pi 的极简先体现在这里:它没有假装真实任务只有 happy path,只是把变化关在了几个能说清楚的位置。
四个工具,是默认词汇,不是能力上限
pi-coding-agent 当前定义了 8 个内置工具:read、bash、powershell、edit、write、grep、find 和 ls。日常编码默认给模型的是 read、bash、edit、write;源码里还单独准备了由 read、grep、find、ls 组成的只读集合。用户和扩展也可以换掉这组默认值。
从使用上看,四个工具已经能覆盖大部分编码动作。read 负责看,edit 和 write 负责改,剩下那些搜索、构建、测试、Git 操作,大多可以通过 bash 完成。它未必是最安全、最适合所有团队的一组配置,但模型要学习的接口很少。
这里有一层很重要的区分:Pi 进程拥有的能力,和模型这一轮看到的工具,并不是同一张表。
工具集合发生变化时,declareToolChanges() 会把新增项和移除项作为会话记录写下来。恢复会话时,运行时可以沿着记录还原当时的工具状态。工具不是启动时塞进系统提示词、之后再也不变的一段静态文本,它也是任务状态的一部分。
MCP 把这个思路做得更明显。一个 Server 可以接入几十个工具,但这些工具不必全部以完整 schema 出现在模型面前。Pi 为 MCP 工具提供了四种暴露方式:
direct:直接声明给模型,适合高频工具; deferred:需要时再搜索和加载; codemode:交给 Codemode 内的脚本调用; hidden:接入运行时,但不向模型开放。
默认值是 codemode。也就是说,接入 MCP 并不等于把整个工具箱摊在上下文里。模型先通过 searchTools 和 describeTool 找到需要的能力,再在脚本里调用。
图 3:工具生态可以很大,模型这一轮看到的只是被选出来的接口、上下文和脚本输出。
这个差别在工具多、返回结果大的时候很实在。普通 MCP 调用的文本结果如果超过 20 KB,Pi 会把中间部分截掉,只把头尾留给模型,完整结果另存到临时文件。Codemode 则能拿到完整返回值,在脚本里筛选、聚合,最后只交回几行真正有用的内容。
系统提示词也采用了相近的做法。工具、规则、项目上下文、Skill、当前目录分别组成独立 section;其中一部分发生变化,Pi 会在会话里记录 patch,再从当前状态组装新的提示词。
这里要把边界说清楚:这不代表每次请求供应商时只发送差异。代码能确认的是,提示词的组成和变化可以追踪、可以恢复。至于最终发给模型的内容,仍然是运行时整理后的完整上下文。
Pi 压缩的是模型眼前的接口,不是宿主进程实际接入的能力。这比“四个工具够不够用”更接近它的设计重点。
会话完整留下,模型只看当前分支
长任务还有一个绕不过去的问题:会话记录希望尽量完整,模型上下文却不能无限增长。
很多实现一开始直接维护一份 messages 数组。短任务没什么问题,等到对话需要压缩、回退、分支,麻烦就来了。为了省上下文而删掉旧消息,审计和恢复会丢信息;什么都不删,窗口迟早会被工具结果塞满。
Pi 把这两件事分开处理。
会话以 append-only 的 JSONL 树保存。每条记录都有自己的 id 和 parentId。从旧节点继续对话,只是长出一个新分支;切换分支,只是把当前叶子指向另一条路径。原来的记录不需要删除,也不需要原地改写。
真正送给模型的内容,由 buildSessionProjection() 根据当前分支临时生成。它沿着当前叶子往回找,识别最近一次 compaction,把摘要、保留的消息和压缩后的新消息重新拼成模型上下文。早期原始记录仍在磁盘里,只是不再进入这一轮请求。
如果需要纠正某条消息对上下文的影响,Pi 也不是回头修改原记录,而是追加一条 context edit,说明替换或移除哪部分模型可见内容。历史怎么发生、模型现在看到什么,仍然能分开追踪。
压缩摘要还会保存读过和改过的文件列表。这个信息看起来不起眼,长任务里却很有用:旧的工具输出可以不再携带,Agent 至少知道自己碰过哪些文件,后面继续修改或排查时不至于完全失忆。
到了请求模型之前,AgentSession 会用这份 projection 替换内存里的消息列表,确保真正发出去的是当前分支的标准视图。上下文溢出时,Pi 会自动 compact 后重试一次;再失败就明确结束,不在后台一遍遍压缩和重放。
我很喜欢这种处理。会话负责留下事实,projection 负责服务当下。两边各有一个清楚的目标,不用互相迁就。
Codemode:让一次工具调用完成一段编排
工具数量继续增加后,光是延迟加载 schema 还不够。更大的开销经常来自中间结果。
假设模型要查几十个 issue,从中找出包含某个标签、最近一周更新、同时还没有负责人的条目。逐个调用工具时,每次参数和返回值都会进入对话,模型最后只是为了得到一张很短的名单,却要重新读一大堆中间数据。
Codemode 的做法是让模型生成一段 JavaScript,在 QuickJS VM 里完成多次工具调用、筛选和汇总,最终只把名单带回主上下文。嵌套工具调用不会逐条变成新的对话消息,运行时只保存名称、参数、状态、耗时和错误等有上限的元数据,不保存大块返回结果。
这个 VM 很克制。脚本没有 Node API,也拿不到 fetch、process、require、模块系统和 WebAssembly;数据穿过 VM 边界时要经过 JSON 序列化。运行时还有限时、内存限制和中断机制,用来处理死循环与资源失控。
但 QuickJS 解决的是脚本编排和上下文污染,并没有凭空创造一个安全沙箱。
脚本调用 read、bash、write 或某个 MCP 工具时,真正执行动作的还是宿主侧工具。它能访问哪些文件、进程和网络,取决于 Pi 进程拿到了什么权限。VM 里的 JavaScript 看不到 process,不代表被它调用的 bash 也失去了宿主权限。
这点如果不分清,很容易高估 Codemode 的隔离能力。它主要缩短的是模型和工具之间的数据路径,安全边界仍要在工具或运行环境上建立。
Pi 把哪些事留在了边界外
Pi 默认不会为每次工具调用弹出确认,也没有内置一套按目录、命令或网络地址划分的权限系统。它继承启动用户和宿主进程的权限。
项目 trust 解决的是另一个问题:一个陌生仓库能不能在用户不知情时加载项目自己的扩展、Skill 和配置。它能阻止受保护的项目资源悄悄进入运行时,却不会限制已经启用的 bash 或 write 能访问哪里。还有一个容易漏掉的细节:AGENTS.md、CLAUDE.md 这类上下文文件默认不受 project trust 控制,除非主动关闭 context loading。trust 是加载策略,不是操作系统的安全边界。
扩展同样运行在 Pi 进程里,可以访问宿主环境。需要处理陌生代码、敏感凭据或多租户任务时,更稳妥的做法是隔离整个进程,或者把高风险工具路由到容器和远程沙箱。Pi 文档给了 Plain Docker、Docker Sandboxes、OpenShell、Gondolin 等方案,但选择哪一种、隔离做到多细,由使用者自己决定。
另外,Pi 默认也没有把 sub-agent、plan mode 这类工作流固化进核心产品。需要的人可以用扩展加进去。这样的好处是默认行为容易理解,代价也很明确:团队如果需要审批、统一策略、多人协作和集中审计,需要在 Pi 之外继续搭。
这一点从仓库演进里也能看出来。现在已经有 pi-durable 以及一组服务端、协议和客户端包,但标准 Coding Agent 的主链路仍然围绕 pi-agent-core 和 AgentSession 展开,durable 集成目前放在 experimental 目录。复杂能力有自己的位置,没有被一股脑压进默认 CLI。
所以我现在更愿意把 Pi 看成一套边界清楚的 Harness 基础,而不是一套替团队把所有决策都做完的 Agent 平台。
极简不是代码少,是核心路径少做决定
这次重新读 Pi,我最大的感受是:一个 Harness 的极简程度,不能只看仓库大小、系统提示词长度,或者默认暴露了几个工具。
更有用的判断方式,是看核心路径替上层做了多少决定。
Pi 的 Agent Core 只守住模型、工具和结果之间的循环;会话完整保存,再按当前分支投影;工具可以接很多,模型只看此刻需要的;复杂编排进入 Codemode,权限隔离留给工具和运行环境。每一层都不神秘,组合起来却足够支撑真实的长任务。
这套取舍当然不适合所有场景。如果公司内部需要细粒度权限、强审批和统一治理,Pi 给的还只是地基。但作为 Harness,它把“默认怎么跑”和“需要时怎么扩”分得很清楚。
我现在看一个 Agent 框架,会先找它最常走的那条路径,再看功能越来越多之后,这条路径有没有被拖成万能控制器。Pi 的仓库已经长大了,主循环却依然能顺着读下来。我觉得,这才是它最有价值的极简。
往期相关推文
《Pi 与 DeepSeek Harness 架构对比:Agent Loop 如何处理继续、收口与恢复》 《从 Claude Code 到 Codex:Coding Agent 的 Harness》 《输出结果不等于完成任务:Agent 最容易忽略的一环》
参考资料
本文代码阅读基于 Pi main 分支提交 96abe9a(2026-10-11),仓库主要包版本为 1.1.0。
Pi 官方仓库(https://github.com/earendil-works/pi) Pi 官方文档:How Pi Works、MCP Servers、Codemode、Containerization(https://pi.dev/docs/latest) Mario Zechner,What I learned building an opinionated and minimal coding agent(https://mariozechner.at/posts/2025-11-30-pi-coding-agent/) Armin Ronacher,Pi: The Minimal Agent Within OpenClaw(https://lucumr.pocoo.org/2026/1/31/pi/) Armin Ronacher,What is Codemode(https://lucumr.pocoo.org/2026/10/6/codemode/)
如喜欢本文,请点击右上角,把文章分享到朋友圈
如有想了解学习的技术点,请留言给若飞安排分享
因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享
·END·
相关阅读:
- Loop Engineering,应该赞成还是反对?
- Claude 做方案,Codex 写代码:多模型协作怎么交接才稳
- 架构排熵:Loop Engineering 的持续清理系统
- CLAUDE.md 拆解:Agent 进仓库前的上下文入口
- Harness工程还没唱罢,Environment工程已然登场
- 设计 Self-Harness 架构:会自我改进的Harness
版权申明:内容来源网络,仅供学习研究,版权归原创者所有。如有侵权烦请告知,我们会立即删除并表示歉意。谢谢!
架构师
我们都是架构师!
关注架构师(JiaGouX),添加“星标”
获取每天技术干货,一起成为牛逼架构师
技术群请加若飞:1321113940 进架构师群
投稿、合作、版权等邮箱:[email protected]