
从 Pi 学习设计自己的 Agent Harness:一条可验证的垂直生产线
一个内容团队把研究、写稿、审核、配图和发布串成自动流程。开始几天很顺:模型能写文件,脚本能跑, 图片能上传。后来编辑改了两段正文,旧审核结论仍显示通过;上传图片只改了 Markdown 链接,却又触发 一次全文和逐图复审;换成便宜模型后,格式看起来正确,引用、论证和视觉闭环却同时退化。
这三类问题不是模型"聪不聪明"的同一个问题。第一类是状态没有绑定产物,第二类是变更失效范围过粗, 第三类是执行器路由缺少回归证据。如果系统只有 Prompt、模型 API 和一串脚本,它很难分辨它们。
自研 Agent Harness 的正确起点,不是先做一个能处理所有任务的全能 Agent,而是先建立一条可验证的 垂直生产线:系统知道输入是什么、当前处于哪个阶段、产生了什么 Artifact、哪些检查已经通过、哪种 变化会让哪些结论失效,以及最后由谁批准。
本文以内容生产为例,但这套方法同样适用于代码迁移、数据清洗、评测流水线和内部知识维护。最终要带走 的不是一张宏大的架构图,而是一条可以从明天开始实现的最小闭环。
一、先把"做一个 Agent"改写成可验收的工序
"做一个能自动研究、写作、审核、配图和发布的 Agent"几乎没有工程信息。它没有说明来源是否齐全、 哪些动作能自动执行、什么叫完成、失败从哪里恢复、模型能否覆盖人工内容,以及一条坏引用是否应该让 整条流水线重跑。
把目标收窄后,第一条工序可以只有这样:
text
输入:经过确认的一手资料、读者问题和仓库规则
输出:一篇来源可追溯、结构完整、通过母稿门禁的候选稿
第一版暂时不做自动配图、自动发布、多 Agent 并行和自主修改流程。它甚至可以只有一个模型。关键是, 这条工序每次都能回答四个问题:
- 用了哪一版输入和规则?
- 产生了哪个候选产物?
- 为什么通过、失败或升级?
- 下次能否用同一组用例复现判断?
如果这四个问题答不出来,增加更多模型和工具只会增加不可观察状态。
二、Pi 值得迁移的不是功能列表,而是边界纪律

Pi v0.82.1 把模型接口、Agent Loop、Coding Agent 应用和终端交互分成不同层。Coding Agent 又把 Session、Resource Loading、Extension 与程序化 SDK 暴露为组合原语。Session 保存的是带父子关系的 运行记录,不只是最后一次发给模型的 messages[];Extension 可以加入 Tool 和事件,但不要求把所有 工作流策略写进核心。
这些第一方事实不能直接推出本文的 Harness 架构。Task Contract、Run Store 和 Quality Gate 是作者 方案,不是 Pi 官方协议。Pi 真正提供的启发是三条分离原则:
text
稳定机制 与 可替换策略分离
运行状态 与 模型上下文分离
候选产物 与 已批准产物分离
例如,模型路由属于策略。业务 Stage 不应该写死"文章就调用某个品牌模型",而应只声明能力、风险、 数据边界和预算,再由路由策略选择执行器。审核结果属于状态。它不能只写一句 passed,而要绑定产物 SHA、审核者、执行轮次和证据。发布稿属于已批准产物。生成模型默认只能写候选目录,通过 Gate 后才可 提升,不能直接覆盖正式版本。
这三条分离把 Harness 从"会调用模型的脚本"变成了可以治理的运行系统。
三、最小闭环只需要五个状态对象


一个垂直 Harness 不必一开始实现十几个服务。先把五个对象设计清楚,已经足以运行第一条生产线。
1. Task Contract:任务到底承诺交付什么
自然语言说明可以保留,但系统需要一份结构化合同:
yaml
task_id: article-pi16
objective: 产出一篇可审核的 Agent Harness 技术母稿
input_revision: research-pack@sha256:...
audience: 有后端或 AI 应用经验的工程师
deliverables:
- path: candidates/pi16.md
kind: master_draft
constraints:
source_policy: primary_preferred
forbidden_actions: [invent_benchmark, overwrite_approved]
acceptance:
- id: source_traceability
severity: blocker
- id: single_reader_problem
severity: blocker
Task Contract 不是给 Prompt 换一个名字。Prompt 帮模型完成一次调用;合同让运行时在多次调用、失败恢复 和执行器交接中保持同一个目标。input_revision 尤其重要:如果来源或规则已经变化,旧结果不能因为 "读起来还不错"就继续继承批准。
2. Run Record:发生过什么
Run Record 保存 Stage、Attempt、执行器、上下文版本、工具事件、Token、失败原因与人工动作。它不是聊天 记录的副本。聊天回答"模型说了什么",Run Record 回答"系统做了什么、当前还能怎么继续"。
json
{
"run_id": "run-pi16-a2",
"task_id": "article-pi16",
"stage": "master_review",
"status": "waiting_owner",
"attempt": 2,
"artifact": "candidates/pi16.md",
"artifact_sha256": "...",
"previous_attempt": "run-pi16-a1",
"failure_route": null
}
同一提纲可以产生两个候选分支。最终批准其中一个,不意味着另一个应该消失;失败分支记录了路由效果、 返工原因和以后回归所需的真实样本。
3. Artifact Manifest:交付的不是最后一条回复
真正可交接的是文件、清单、图片、补丁或报告。每个 Artifact 至少要有稳定路径、类型、状态、生产者、 来源 Run、SHA 和上一版本。只有 Manifest 能回答"当前审核对应哪份文件""图片顺序是否变化""回填 链接后正文语义是否未变"。
候选和批准版本必须分开:
text
candidates/run-pi16-a2/draft.md
→ Gate 通过
artifacts/master-drafts/pi16.md
这个权限边界比要求模型"请不要覆盖正式稿"可靠得多。
4. Quality Gate:完成必须有出口条件
模型说"已完成"只能结束一次调用,不能结束一个 Stage。每个 Stage 都要有出口条件:来源阶段检查一手 证据与冲突;母稿阶段检查事实、单一主线、章节职责和读者产物;平台阶段分别检查 CSDN 与小红书; 视觉阶段检查最终 PNG、证据可读性和顺序。
Gate 也不能只有 pass/fail。失败至少要给出唯一主要路线,例如:补证据、删重复、拆分、重构或停止 平台版本。Orchestrator 才能确定是重试同一步、回退上游,还是等待人工判断。
5. Checkpoint:恢复的是执行状态,不只是文件
Git Commit 只能恢复文件。真正的 Checkpoint 还要固定 Task Contract、输入版本、路由策略、Stage、Gate、 Artifact Manifest 和批准记录。否则文件退回去了,模型仍可能使用新规则或错误的旧审核状态继续执行。
text
加载 checkpoint
→ 恢复任务、上下文和策略版本
→ 创建新的 Attempt
→ 只重跑失效阶段
因此回滚不是删除失败历史,而是从一个已知节点产生新分支。
四、六步生产线:先把判断与搬运分开

有了五个状态对象,最小流程可以压缩为六步:
text
1. Intake:确认输入、来源和任务路线
2. Produce:只生成候选 Artifact
3. Deterministic Preflight:检查格式、路径、副本、Schema 和 SHA
4. Independent Review:判断事实、论证、读者价值和视觉语义
5. Owner Gate:决定是否进入外部写入或正式发布
6. Delivery:上传、回填、迁移并生成可逆证明
这里最重要的不是步骤数量,而是判断与搬运分离。确定性脚本适合回答"两个副本是否一致""Manifest 是否覆盖全部图片""远端对象的大小和 SHA 是否匹配"。它不应该回答"文章是否有价值""证据图是否 误导""小红书是否形成认知闭环"。后者需要独立编辑判断。
反过来,已经作出的编辑结论也不应让模型手写复制到四份 Gate、两个索引和一张 owner 卡。审核者先把 结论写入单一结果文件,再由脚本机械展开,可以降低重复 Token,也减少身份、SHA 和状态写错的机会。
五、按变更面失效,而不是任何变化都重审全部内容

生产 Harness 很容易在"严谨"名义下变得极重:Markdown 只替换九个本地图片链接为 R2 URL,也重新读 全文、重看全部图片;单页字号修复后,又重复审核其他十五张未变化图片。成本上升,却没有增加判断质量。
更合理的做法是先生成审核快照,再对变化分类:
| 变化 | 应失效的结论 |
|---|---|
| 正文语义变化 | 对应平台的内容、事实与最终包审核 |
| 来源契约或证据映射变化 | 相关事实链、证据页与最终包审核 |
| 共享 CSS 或渲染器变化 | 受影响平台全部图片视觉审核 |
| 单页 PNG 且来源未变 | 该页、相关论点、总览顺序与 Manifest |
| 仅审核结果机械展开 | 不产生新的内容判断 |
| 仅 R2 URL 回填且可逆证明成立 | 只验证远端对象、链接、清单与语义 SHA |
继承旧结论的前提不是"我记得没改",而是旧快照、新 SHA、差异分类和可逆证明同时存在。证明失败就 停止并升级完整审核。这样做不是降低门槛,而是把昂贵判断集中在真正变化的地方。
六、模型路由必须服从回归,不服从价格表
低成本模型很适合候选摘要、字段规范化、分类和确定性模板填充,但"便宜"不能自动推导为"可以接管 某阶段"。内容生产尤其容易出现表面合规:文件存在、字数合适、章节齐全,事实归因、引用映射、删减 保真和视觉闭环却失败。
因此路由请求应该描述任务,而不是先指定品牌:
yaml
operation: platform_adaptation
risk: high
required_capabilities: [source_fidelity, narrative_reframe]
owner_scope: none
fallback: editor
每个候选执行器在同一组冻结案例上测试,至少记录:
- 关键失败数与通过率;
- unsupported claim 数量;
- Schema 与格式合规率;
- 平均重试和升级次数;
- 人工修改量;
- Token、延迟与调用成本。
人工修改量往往比单价更重要。一个模型调用便宜十倍,却让编辑多花四十分钟,真实总成本可能更高。 如果某类任务连续失败,正确动作不是继续增加 Prompt,而是让路由器 abstain 或升级强模型,并保留 失败样本扩充回归集。
这也解释了为什么模型降级要从一个命名明确的工序做 Shadow Test,而不是一次把研究、写稿、审核和 视觉全部交出去。Harness 负责让实验可比较,不负责替不合格模型制造通过结论。
七、从第一天建立五类回归案例

回归集不需要一开始就很大,但必须覆盖最容易被"看起来不错"掩盖的问题:
- 来源边界:不得编造来源中没有的版本、数字、日期和作者动机。
- 改写保真:优化表达时,不改变数字、专名、结论和不确定性。
- 系列边界:不机械重复上一篇,也不提前消耗下一篇的核心产物。
- 产物契约:Frontmatter、JSON、Manifest、文件路径和状态迁移有效。
- 冲突升级:两个一手来源不一致时显式报告,不生成看似合理的统一答案。
Batch 06 的 regression-cases.yaml 已给出这五类静态样例,但它们仍只是参考 Fixture。真正上线前要换成 自己的失败案例,并把每次事故转成新用例。回归的目标不是证明模型永远正确,而是让模型、Prompt、Tool 或流程升级后,团队知道哪项能力变好、哪项边界退化。
八、人工节点必须进入状态机,而不是藏在聊天窗口

高风险选题、母稿价值、最终视觉和发布决定通常仍需要强模型或人工主编。Harness 不必假装这些节点都能 API 化,但必须让它们可观察:
yaml
stage: final_semantic_review
mode: human_operated
input: [approved_candidate, source_ledger, gate_report]
output: [decision, findings, approved_sha]
on_enter: waiting_review
用户或编辑完成判断后,脚本只负责记录原始批准证据、批准范围和产物 SHA。批准母稿进入平台生产,不能 自动推导为批准最终包;批准最终包,也不能自动推导为允许外部 R2 写入或正式发布。每个外部副作用都要 有清楚的授权范围。
人的判断不是自动化缺陷。没有状态、没有输入输出、没有批准范围的人工作业,才是系统缺口。
九、四阶段实施顺序

阶段一:固定流水线
只实现 Task Contract、固定 Stage、单执行器、候选目录、Run Record 和一个 Schema Gate。目标不是自治, 而是同一输入能重复得到可审计结果。
阶段二:加入独立质量门
增加来源、事实、读者价值、平台和视觉 Gate;生产者与审核者分离;审核结果绑定 SHA。此时宁可人工判断, 也不要让生成者自己签字。
阶段三:加入可恢复执行
增加 Attempt、Checkpoint、Artifact Manifest、失败分类、幂等 Tool 和按变更面失效。先解决"失败后怎样 继续",再解决"怎样同时跑更多任务"。
阶段四:有限路由与自治
只有回归基线稳定后,才让路由器按风险和历史结果选择执行器,让模型决定是否读取更多来源或请求升级。 预算、权限、Acceptance Criteria、批准产物和发布授权仍不能由模型自行修改。
多 Agent 也应在这一阶段按需要加入。单条流程不能稳定完成时,多 Agent 只会放大状态、成本和调试问题。
十、怎样判断这条 Harness 已经值得扩展

不要用"它已经能自动完成一篇文章"作为成熟标准。至少观察这些信号:
- 同一回归集在模型、Prompt 和工具升级后可重复运行;
- 失败能定位到 Stage、Attempt、Artifact 和 Gate;
- 低风险机械变化不会重触发无关的昂贵审核;
- 高风险语义变化不能借机械回填绕过旧审核;
- 取消和重试不会让旧 Attempt 覆盖新产物;
- 外部写入都有独立授权和可逆证明;
- 执行器降级依据真实通过率与返工量,而不是价格或感觉;
- 人工编辑可以只看需要判断的证据,而不是重新检查整个流水线。
Batch 06 的参考 Schema 和本文蓝图都没有完成真实生产 E2E,不能被写成通用答案。它们的价值是给出一条 可实施顺序:先让一个工序可定义、可观察、可验证、可恢复,再增加路由和自治。
这也是从 Pi 最值得学走的东西。不是复制默认工具、终端界面或某个 Session 格式,而是让核心保持小, 让策略可以替换,让状态留在模型之外,让每个产物都能追溯,让每次批准都有边界。
成熟的 Harness 不以"模型能做多少事"为终点。它要让团队随时回答:系统现在要做什么,为什么选择这个 执行器,执行了哪些动作,哪份产物通过了什么检查,变化后哪些结论仍然有效,失败时从哪里继续,以及 最终决定由谁作出。
参考资料
- Pi
v0.82.1:github.com/earendil-wo... - Pi Coding Agent README:github.com/earendil-wo...
- Pi SDK:github.com/earendil-wo...
- Pi Session Format:github.com/earendil-wo...
- Pi Extensions:github.com/earendil-wo...
- 用户补充的 Batch 06 / Batch 09 PI-16 与 PI-18,以及静态合同和回归样例。