跳转到正文

Anthropic《Effective harnesses for long-running agents》系统解读:跨会话交接与 PPT Master 的制品化 harness

原文:Effective harnesses for long-running agents
实践项目:PPT Master
前置阅读:《Building effective agents》 · 《Agent Skills》 · 《Effective context engineering》

上一篇解读的结尾提到,PPT Master 的 split mode 与制品链本质上是一个手工搭建的 harness。这一篇要回答的就是:官方设计的 harness 长什么样,两者的差距在哪里。 这里的对应关系特指启用 split 的 Default Generate;默认连续执行、Quick profile 和三条非 Generate 路线并不采用同一套双会话结构。

原文的问题定义非常干脆:

The core challenge of long-running agents is that they must work in discrete sessions, and each new session begins with no memory of what came before.

注意后半句——每个新会话开始时对之前发生的一切毫无记忆。上一篇讨论的 compaction 在这里被明确判定为不够:

Compaction isn't sufficient.


一、基本概念:harness 是什么

原文把 harness 定位为支撑 Agent 运行的框架系统,并以 Claude Agent SDK 为例:

The Claude Agent SDK is a powerful, general-purpose agent harness adept at coding, as well as other tasks that require the model to use tools to gather context, plan, and execute.

三者的分工可以这样区分:

负责
模型执行任务的核心能力
Agent在一次会话内使用工具收集上下文、规划、执行
Harness让 Agent 能够跨越多个会话持续工作的框架

harness 解决的不是"这一轮怎么做对",而是"下一轮怎么接得上"。


二、两类失败模式

原文在实验中观察到的两个失败,值得单独记住,因为它们几乎必然出现在任何长任务系统里。

一次做太多

The agent tended to try to do too much at once—essentially to attempt to one-shot the app.

Agent 试图一口气完成整个应用,结果中途耗尽上下文窗口,留下一个半成品状态。

过早宣布完成

A later agent instance would look around, see that progress had been made, and declare the job done.

后续的 Agent 实例环顾四周,看到"已经有进展了",于是宣布任务完成。

第二种失败为什么更危险

第一种失败会留下明显的破损状态,容易被发现。第二种失败交付的是一个看起来完整的产物——只有逐项核对才知道少了什么。 一个没有清单的长任务系统,必然会在某个会话上提前收工。


三、解决方案:初始化 Agent 与编码 Agent

原文把职责拆成两个角色。

初始化 Agent(只在首次会话运行)

Set up the initial environment: an init.sh script, a claude-progress.txt file that keeps a log of what agents have done, and an initial git commit.

它不写业务代码,只负责让后续会话有一个可以接手的环境。

编码 Agent(后续每次会话)

Make incremental progress, then leave structured updates.

做增量进展,然后留下结构化的更新。 两个动作缺一不可——只做不留,下一个会话就得重新摸索。


四、环境中的四件关键制品

1. 特性清单(feature_list.json)

200 多项详细特性,初始全部标记为失败:

json
{
    "category": "functional",
    "description": "New chat button creates a fresh conversation",
    "steps": [...],
    "passes": false
}

配套一条硬规则:

It is unacceptable to remove or edit tests because this could lead to missing or buggy functionality.

选择 JSON 而非 Markdown 是有意的——原文指出 JSON 格式更难被不当篡改。这是一个容易被忽略的细节:清单的作用是约束 Agent,如果 Agent 可以顺手改写清单,约束就不存在了。

2. 进度文件(claude-progress.txt)

记录历次会话做了什么。原文把它和 git 历史一起视为整个方案的关键:

The key insight here was finding a way for agents to quickly understand the state of work when starting with a fresh context window, which is accomplished with the claude-progress.txt file alongside the git history.

3. 启动脚本(init.sh)

解决"新会话的 Agent 不知道怎么把应用跑起来"的问题。

4. Git 提交

每个会话结束提交一次,既是进度锚点也是回滚能力。原文要求代码达到"可以合并到主分支"的质量——环境必须是干净的,不能给下一班留下半截状态。

会话启动的标准流程

text
1. 运行 pwd 确认工作目录
2. 阅读 git log 和进度文件
3. 读取特性清单,选择优先级最高的未完成特性
4. 运行 init.sh 启动开发服务器
5. 做基础端到端测试

失败模式与制品的对应

失败模式初始化 Agent 提供编码 Agent 使用
过早宣布完成创建特性清单读清单,只做一个特性
环境遗留 bug初始化 git 与进度笔记开场检查,收尾提交并更新
特性标记不实设置特性清单自我验证,测试通过才标记
不知如何运行编写 init.sh开场读取并运行

五、原文承认的开放问题

原文没有给出定论的地方也值得记录:

It's still unclear whether a single, general-purpose coding agent performs best across contexts, or if better performance can be achieved through a multi-agent architecture.

单一通用 Agent 与多 Agent 架构孰优,官方也还在观察。这对下面的对照分析是个有用的背景——PPT Master 选择的是角色分工路线,但这不是被原文验证过的最优解。


从概念转入实践

以下用 PPT Master 检验这套 harness 设计。它的任务形态与原文案例(全栈 Web 开发)不同,但跨会话交接的问题完全一致。


六、角色对应:split 规划会话承担初始化职责

原文的双角色划分,在 PPT Master 里有一个几乎精确的对应:

原文PPT Master产出
初始化 Agentsplit 规划会话(Step 1–5,Strategist 主导)design_spec.mdspec_lock.mdimages/templates/
编码 Agentsplit 执行会话(Step 6–7,Executor 主导)svg_output/exports/

差别在于 触发方式。原文的初始化 Agent 只在首次运行,之后每次会话都是编码 Agent;PPT Master 只有在最终确认的 generation_modesplit 时,才会让规划会话产出全部计划并 主动终止,再由用户开新窗口输入「继续生成 projects/<项目名>」进入执行会话。这个选择既可能来自用户直接要求,也可能来自用户接受重上下文信号触发的建议;未选择 split 时,Default Generate 会在确认后自动连续进入页面生产。

resume-execute.md 的自我定位和原文的编码 Agent 完全一致:

This stage is context-independent: it owns the execution session starting from a fresh chat — no upstream conversation context required.


七、Default Generate 的页面清单就是特性清单

这是两个系统最强的对应关系。

原文用 feature_list.json 防止"过早宣布完成"。PPT Master 用的是 design_spec.md 第 IX 节的页面清单,并配了一条同等强度的硬规则:

Exact page roster: render design_spec.md §IX one-for-one, in order. Any add/drop/merge/split/reorder requires Spec repair/refinement first.

对照原文那句"不可删除或编辑测试",两者的逻辑完全相同:清单是约束,不是建议。想改清单,必须先回到上游修复规格,而不能在执行过程中顺手调整。

这条规则在执行纪律上直接针对第二种失败模式。Executor 不能"看到已经画了 15 页觉得差不多了"就收工——清单要求 20 页就必须生成 20 页,少一页在工作流语义上仍是未完成。但当前普通 flat Generate 尚无把 §IX 与实际 SVG ordered roster 做通用交叉比较的自动门,不能把这条硬规则误写成现有工具已经完整强制。

但格式上有差异

原文特意选择 JSON,理由是"比 Markdown 更难被不当篡改"。PPT Master 的页面清单存在 design_spec.md 里,是 Markdown

它靠 纪律(硬规则 + Gate 校验)而非 格式 来防止篡改。这个差异留到第十一节讨论。


八、split 恢复:以真实制品而不是审计日志重建状态

原文的方案是 claude-progress.txt 加 git 历史。PPT Master 已有 validation/workflow.log,但它是冷的命令/结果审计日志,不是规划状态、进度权威或恢复来源;resume-execute 明确禁止把它当作状态重放。在 split 或恢复执行时,Step 1 依靠真实制品重建上下文:

检查项何时必需说明
spec_lock.md始终执行锚点与路由契约
design_spec.md始终完整设计叙事与 §IX 页面清单
notes/total.md§X 声明用户提供的最终/逐字旁白时冻结的旁白输入,不能从旧对话重建
images/ 及相应文件lock 引用了图像时Existing / Generated / Sourced / Rendered 状态的文件必须存在
templates/lock 引用了版式时执行所需的版式与镜像原型
解析器返回的 Chart/Table SVGlock 引用了活动图表时必须通过共享目录解析并验证真实文件存在

中途恢复时还会读取"最新完成的 SVG"和当前图像元数据。

笔者归纳

PPT Master 用的是 以真实制品为恢复状态,而非 以审计日志为进度权威

svg_output/ 中的实际文件比 Agent 的自然语言自述更接近 outcome,但它也不是单独充分的完成证明:文件可能缺号、残缺、陈旧,存在也不表示已经通过质量门。恢复时必须结合 roster 纪律、文件内容、当前输入与 gate 结果解释。

代价是表达力:文件系统能告诉你"P07 存在",冷审计日志也可能保留相关命令或错误,但两者仍不能保证完整还原"P07 重画过三次,因为图表坐标一直对不上"。原文的 claude-progress.txt 保留的正是这类有意维护、面向接手者的历史。


九、验证:Default Generate 的质量门与恢复矩阵

原文的验证是"用浏览器自动化做端到端测试,通过后才标记特性为 passed"。PPT Master 的验证链条更长:

text
首页门(P01 完成后 svg_quality_checker --stage first-page)
  → 不间断生成剩余页面
    → 最终门(svg_quality_checker --stage final)
      → finalize_svg → svg_to_pptx
        → 导出回执(状态、页数、警告分类)

其中"首页门"的设计意图与原文的增量哲学一致:不是等 20 页全画完才发现方法有问题,而是在第一页就暴露并校准。Quick profile 会跳过首页门和 Spec/lock 相关检查,只运行无锁的最终检查与导出,因此这条验证链也不是所有路线共享的固定流程。

超出原文的部分:failure-recovery.md

原文用一张四行表格覆盖失败模式。PPT Master 有一份专门的治理文档,其恢复矩阵包含 20 多个失败点,每个失败点声明四个属性:

属性含义
Blocking是否阻断下一个门
Automatic recovery自动恢复动作
User intervention是否需要人工介入
Resume entry从哪一步恢复

配套一条全局硬规则:

A failed required artifact blocks the next gate. A failed convenience surface falls back to the canonical channel and does not block the active route.

区分"必需制品"和"便利设施"——在 Default Generate 中,Confirm UI 挂了可以退回聊天确认,但该 profile 所需的 spec_lock.md 缺失必须停止。这个区分让系统在部分组件失效时仍能推进,同时不会在当前 profile 的关键制品缺失时蒙混过关。

笔者观点

恢复矩阵的价值不在于列举了多少失败,而在于 每个失败都有一个声明好的恢复入口。原文提到"知道从哪里继续"是长任务的核心,PPT Master 把这件事从运行时判断变成了查表操作。


十、Default Generate 如何防止"一次做太多"

原文的第一种失败模式——试图一口气做完——PPT Master 用三个机制共同约束:

  1. 阻塞门SKILL.md 的全局纪律规定,遇到 ⛔ BLOCKING 必须停下等待用户明确确认,不得代替用户决定;
  2. 禁止跨阶段打包:不得把未关闭的门两侧的工作合并处理;
  3. 禁止投机执行:不得在拥有某制品的步骤到来之前提前准备该制品。

第三条尤其对应原文的观察。Agent"想一次做完"的倾向,具体表现就是提前生成后续阶段的产物——比如在设计还没确认时就开始画页面。把这条写成显式禁令,比事后发现半成品要有效。


十一、对照原文校准三个差异

以下差异不自动等于 PPT Master 的待办项。是否需要改变,应先看现行校验、恢复机制是否出现可复现故障。

1. 页面清单没有单独的结构化副本

原文明确选择 JSON 是因为"比 Markdown 更难被不当篡改"。PPT Master 的 §IX 页面清单在 Markdown 文档里,当前主要依赖硬规则和规划制品校验约束修改。

但这也不等于完全依赖 Agent 自觉:规划制品的结构和枚举、SVG/profile 约束以及结构化模板的映射关系都有代码检查。边界在于,普通 flat Generate 的 §IX 与实际 SVG ordered roster 目前没有通用自动交叉校验。系统选择让经确认的 Design Spec 保持页面清单权威,而不是再维护一份可能漂移的平行 JSON;若要自动证明一一对应,需要另加一个读取双方的最小派生检查。

如果未来出现现有检查无法捕获的清单漂移,可以研究独立的派生校验制品或哈希;不宜直接把更完整的页面权威塞进 spec_lock.md,因为 lock 是面向 Executor 的投影,不应反向取代 Design Spec。

2. 项目目录没有连续版本历史,但已有有界快照

原文用 git 提交作为进度锚点,同时提供回滚能力。PPT Master 的 projects/ 是用户工作区,不在版本控制下。

这意味着它没有原文那种逐步 commit 的连续历史。不过“完全没有回滚机制”也不准确:使用默认输出路径导出时会把现有 svg_output/ 复制到 backup/<timestamp>/svg_output/(显式 -o 会跳过该备份),可选视觉审查会在修改每个 SVG 前写入 .review/backup/。这些是有界快照,不等同于通用版本控制。

projects/ 还是被主仓库忽略的用户工作区。是否在外部工作区使用 git 应由用户决定,不属于 harness 应自动初始化或提交的现行职责。

3. 没有完整的跨会话重试历史

第八节讨论过,PPT Master 已有冷审计日志,也以真实制品作为恢复权威。这在正常路径上更可靠,但仍不会保存完整的失败和重试历史;workflow.log、postflight、检查报告与视觉审查记录只能覆盖各自有限范围。

具体场景:某页因为图表坐标问题重画了三次,最终通过。这个信息在文件系统上不留痕迹。下一次遇到类似页面时,Agent 无从得知这是一个已知的困难点。

原文的 claude-progress.txt 保留的正是这类信息。不过新增全局 progress.md 会引入另一份需要维护的状态。只有真实任务反复需要跨会话追溯重试原因时,这类追加日志才有明确收益;目前更准确的结论是“没有通用重试历史”,而不是“必须补一份日志”。


十二、我的理解:harness 是把交接成本前置

原文与 PPT Master 的共同点,是都不指望模型"记住"什么。

核心观点

harness 的本质,是 把跨会话的交接成本从运行时前置到设计时

设计时想清楚"下一个会话需要知道什么",把它写成固定结构的制品;运行时就不需要任何一方去回忆、推断或重建。

按这个标准,一个 harness 是否完备,可以用三个问题检验:

  1. 接手的 Agent 能否在不读任何对话历史的前提下知道当前状态?—— PPT Master 用 resume-execute 的 Step 1 校验回答;
  2. 它能否知道还有什么没做完?—— 用 §IX 页面清单与一一对应的硬规则回答;
  3. 它能否知道自己做的对不对?—— 用质量门与导出回执回答。

三个问题分别对应原文的进度文件、特性清单和端到端测试。对启用 split 的 Default Generate 而言,PPT Master 在第二、三问上使用清单纪律、质量门与恢复矩阵,在第一问上更轻:以真实制品而非冷审计日志重建状态,可靠性边界清楚,但不保留完整历史。

而原文留下的开放问题——单 Agent 还是多 Agent——PPT Master 事实上给出了一个中间答案:串行核心角色,加条件式并行支持阶段。Strategist 与 Executor 职责分离,核心页面生成保持主 Agent 串行;主题研究在宿主允许时使用隔离 worker,可选视觉审查也能分批并行。启用 split 时,规划与执行还会落在不同会话中。


十三、下一步

  1. Writing effective tools for agents— 本文第九节的质量门与回执,其接口设计质量直接决定 harness 是否可靠(系统解读);
  2. Demystifying evals for AI agents— 本文三个差异是否构成真实问题,需要评估证据而不是仅凭形式类比判断(系统解读)。

← 返回 Anthropic 学习地图