---
title: 'Pi 源码解读：Agent Harness 和 Agent OS，到底差了什么？'
description: '从 Pi 的 Agent、AgentSession 与 Extension API 出发，解释它为何是适合改造的 Agent Harness，以及它距离 Hermes、OpenClaw、nanobot 这类个人 Agent OS 还缺哪些运行时层。'
pubDate: 2026-08-06
slug: pi-harness-vs-agent-os
tags: [harness, agent, 源码解读]
lang: zh-CN
draft: false
featured: false
showCTA: true
showComments: true
series:
  id: pi-source-walkthrough
  order: 1
---

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

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

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

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

## 先说结论

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

> **数据快照**
>
> - 最后核验：2026-08-06
> - Pi 源码快照：[`bde81c8`](https://github.com/earendil-works/pi/tree/bde81c84405514c8b0f57c34405c152fb129c0ce)（`main` 分支当日提交）
> - 主要对象：Pi Agent Harness、Hermes Agent、OpenClaw、nanobot
> - 讨论边界：本文比较它们的运行时职责，不比较模型能力、社区规模或某次任务的成功率
> - 证据限制：Pi 部分以固定源码快照为准；其余三个项目的“开箱能力”来自当日官方 README / 文档，不能推出它们在每种部署配置下都有相同表现

## 先把“Agent”拆成两层

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

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

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

Pi 的项目 README 明确把自己拆为 `pi-agent-core`、`pi-ai`、`pi-coding-agent` 和 TUI：运行循环、模型适配、交互式编码界面各自独立。[Pi README](https://github.com/earendil-works/pi/tree/bde81c84405514c8b0f57c34405c152fb129c0ce) 对这个边界说得相当直白。相对地，[Hermes](https://github.com/NousResearch/hermes-agent)、[OpenClaw](https://github.com/openclaw/openclaw) 和 [nanobot](https://github.com/HKUDS/nanobot) 的公开入口都把聊天渠道、持续服务或自动化放进产品定义。

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

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

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

```ts
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 的内部问题。源码还把 `beforeToolCall`、`afterToolCall`、`shouldStopAfterTurn` 和 `prepareNextTurn` 放进 loop 配置中。[对应的配置装配代码](https://github.com/earendil-works/pi/blob/bde81c84405514c8b0f57c34405c152fb129c0ce/packages/agent/src/agent.ts#L416-L454) 证明了它为外部策略留出了钩子；它**不能**证明 Pi 已经替你定义了“什么任务应该每天九点运行”或“陌生 Telegram 用户能否创建会话”。

**图 1：Pi `Agent` 的单次执行闭环；依据 2026-08-06 的源码快照**

```mermaid
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 执行。[文件头的职责说明](https://github.com/earendil-works/pi/blob/bde81c84405514c8b0f57c34405c152fb129c0ce/packages/coding-agent/src/core/agent-session.ts#L1-L13) 与 [它对 `Agent`、session manager、extension runner 的依赖](https://github.com/earendil-works/pi/blob/bde81c84405514c8b0f57c34405c152fb129c0ce/packages/coding-agent/src/core/agent-session.ts#L16-L109) 共同说明了这层的任务。

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

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

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

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

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

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

```ts
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。[权限与容器化说明](https://github.com/earendil-works/pi/blob/bde81c84405514c8b0f57c34405c152fb129c0ce/README.md#L204-L211) 不是缺失的文档，而是项目有意保留给宿主的责任。

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

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

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

```mermaid
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 的骨架：模型调用、工具循环、会话、压缩、扩展与交互界面。源码中的 `Agent` 和 `AgentSession` 也解释了它为什么特别适合做 Loop Engineering 的执行底座：每一轮的状态、生命周期和工具调用都有明确入口。

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

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

## 参考资料

- [Pi 仓库，源码快照 `bde81c8`](https://github.com/earendil-works/pi/tree/bde81c84405514c8b0f57c34405c152fb129c0ce)
- [Pi：`Agent` 的运行循环入口](https://github.com/earendil-works/pi/blob/bde81c84405514c8b0f57c34405c152fb129c0ce/packages/agent/src/agent.ts#L324-L455)
- [Pi：`AgentSession` 的共享运行时职责](https://github.com/earendil-works/pi/blob/bde81c84405514c8b0f57c34405c152fb129c0ce/packages/coding-agent/src/core/agent-session.ts#L1-L109)
- [Pi Extension 文档](https://pi.dev/docs/latest/extensions)
- [Hermes Agent 官方仓库](https://github.com/NousResearch/hermes-agent)
- [OpenClaw 官方仓库](https://github.com/openclaw/openclaw)
- [nanobot 官方仓库](https://github.com/HKUDS/nanobot)
