【AI Coding】5-Pi Agent Harness:一个极简终端编码Harness的解构

【AI Coding】5-Pi Agent Harness:一个极简终端编码Harness的解构

  • [Pi Agent Harness:一个极简终端编码 Harness 的解构](#Pi Agent Harness:一个极简终端编码 Harness 的解构)
    • [一、先问一个问题:为什么编码 Agent 需要一个"框架"?](#一、先问一个问题:为什么编码 Agent 需要一个"框架"?)
    • [二、Pi 是什么:一个"极简终端编码 Harness"的自我定义](#二、Pi 是什么:一个"极简终端编码 Harness"的自我定义)
      • [2.1 官方定位一句话](#2.1 官方定位一句话)
      • [2.2 项目结构与规模](#2.2 项目结构与规模)
      • [2.3 运行形态:不止"终端交互"](#2.3 运行形态:不止"终端交互")
    • [三、小内核如何跑起来:四个默认工具 + 上下文管理](#三、小内核如何跑起来:四个默认工具 + 上下文管理)
      • [3.1 极简的默认工具集](#3.1 极简的默认工具集)
      • [3.2 上下文来源:AGENTS.md 分层加载](#3.2 上下文来源:AGENTS.md 分层加载)
      • [3.3 会话管理:JSONL + 树状分支](#3.3 会话管理:JSONL + 树状分支)
      • [3.4 压缩:上下文满了以后发生什么](#3.4 压缩:上下文满了以后发生什么)
    • 四、扩展层:不改内核,怎么长出我们想要的能力
      • [4.1 四类可定制资源](#4.1 四类可定制资源)
      • [4.2 Extension:一个真实例子](#4.2 Extension:一个真实例子)
      • [4.3 Skill:直接吃 Claude Code / Codex 生态](#4.3 Skill:直接吃 Claude Code / Codex 生态)
    • [五、反内置哲学:不做权限弹窗、不做 MCP、不做子 Agent](#五、反内置哲学:不做权限弹窗、不做 MCP、不做子 Agent)
      • [5.1 六个"没有"](#5.1 六个"没有")
      • [5.2 为什么"不做"反而是设计](#5.2 为什么"不做"反而是设计)
    • [六、生态图景:Harness 正在变成一个"可换件"](#六、生态图景:Harness 正在变成一个"可换件")
      • [6.1 Pi 生态里的三个样本](#6.1 Pi 生态里的三个样本)
      • [6.2 Harness 概念的扩散:DeepSeek Harness](#6.2 Harness 概念的扩散:DeepSeek Harness)
    • [七、动手:从零跑起 Pi,并在十分钟内验证 Harness 的价值](#七、动手:从零跑起 Pi,并在十分钟内验证 Harness 的价值)
      • [Step 1 安装](#Step 1 安装)
      • [Step 2 验证 Context 文件加载](#Step 2 验证 Context 文件加载)
      • [Step 3 导入已有 Skill](#Step 3 导入已有 Skill)
      • [Step 4 加一个扩展做路径保护](#Step 4 加一个扩展做路径保护)
    • [八、结论:我们该怎样理解 Harness?](#八、结论:我们该怎样理解 Harness?)
    • 参考资料

Pi Agent Harness:一个极简终端编码 Harness 的解构

前四篇 我们依次解决了四个问题:上下文演化、Skill 体系设计、Skill 精准触发、多 Agent 协同与成本边界。

本篇切入一个更高频的问题:当 Claude Code、Codex、Cursor、OpenCode、Pi 这些终端编码工具摆在一起,我们到底在选择什么?答案是 Harness ------模型之外的整套运行框架。

本文以 2025 年 8 月诞生、至今仍保持"极简内核"定位的 Pi Agent Harness(作者 Mario Zechner / badlogic,MIT 协议)为主线,拆解 Harness 的职责边界、Pi 的设计取舍,以及"模型换着用、工具链不变"的工程化意义。


一、先问一个问题:为什么编码 Agent 需要一个"框架"?

我们回到第一性原理。单把模型接上终端,会发生什么?

  • 模型第一次调用时看到的是一个裸文件系统。它不知道项目该往哪里写代码,不知道测试怎么跑,不知道哪些目录碰不得。
  • 一个"知识渊博但双手空空"的模型,和一个"能读文件、能改文件、能执行命令"的模型,是两种完全不同的产品。差距不在模型,而在模型和操作系统之间的那层胶水
  • 这层胶水要回答的具体问题包括:模型能不能调用工具、用哪几个工具、工具结果如何进入上下文、对话历史存在哪、上下文满了怎么办、读写操作要不要经过批准。

这层胶水,业界现在称之为 Harness(运行框架/挽具)。它的核心矛盾在于方向完全相反的两个诉求:

诉求 表现
开箱即用 装完就能干活,默认能力覆盖多数任务
可塑性 换模型、加工具、改交互,不修改内核源码也能做到

Claude Code、Codex、Cursor 的处理方式,是在各自编辑器/CLI 生态里把 Harness 做厚;而 Pi 选择了另一条路:把内核压到最小,把扩展做成一等公民

我们之前提到过"从 rules 到 skills、再到 harness"的演化(见系列第 0 篇)。Pi 恰好是这个演化链条里最典型的样本:它不推销任何"全家桶",而是提供一个可以拼装的最小骨架。


二、Pi 是什么:一个"极简终端编码 Harness"的自我定义

2.1 官方定位一句话

Pi 的官方仓库对自己的定义非常明确(pi-mono README):

Pi is a minimal terminal coding harness. adapt pi to our workflows, not the other way around, without having to fork and modify pi internals.

把它翻成工程语言就是三件事:

  1. Harness,不是模型,也不是 IDE。它不训练模型、不替我们决定编辑器,只负责"让一个通用模型在一个真实项目里安全地干活"。
  2. 适配工作流的是使用者,不是反过来 。Pi 不搞"功能全家桶",默认只给四个工具:readwriteeditbash,加上可选的 grepfindlsQuickstart 文档)。
  3. 不改内核也能扩展。扩展方式是 TypeScript Extension、Skill、Prompt Template、Theme 四类资源,可以打包成 Pi Package 用 npm 或 git 分发。

2.2 项目结构与规模

Pi 是一个 monorepo,包结构本身就是"Harness 该拆成几块"的标准答案(pi-mono README):

职责
@earendil-works/pi-ai 统一多提供商 LLM API(OpenAI / Anthropic / Google / Bedrock / 国产各家等 20+ 家)
@earendil-works/pi-agent-core Agent 运行时:工具调用 + 状态管理
@earendil-works/pi-coding-agent 交互式编码 Agent CLI(终端 TUI)
@earendil-works/pi-tui 终端 UI 库(差分渲染)
@earendil-works/pi-telemetry 厂商中立遥测契约

这五个包回答的问题分别是:怎么连模型(pi-ai)、怎么跑 Agent 循环(pi-agent-core)、怎么和人类交互(pi-coding-agent + pi-tui)、怎么观察它(pi-telemetry)。Harness 的职责可以被拆成这四层,这是我们在其他工具里看不到的清晰分层。

2.3 运行形态:不止"终端交互"

Pi 有四种运行形态,这决定了它能被嵌入任何地方(coding-agent README):

形态 命令/方式 适用
交互模式 pi 日常在项目里对话干活
打印/JSON 模式 pi -p "..." / --mode json 一次性提问、脚本化调用、CI 里做检查
RPC 模式 --mode rpc 通过 stdin/stdout JSONL 协议被 IDE、其他程序嵌入
SDK 嵌入 AgentSession Node/TS 应用里直接内嵌 Agent 会话

RPC 模式是 Pi 作为 Harness 最有说服力的一点:它不要求使用者"用它的界面",而是把 Agent 会话当作一个可以编程控制的子进程对象暴露出来(RPC 文档)。对做企业级 Agent 平台的团队来说,这意味着 Pi 可以成为底座,而不是一个孤立玩具。


三、小内核如何跑起来:四个默认工具 + 上下文管理

3.1 极简的默认工具集

Pi 默认给模型的四个工具,恰好覆盖编码 Agent 的最小闭环(Quickstart 文档):

工具 能力 备注
read 读文件 只读,安全
write 创建/覆盖文件 写操作
edit 打补丁改文件 写操作
bash 执行 shell 命令 最高风险

反直觉点:工具越少,模型越不容易选错。我们在系列第 3 篇讲过"工具超过 15 个模型会陷入选择困难",Pi 把默认集压到 4 个,等于直接把这类问题挡在设计层面。需要更多能力时,用 Skill / Extension 按需加,而不是一开始全塞给模型。

3.2 上下文来源:AGENTS.md 分层加载

Pi 启动时会按层加载上下文文件(Quickstart 文档):

复制代码
~/.pi/agent/AGENTS.md            # 全局指令
父目录逐级向上的 AGENTS.md / CLAUDE.md
当前目录的 AGENTS.md / CLAUDE.md
AGENTS.override.md               # 存在时替换同目录 AGENTS.md/CLAUDE.md

这套设计解决了两个实际问题:一是项目约定(跑什么检查、不能动哪个目录)可以直接放进仓库随代码走;二是它兼容已有的 Claude Code 生态文件(CLAUDE.md),迁移成本低。

3.3 会话管理:JSONL + 树状分支

Pi 的会话以 JSONL 文件存在 ~/.pi/agent/sessions/,按工作目录组织(Sessions 文档)。每个会话是一棵树,不是一条线:

能力 命令 场景
继续最近会话 pi -c 早上接着昨晚的活
浏览历史会话 pi -r 找回上周做过的任务
从历史点分支 /fork/tree "换个思路重来",保留原分支
克隆当前分支 /clone 在副本上尝试方案,不动主线

树状存取是 Harness 层解决"上下文探路成本"的关键:试错不再是不可逆的,想回到某个决策点,从那个节点再分一条路即可。

3.4 压缩:上下文满了以后发生什么

Pi 的自动压缩机制是"可被审计"的(Compaction 文档),触发条件是一个明确的公式:

复制代码
contextTokens > contextWindow - reserveTokens

默认 reserveTokens 为 16384(给模型留响应空间);触发后从最新消息往回找,保留最近约 20k token(keepRecentTokens 默认值),更老的部分交给模型生成结构化摘要,存成一条 CompactionEntry(带 firstKeptEntryId 锚点),后续请求用"摘要 + 保留消息"重建上下文。

这个过程和我们的老熟人"上下文衰减"(系列第 0 篇)正面相遇:压缩不是简单截断,而是把老信息转成摘要、把文件操作追踪累积保留,让模型"忘了细节但记得结论"。


四、扩展层:不改内核,怎么长出我们想要的能力

4.1 四类可定制资源

Pi 把"改行为"的入口收敛成四类(coding-agent README):

资源 是什么 什么时候用
Extension TypeScript 模块,可注册工具/命令/事件钩子 要动运行逻辑:权限闸门、git 检查点、路径保护
Skill 目录 + SKILL.md,按需加载的能力包 复用 Claude Code / Codex 生态的 Skill
Prompt Template 从斜杠命令展开的复用提示词 把常用提问固化成 /review/deploy
Theme 终端主题 界面观感

4.2 Extension:一个真实例子

官方文档给的权限闸门例子,直接演示了 Extension 如何拦截危险命令(Extensions 文档):

typescript 复制代码
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";

export default function (pi: ExtensionAPI) {
  // 监听工具调用事件,拦截 rm -rf / sudo
  pi.on("tool_call", async (event, ctx) => {
    if (event.toolName === "bash" && event.input.command?.includes("rm -rf")) {
      const ok = await ctx.ui.confirm("危险操作", "允许 rm -rf 吗");
      if (!ok) return { block: true, reason: "Blocked by user" };
    }
  });

  // 注册一个自定义工具
  pi.registerTool({
    name: "greet",
    description: "向指定姓名打招呼",
    parameters: Type.Object({ name: Type.String() }),
    async execute(toolCallId, params) {
      return { content: [{ type: "text", text: `Hello, ${params.name}` }] };
    },
  });
}

这段代码的三层含义:

  1. 能力即钩子tool_call 事件是所有安全策略的接入点,不 fork 源码就能加权限控制。
  2. 工具即函数registerTool 让任何 TypeScript 能力(内部服务、DB、CI)变成模型可调用的工具,签名就是参数 Schema。
  3. 信任边界自建:Pi 默认不给任何权限弹窗,但允许使用者用 Extension 自建审批流------要不要批准、怎么批准,由项目自己定。

4.3 Skill:直接吃 Claude Code / Codex 生态

Pi 的 Skill 机制遵循 Agent Skills 规范(agentskills.io),并且可以在设置里直接导入其他 Harness 的 Skill 目录(Skills 文档):

json 复制代码
{
  "skills": ["~/.claude/skills", "~/.codex/skills"]
}

一个 Skill 的标准结构是:

复制代码
my-skill/
├── SKILL.md       # frontmatter(name+description) + 使用说明
├── scripts/       # 辅助脚本
└── references/    # 按需加载的详细文档

加载机制是渐进式披露:启动时只把每个 Skill 的 name/description 放进系统提示,任务匹配时才让模型用 read 读完整 SKILL.md。这正是我们在系列第 2 篇讲的机制,Pi 直接采用同款协议。

这就是 Harness 生态的价值:Skill 不再绑定某个工具,~/.claude/skills 里的资产在 Pi 下直接复用。对个人来说,等于一次沉淀、到处可用。


五、反内置哲学:不做权限弹窗、不做 MCP、不做子 Agent

5.1 六个"没有"

Pi 的 Philosophy 部分列了一串"我们刻意不做"(coding-agent README):

不做 替代方案
MCP 用 CLI 工具 + Skill,或者用 Extension 自己加 MCP 支持
子 Agent 用 tmux 起多个 Pi 实例,或用 Extension 自建
权限弹窗 容器化,或用 Extension 自建确认流
Plan 模式 把计划写进文件,或用 Extension 实现
内置 Todo TODO.md 文件
后台 bash 用 tmux,全程可见可交互

5.2 为什么"不做"反而是设计

这六个"没有"不是因为偷懒,而是三个明确判断:

  1. 内核最小化才能活下来。每内置一个功能,就多一层"使用者以为的默认"和"实际行为"的偏差,也就多一个被模型误用的面。
  2. 权限是组织问题,不是通用问题 。个人项目、开源仓库、企业合规的审批粒度完全不同,统一弹窗要么烦人要么漏风。Pi 的默认是"以启动进程的用户权限运行",需要边界时用容器(Gondolin / Docker / OpenShell 三套方案,Containerization 文档)做隔离。
  3. 工具间消息的不信任原则。我们在系列第 3 篇引过 OWASP 数据:73% 的部署容易受 Agent 通信通道注入攻击。Pi 把"Agent 间消息"直接从默认能力里拿掉,等于默认避开了整类攻击面。

需要指出的是,这套哲学有代价:新手第一次上手会觉得"这也缺那也缺"。Pi 的补偿是把扩展成本压到最低------官方文档里大量出现"问 Pi 让它再写一个 Extension",即用模型本身来补齐能力。


六、生态图景:Harness 正在变成一个"可换件"

6.1 Pi 生态里的三个样本

Pi 的仓库图谱展示了 Harness 的三种演化方向(均在 GitHub 上可查):

项目 关系 方向
oh-my-pi (omp) Pi 的 fork 分支 把内核做厚:60+ 提供商、31 个内置工具、LSP/DAP、浏览器、子 Agent
pie Pi 的 Rust 移植 把内核做硬:原生性能 + 触发器/定时任务/有状态循环
omnigent 元 Harness(meta-harness) 同时编排 Claude Code、Codex、Cursor、Pi,按任务切换 Harness
PI-Desktop 基于 Pi 的桌面封装 把 Harness 包进本地优先的桌面应用,插件化扩展

这组项目说明一个问题:Harness 开始像 IDE 一样,成为可以"换件"的中间层。omnigent 的定位尤其直接------它把 Pi 与 Claude Code、Codex、Cursor 并列对待,用同一套策略层做沙箱、预算、审批。模型可以变,Harness 也可以变,但治理层不变,这正是企业最想要的组合方式。

6.2 Harness 概念的扩散:DeepSeek Harness

2026 年 8 月 13 日的技术动态日报里,我们记录过一个信号:DeepSeek 的更新日志提到"DeepSeek Harness 极简模式(即将发布)",当时的判断是"模型 + Harness 组合可能复刻 DeepSeek 时刻"(2026年8月13日_技术动态日报)。

把这一条和 Pi 放在一起看,就能发现行业的共识正在形成:模型厂商不再只发布 API,开始发布自己附带的运行框架。区别在于,DeepSeek Harness 是模型厂商想垂直整合到底,Pi 是开源的通用底座------前者绑定自家模型,后者对模型中立。对开发者来说,中立的 Harness 意味着不会被单一厂商锁死,模型的定价和能力的竞争红利都能享受。


七、动手:从零跑起 Pi,并在十分钟内验证 Harness 的价值

我们不追求全面,只验证三件事:能装、能连模型、能扩展。

Step 1 安装

bash 复制代码
npm install -g --ignore-scripts @earendil-works/pi-coding-agent

--ignore-scripts 关闭依赖生命周期脚本,降低供应链风险------这也呼应了官方把 npm 依赖当成"需要审查的代码"的工程纪律。macOS/Linux 也可以用 curl -fsSL https://pi.dev/install.sh | sh

Step 2 验证 Context 文件加载

在项目根目录放一个 AGENTS.md

markdown 复制代码
# 项目约定
- 改完代码必须运行 npm run check
- 不要修改生产迁移脚本
- 回复保持简洁

启动 pi,问它"这个项目怎么跑测试",如果它引用了 npm run check,说明上下文注入链路正常工作。

Step 3 导入已有 Skill

json 复制代码
// .pi/settings.json
{
  "skills": ["~/.claude/skills", "~/.codex/skills"],
  "enableSkillCommands": true
}

重启后 /skill: 命令能看到已存在的 Skill,验证跨 Harness 复用。

Step 4 加一个扩展做路径保护

~/.pi/agent/extensions/ 放一个 .ts 文件,拦截对 .env 的写入:

typescript 复制代码
pi.on("tool_call", async (event, ctx) => {
  if (event.toolName === "edit" || event.toolName === "write") {
    if (String(event.input.path ?? "").includes(".env")) {
      return { block: true, reason: "Protect .env from edits" };
    }
  }
});

这一步验证的是"能力即代码":安全策略不是配置项,而是 TypeScript 模块,进 git、可测试、可协作。

验收标准不是"模型答得多好",而是这套骨架能不能被团队改造成自己的形状。十分钟内做到"模型任意换、Safety 自定义、Skill 复用存量资产",Pi 作为 Harness 的价值就成立了。


八、结论:我们该怎样理解 Harness?

把本篇的线索收拢成四个结论:

  1. Harness 是 AI Coding 的"工程题",不是"模型题"。同一批模型换一套骨架,生产率和风险完全不同。评估编码工具,先看它怎么管工具、上下文、权限、会话,再看模型列表有多长。
  2. Pi 提供了一种可复用的极简范本。五个包的分层(AI 接入 / Agent 循环 / 交互 / TUI / 遥测)、四个默认工具、树状 JSONL 会话、可审计压缩、TypeScript 扩展,任何团队自建 Agent 底座时都值得逐条对照。
  3. 生态正在把 Harness 变成可换件。omnigent 把 Pi 和 Claude Code、Codex 并列治理,DeepSeek 在发布自家 Harness------方向相反但都说明 Harness 正在成为基础设施层。
  4. 适用边界 :Pi 适合愿意自己拼装、已有 Claude Code/Codex Skill 资产、或需要把 Agent 嵌入自有系统的团队;不适合想要"开箱即用全家桶"、依赖子 Agent/Plan 模式/权限弹窗开箱即用的场景。选择 Harness 的标准不是功能数量,而是它能不能按使用者的形状生长

参考资料

相关推荐
桂云网络OSG1 小时前
桂花AI引擎,广西本土自研的企业级 Agent 编排引擎发布:不聊参数,聊工程落地
人工智能
WX _ jishuwu19901 小时前
esmfold gpu模式 批量预测蛋白三级结构实况记录 - 供参考
人工智能·ubuntu·三代测序·亚细胞定位,·deeploc·protcompv9
Nablai1 小时前
从供应链与合规看:AI 玩具为何需要多芯片路线
人工智能
王清欢Randy1 小时前
AI 时代的 “黑客与画家”
人工智能·程序人生·ai编程·程序员技能
鲜于言悠9051 小时前
告别AI界面翻车!深度拆解MCP Apps与A2UI两套生成式UI协议
人工智能
大模型码小白1 小时前
数据可视化:AI 生成 HTML5 动态交互式数据图表
前端·数据库·人工智能·深度学习·机器学习·信息可视化·html5
明月_清风1 小时前
本体论和本体建模的具体应用场景究竟是什么?
人工智能·后端
星核0penstarry2 小时前
ToolGrad:把数据生成倒过来,工具调用样本通过率提到 99.8%
人工智能·测试工具·llm·函数调用·数据合成·文本调用
南京兴帝文化传媒有限公司2 小时前
基于地图平台的本地商户信息优化:药店夜间服务标注与客户转化实操
前端·javascript·数据库·人工智能·geo 优化·geo优化避坑·ai搜索获客