Long-running Agent Harness
Long-running Agent Harness 是本知识库对一类长时任务执行外壳的归纳:当 AI Agent(智能体) 的工作跨越多个 上下文窗口 时,harness 不能只依赖自动压缩或聊天历史续接,而要把任务规格、进度、验证证据和下一步入口写到外部环境里,让每个新会话都能像接班工程师一样快速恢复状态。
Anthropic 2025 年 11 月的工程文章把这个问题放在 Claude Agent SDK 场景中讨论:即使有 compaction,单纯让强模型循环执行一个高层目标,仍会出现两类失败:一是试图一次性做太多,耗尽上下文后留下半成品;二是在项目已经有部分进展时提前宣布整体完成。解决方向不是把上下文窗口塞得更满,而是设计一个能跨会话交接的 Harness Engineering(驾驭工程)。
OpenAI 的 Codex 长程实验提供了同一模式的另一侧证据:GPT-5.3-Codex 连续约 25 小时构建设计工具,期间发生 13 次自动上下文压缩、2,106 次工具调用和约 26k 行 patch。真正支撑这次长跑的不是单个巨大 prompt,而是写入仓库的规格、计划、执行规则、状态日志和验证命令。这说明长时 harness 的共同核心是外部化控制状态:让下一轮循环从文件、git 和测试结果恢复,而不是从模型记忆里猜。
两阶段模式
Anthropic 的方案把第一次会话和后续会话分开:
| 阶段 | 角色 | 产物 | 目的 |
|---|---|---|---|
| Initializer agent | 第一次运行的专用 prompt | feature_list.json、init.sh、claude-progress.txt、初始 git commit | 把模糊需求展开成可验证功能清单,并建立可复跑环境 |
| Coding agent | 后续每个新上下文窗口 | 单个功能的实现、测试证据、git commit、进度更新 | 小步推进,同时留下下一轮可读的交接材料 |
这个划分的关键是:初始化不是开始写代码,而是给未来所有 Agent 建工作场地。feature_list.json 是任务范围的结构化来源,init.sh 是环境恢复入口,claude-progress.txt 和 git history 是 Agent Memory(Agent 记忆),初始 commit 则把“环境从何处开始”变成可审计事实。
Codex 的 durable project memory
Codex 长程实验没有使用 Anthropic 示例中的 feature_list.json / claude-progress.txt 命名,但文件栈承担了相同职责:
| 文件 | Harness 职责 |
|---|---|
Prompt.md | 冻结目标、非目标、约束、交付物和 “done when” |
Plan.md | 将开放任务拆成 milestone,每个 milestone 带验收标准和验证命令 |
Implement.md | 规定执行协议:按计划推进、保持 diff scoped、失败先修复、持续更新文档 |
Documentation.md | 保存当前状态、决策记录、运行方法、demo flow 和 known issues |
这组文件构成了文章所说的 durable project memory。它和自动 compaction 互补:compaction 帮助当前上下文继续容纳历史摘要,project memory 则把关键控制状态放进仓库,使 Agent 能反复回读稳定定义的目标和完成标准。
flowchart LR
SPEC["Prompt.md\n目标与边界"] --> PLAN["Plan.md\nmilestone + 验收"]
PLAN --> RUNBOOK["Implement.md\n执行协议"]
RUNBOOK --> LOOP["Codex loop\n实现/验证/修复"]
LOOP --> DOC["Documentation.md\n状态与决策"]
DOC -.-> PLAN
LOOP --> VERIFY["lint/typecheck/test/build/export"]
VERIFY -->|"失败"| LOOP
VERIFY -->|"通过"| DOC
Codex 实验的截图还暴露了一个重要细节:验证不是一次总验收,而是 milestone 后的持续质量门。示例命令包括 npm run lint、npm run typecheck、npm run test、npm run build、导出 CLI、snapshot-focused tests、replay-focused tests 和 persistence-focused tests。长时 harness 的可靠性来自这些外部失败信号;没有它们,Agent 只能靠自我叙述判断是否完成。
交接流程
一个典型后续会话的启动顺序是:
flowchart LR
PWD["确认工作目录"]
STATE["读取 progress file"]
GIT["查看 git log"]
FEATURES["读取 feature_list.json"]
INIT["运行 init.sh"]
SMOKE["浏览器端到端 smoke test"]
PICK["选择一个未通过功能"]
WORK["实现、验证、提交、更新进度"]
PWD --> STATE --> GIT --> FEATURES --> INIT --> SMOKE --> PICK --> WORK
这条流程把 Context Engineering(上下文工程)里的 Write / Select / Compress 原则落到编码任务上:长期状态写入文件和 git;新会话只选择当前需要的高信号材料;上一轮详细工具轨迹不再依赖 compaction 传递。
Feature list 作为外部规格
feature_list.json 的设计不是普通 TODO,而是可执行验收清单。Initializer agent 会把最初的高层 prompt 展开为大量端到端功能描述,每项包含类别、用户步骤和 passes: false。后续 Coding agent 只能在验证后把 passes 改为 true,不应删除或重写测试描述。
用 JSON 而不是 Markdown 有两个工程含义:
- 结构更难被随意改坏:模型更容易把 Markdown checklist 当作可编辑叙事,JSON 则更像数据文件。
- 状态与验收绑定:
passes字段把“是否完成”从自然语言总结变成可检查状态,降低 Agent 自称完成的空间。
这与 Evals(评估)的原则一致:评估条件要客观、难作弊、可回归。只让 Agent 写“我做完了”没有价值;让它在端到端测试后改变明确字段,才是可追踪的进度。
干净状态与小步提交
长时 Agent 最大的隐患不是某一轮失败,而是失败被下一轮继承却没有说明。Anthropic 因此要求每个 Coding agent 只做一个功能,并在结束时把仓库留在接近可合并的干净状态:没有明显 bug,代码整洁,有清楚的 progress update 和描述性 git commit。
git 在这里不只是版本控制,而是 harness 的恢复机制:
- 下一轮 Agent 可以通过 log 理解最近改动;
- 当前轮改坏时可以回滚到已知好状态;
- 人类可以审查每个增量,而不是面对一次巨大 diff;
- commit message 与 progress file 形成双轨记忆,一个记录代码事实,一个记录任务意图。
这也是 Loop Engineering(循环工程)里“外部状态文件 + 质量门 + 路由”的具体实现。没有小步提交,长时循环会把多轮错误堆成一个难以诊断的状态。
端到端测试是启动条件
文章强调,Coding agent 不应一启动就写新功能,而要先恢复环境并跑基本端到端 smoke test。例如 web app 场景下,用 Puppeteer MCP 像真实用户一样打开新聊天、发送消息、等待响应。这样做能先发现上一轮留下的未记录破坏,避免在坏状态上继续叠加功能。
页面中的截图主要说明这个验证形态:Claude 通过 Puppeteer MCP 捕获浏览器截图来检查 claude.ai clone 的界面行为。它不是新的算法,而是一个 harness 设计原则:给 Agent 接近真实用户路径的验证工具。单元测试、curl 或代码阅读不足以证明 UI 功能真的可用;浏览器自动化把失败信号移动到用户体验层。
仍有边界:Puppeteer MCP 这类视觉/浏览器工具可能看不到浏览器原生 alert modal,依赖这些原生弹窗的功能仍容易漏测。因此长时 harness 需要把已知测试盲区写入进度文件或功能清单,而不是假设端到端测试覆盖一切。
失败模式对照
| 失败模式 | Initializer agent 的职责 | Coding agent 的职责 |
|---|---|---|
| 过早宣布全项目完成 | 建立完整 feature list,让未完成范围显式存在 | 每轮读取清单,只选择一个未通过功能 |
| 留下 bug 或未记录进度 | 初始化 git repo 和 progress file | 启动时读进度与 git log,结束时 commit 并更新进度 |
| 未测试就标记通过 | 所有功能初始为 passes: false | 只有认真自测后才能改为 true |
| 不知道如何运行应用 | 写出 init.sh | 启动时先读并运行 init.sh |
这个表格的价值在于把“模型行为问题”转译成“环境中缺什么控制状态”。当 Agent 试图 one-shot、忘记测试、或提前收工时,修复点往往不是再写一句更凶的 prompt,而是补一个外部规格、质量门或交接产物。
OpenAI 和 Anthropic 两个案例的差异也有价值:Anthropic 更强调跨多个新会话 的小步接力,Codex 文章更强调单个长会话 在 compaction、工具调用和持续验证下保持连贯。但两者收敛到同一工程判断:长时 Agent 的状态必须落到可审查的外部介质里,且每个阶段都要有机器可验证的通过条件。
与持久执行的边界
Long-running Agent Harness 解决的是跨上下文窗口的认知续接;Durable Execution(持久执行)解决的是进程崩溃或部署后的步骤级恢复。两者相邻但不等价。
feature_list.json、progress file 和 git commit 能让下一次 Agent 会话理解“现在做到哪了”;持久执行引擎则保证“步骤 3 成功、步骤 4 失败后,重启时不会重跑步骤 1–3”。生产系统通常需要两者:外部状态让 Agent 接得上任务,步骤级 checkpoint 让运行时接得上流程。
相关概念
- Harness Engineering(驾驭工程) — 长时 Agent harness 所属的系统工程面
- Claude Agent SDK — Anthropic 示例使用的 Agent SDK
- Agent Memory(Agent 记忆) — progress file、git history 和 feature list 的共同角色
- Context Engineering(上下文工程) — 跨上下文窗口时的 Write / Select / Compress 策略
- Evals(评估) —
feature_list.json和浏览器端到端测试提供外部完成信号 - Loop Engineering(循环工程) — 把长时执行组织成可路由、可停止、可审计的循环
- Durable Execution(持久执行) — 与长时 harness 互补的运行时恢复层