/ By 煎鱼 / #harness #agent #源码解读 / AI 入口

Pi 源码解读:Agent Harness 和 Agent OS,到底差了什么?

从 Pi 的 Agent、AgentSession 与 Extension API 出发,解释它为何是适合改造的 Agent Harness,以及它距离 Hermes、OpenClaw、nanobot 这类个人 Agent OS 还缺哪些运行时层。

“Pi 能不能装几个插件,直接变成 Hermes 或 OpenClaw?”

这个问题很容易被功能表带偏。四个项目都能接模型、调工具,也都能扩展;如果只看这些方框,Pi 和它们像是少装了几块积木。

但顺着 Pi 的源码往下看,结论要更克制一些:Pi 是一个把 Agent 循环、会话与扩展接口做得很干净的 Harness;Hermes、OpenClaw 和 nanobot 则把消息入口、持续运行、记忆、调度与治理一起交付成了 Agent OS。

前者可以长成后者,但不是把 Extension 数量加到某个阈值就会自动发生。缺的不是一个天气工具,而是一组必须共同运行、共同审计的控制面。

#先说结论

Pi 适合作为可控的 Agent 执行底座;若目标是“开箱即用的个人助手”,还需要另行拥有或选择提供渠道、调度、身份、权限、记忆和运维的 Agent OS。本文据此区分源码已经提供的能力与必须由上层补齐的责任。

数据快照

  • 最后核验:2026-08-06
  • Pi 源码快照:bde81c8main 分支当日提交)
  • 主要对象:Pi Agent Harness、Hermes Agent、OpenClaw、nanobot
  • 讨论边界:本文比较它们的运行时职责,不比较模型能力、社区规模或某次任务的成功率
  • 证据限制:Pi 部分以固定源码快照为准;其余三个项目的“开箱能力”来自当日官方 README / 文档,不能推出它们在每种部署配置下都有相同表现

#先把“Agent”拆成两层

用人话说,Harness 是发动机和驾驶控制:给它任务、模型、工具与状态,它能把一轮又一轮工作跑完。Agent OS 则还要负责让这台发动机长期待命:消息从哪里进来、该由哪个会话处理、什么时候唤醒、用谁的身份访问外部系统、出了问题如何停下与追溯。

表 1:四个项目的公开职责边界;状态以 2026-08-06 的官方资料为准

维度PiHermes AgentOpenClawnanobot
核心定位可嵌入的 Agent runtime 与 coding CLI自我改进的个人 Agent运行在设备上的个人助手自托管个人 Agent runtime
单轮 Agent loop / 工具调用
扩展入口TypeScript Extension、工具、事件与 TUI工具、Skills、插件与多种后端Tools、Skills、PluginsPython SDK、MCP、工具与子 Agent
消息与网关主仓库不提供个人助手网关;另有 pi-chat 项目面向聊天自动化Gateway 连接多种聊天渠道Gateway 统一会话、事件与渠道WebUI、聊天应用与长期运行 gateway
持续任务与长期记忆可由扩展自行实现内置 cron、跨会话记忆与 skill 演化Gateway、渠道、工具与设备节点构成持续服务goals、memory、cron 与 automation 已在运行时中提供
默认安全边界不内置文件、进程、网络或凭据权限系统提供命令审批、配对和隔离文档有配对、sandbox 与暴露运行手册需按其配置与部署文档审查

Pi 的项目 README 明确把自己拆为 pi-agent-corepi-aipi-coding-agent 和 TUI:运行循环、模型适配、交互式编码界面各自独立。Pi README 对这个边界说得相当直白。相对地,HermesOpenClawnanobot 的公开入口都把聊天渠道、持续服务或自动化放进产品定义。

这不是“谁更高级”的排序。想在本地终端里精确控制一个 Coding Agent,较小的 Harness 往往更舒服;想让同一个 Agent 在 Telegram、定时任务和多天记忆之间持续工作,OS 的默认层反而省掉大量不显眼的工程。

#Pi 的最小闭环:Agent 只负责把一轮工作跑完

Pi 的 packages/agent/src/agent.ts 是理解边界最短的入口。Agent 保存当前 transcript、工具集和模型状态;收到 prompt 后,它把消息交给 runAgentLoop(),并在循环中收集模型消息、工具执行和生命周期事件。Agent.prompt()runAgentLoop() 的关系大致可以浓缩成下面这样;为说明结构,省略了类型、流式更新与错误处理。

class Agent {
async prompt(input: string) {
const messages = this.normalizePromptInput(input);
await runAgentLoop(
messages,
this.createContextSnapshot(),
this.createLoopConfig(),
(event) => this.processEvents(event),
signal,
this.streamFunction,
);
}
}

这个对象的职责很明确:模型是否继续、工具何时执行、结果怎样进入下一轮上下文,都是 loop 的内部问题。源码还把 beforeToolCallafterToolCallshouldStopAfterTurnprepareNextTurn 放进 loop 配置中。对应的配置装配代码 证明了它为外部策略留出了钩子;它不能证明 Pi 已经替你定义了“什么任务应该每天九点运行”或“陌生 Telegram 用户能否创建会话”。

图 1:Pi Agent 的单次执行闭环;依据 2026-08-06 的源码快照

flowchart TD
  S([开始:输入 prompt]) --> A[Agent 生成消息与上下文快照]
  A --> B[runAgentLoop 请求模型]
  B --> C{模型请求工具?}
  C -- 是 --> D[执行或拦截工具调用]
  D --> E[工具结果写入 transcript]
  E --> B
  C -- 否 --> F[发出 turn_end / agent_end 事件]
  F --> G([结束:本次 Agent run 空闲])
  H[外部 hook] -. 可改工具、停止或下一轮 .-> D
  H -. 可改工具、停止或下一轮 .-> B

读图时最值得注意的是终点:它是“这次 run 空闲”,不是“服务继续待命”。Pi 的 loop 已经是 Agent 最难替换的一部分,但长期运行的入口和调度不在这段 loop 里。

#AgentSession 补的是会话,不是控制平面

如果只看 Agent,Pi 像一个很干净的循环库;pi-coding-agent 再用 AgentSession 把它变成可交互的产品。这个类被 interactive、print、RPC 等运行模式共享,负责自动保存会话、模型与 thinking level、压缩、分支和 bash 执行。文件头的职责说明它对 Agent、session manager、extension runner 的依赖 共同说明了这层的任务。

这给 Pi 带来两个很实际的能力:同一段对话可以恢复、压缩和分叉;不同交互界面可以复用同一会话运行时。它仍然没有替上层回答三个 OS 问题:

  • 一条外部消息怎样路由到正确的 AgentSession
  • 没有前台终端时,谁负责唤醒、超时、重试和投递结果;
  • 这次会话的 shell、网络和凭据到底代表哪个用户、遵循哪套审批规则。

把 Session 当成 Memory 也会造成误判。Session 首先是可恢复的执行记录和当前上下文;长期偏好、跨任务知识、可检索事实、失效策略分别需要不同的写入条件、作用域和淘汰策略。Hermes 所说的跨会话记忆与 Skills 演化,或 nanobot 所说的长期记忆,讨论的是这个更上层的问题,而不仅是“把 JSONL 留在磁盘上”。

#Extension 给了积木,但没有替你画出城市规划

Pi 的 Extension API 比“插件能加一个工具”宽得多。扩展可以注册模型可调用的工具、订阅生命周期事件、拦截或修改工具调用、注入上下文、定制压缩、添加命令和 TUI,并用 appendEntry() 保存自定义状态。官方 Extension 文档 还明确说明,扩展拥有宿主进程的完整系统权限。

这意味着对话中的判断有一半是对的:可以在 Pi 上做出 memory tool、浏览器工具、定时任务入口,甚至做一个分层的审批界面。比如,下面这种拦截确实可以把危险 shell 命令从“模型想调用”变成“用户确认后才调用”。

pi.on("tool_call", async (event, ctx) => {
if (event.toolName === "bash" && event.input.command?.includes("rm -rf")) {
const ok = await ctx.ui.confirm("危险命令", "是否允许执行?");
if (!ok) return { block: true, reason: "Blocked by user" };
}
});

但它也恰好解释了为什么“装插件就开箱即用”不成立。上例只是一个字符串规则:它没有识别软链接、间接执行、远程 shell、凭据外泄,也没有给后台任务提供可复核的身份。Pi README 对此的立场很明确:它不含限制文件系统、进程、网络或凭据访问的内置权限系统,默认使用启动进程的权限;更强边界需要容器化或 sandbox。权限与容器化说明 不是缺失的文档,而是项目有意保留给宿主的责任。

#从 Pi 长成 Agent OS,真正要补的是五条跨层链路

把工具、记忆、渠道这些名词列出来很容易;困难在于它们必须和同一份身份、状态和审计记录连起来。下面的图不是 Pi 当前架构,而是基于其公开扩展点作出的实现建议

图 2:在 Pi 之上增加 Agent OS 控制面的建议分层;这是本文的工程推断,不是 Pi 官方路线图

flowchart TB
  A[渠道:TUI、Web、Telegram、飞书] --> B[Gateway:鉴权、限流、会话路由]
  C[Scheduler:cron、事件、重试] --> B
  B --> D[Control Plane:任务、身份、审批、审计]
  D --> E[Pi AgentSession]
  E --> F[Pi Agent loop]
  F --> G[工具与 MCP]
  G --> H[执行边界:沙箱、网络、凭据代理]
  I[Memory:短期、长期、知识、经验] <--> D
  I <--> E
  J[Eval:验收、失败分类、回归] --> D
  J --> E

其中最容易被低估的有五条:

  1. 渠道到会话。 收到消息不是 session.prompt(text) 就结束了。还要确定发送者、租户、会话 key、并发策略和结果回投位置。
  2. 任务到调度。 cron 触发后需要去重、超时、重试、失败通知和停止开关,否则“每天总结”很快变成每天制造一条无人处理的失败日志。
  3. 记忆到权限。 一条长期记忆应属于用户、项目还是共享空间?能否被低权限渠道读到?何时撤回?这些都不能交给向量检索的相似度独自决定。
  4. 工具到执行边界。 模型提出一个 tool call,只是意图;真正的权限检查应在网络、文件、进程和凭据即将产生副作用的位置再次发生。
  5. 结果到评测。 Loop Engineering 不是“失败了再塞一句反思 prompt”。至少要能记录目标、成功信号、失败类别与重试预算,才知道循环是在变好还是只是在多花 token。

所以 Pi 很适合承担图中的 AgentSession + Agent loop:核心循环小、生命周期清楚、工具和 UI 可替换。Graph Engineering 也不是做不到,只是图中的 Planner、Coder、Reviewer、Judge 不能只靠一次 Agent.prompt() 自然长出来;你还要在 Control Plane 定义节点状态、边条件、并发、失败回收和最终验收。Pi 可以是图节点的执行器,却不会自动成为图调度器。

#怎样选择:不要先问“能不能”,先问哪一层该由谁拥有

如果目标是可改造的 Coding Agent、特殊工具链,或一套需要自己掌握调度语义的 local-first runtime,Pi 是很好的起点。你可以把最小闭环跑通,再逐层增加有明确需求的渠道、Memory、审批和评测。

如果目标是今天就要通过聊天渠道处理持续任务,优先评估 Hermes、OpenClaw 或 nanobot 是否已经覆盖你的部署、身份与安全要求。它们省下的不是几段 plugin 代码,而是网关、生命周期和默认操作路径;当然,也会把更多运行时行为带进你的系统。

最需要避免的路线是:先把 Pi 接到所有渠道和高权限工具,再补权限、持久化和观测。那会得到一个很会做事、但没人说得清它什么时候醒来、拿谁的权限、又留下了什么的 Agent。

#总结:Pi 缺的不是能力清单,而是 OS 的责任边界

Pi 已经提供了 Agent 的骨架:模型调用、工具循环、会话、压缩、扩展与交互界面。源码中的 AgentAgentSession 也解释了它为什么特别适合做 Loop Engineering 的执行底座:每一轮的状态、生命周期和工具调用都有明确入口。

但 Hermes、OpenClaw、nanobot 所在的层次不只是“更多 tools”。它们把渠道、Gateway、定时任务、长时记忆、身份、安全和持续运维组合成一个长期服务。Pi 可以向上生长,前提是你愿意明确拥有这些控制面的设计与维护。

下一篇会继续沿着 Pi 的源码看 Extension:一个扩展究竟能在什么时机改变上下文、拦截工具和保存状态;以及为什么这既是 Pi 最强的可塑性,也是最需要先设计安全边界的地方。

#参考资料

Share this post

Mermaid 图表
100%