Anthropic 适用于长期运行代理的有效工具 精读笔记
info
Anthropic 近期发布的工程博客《Effective harnesses for long-running agents》提出了一套面向长期运行任务(如持续数小时/数天的软件开发)的 AI Agent 架构设计与工程机制。本文对该论文进行了深入的精读与结构化总结,提炼出核心技术点、关键流程、失败案例及经验教训,并附上可直接落地的配置代码示例,旨在帮助工程师理解并应用该架构于实际项目中。
一、文章整体理解
本文聚焦 AI Agent 在处理跨多个上下文窗口的长时任务(如持续数小时/数天的软件开发)时的核心痛点——离散会话间的状态断裂与进度一致性问题。随着 AI 能力提升,开发者越来越需要 Agent 承接复杂长任务,但现有上下文窗口限制和压缩机制(compaction)无法解决 Agent“一次性贪多”或“过早宣告完成”的问题,导致项目进展混乱、功能残缺。这一问题在工程实践中至关重要,因为长时任务的自动化是 Agent 落地的核心场景,而状态管理和增量推进是自动化可靠性的基础。作者的核心思路源自人类软件工程师的协作模式,设计了“初始化 Agent + 编码 Agent”的双角色架构,通过环境标准化、进度结构化、增量开发、强制测试,让 Agent 能跨会话持续推进任务,同时保持环境清洁可继承。
二、核心技术点拆解
技术点 1:双 Agent 架构(初始化 Agent + 编码 Agent)
- 解决问题:长时任务中“初始环境无标准”和“会话间进度无衔接”的双重问题,避免 Agent 重复工作或偏离目标。
- 传统方式不足:单一 Agent 既负责环境搭建又负责功能开发,导致初始架构混乱、后续会话无法快速理解前置状态,且缺乏明确的任务分解边界。
- 设计方案:
- 初始化 Agent:仅在首次会话执行,输出三件核心产物——
init.sh启动脚本(统一开发环境)、claude-progress.txt进度日志(结构化记录历史操作)、feature_list.json功能清单(全量需求拆解),并完成初始 Git 提交。 - 编码 Agent:后续所有会话执行,专注单功能增量开发,会话前后通过读取进度文件和 Git 日志衔接状态,结束时提交代码并更新进度。
- 初始化 Agent:仅在首次会话执行,输出三件核心产物——
- 关键 trade-off:
- 优点:职责边界清晰,环境和需求标准化,后续 Agent 无需重复搭建和探索,提升效率。
- 缺点:增加了初始配置成本,对初始化 Agent 的需求拆解能力要求极高;若初始功能清单遗漏需求,后续需手动修改(且有破坏原有结构的风险)。
技术点 2:结构化功能清单(feature_list.json)
- 解决问题:Agent 过早宣告任务完成、功能开发无明确范围、进度不可量化的问题。
- 传统方式不足:仅依赖高层级提示(如“构建 claude.ai 克隆版”),Agent 无法感知全量需求边界,容易遗漏功能或误判完成状态;Markdown 等非结构化清单易被 Agent 随意修改。
- 设计方案:
- 由初始化 Agent 基于用户提示拆解全量功能(示例中达 200+ 项),每项包含分类、描述、测试步骤、是否通过(passes)字段。
- 强制规定编码 Agent 仅能修改 “passes” 状态,禁止删除或编辑测试步骤(通过强提示约束)。
- 采用 JSON 格式存储,利用模型对 JSON 结构的尊重性,减少不当修改。
- 关键 trade-off:
- 优点:需求边界清晰,进度可视化,避免功能遗漏和过早收尾。
- 缺点:初始拆解耗时较长,复杂项目的功能分类和测试步骤设计难度大;JSON 格式灵活性低,不适合快速迭代的需求变更场景。
技术点 3:增量开发 + 清洁状态约束
- 解决问题:Agent 一次性实现过多功能导致上下文溢出、代码遗留 bug 或文档缺失,后续会话需花费大量时间修复的问题。
- 传统方式不足:无明确开发粒度限制,Agent 倾向于“一锤子买卖”式开发,超出上 下文窗口后功能半成品遗留,且无强制清洁要求。
- 设计方案:
- 增量开发:编码 Agent 每次会话仅允许选择一个未完成的高优先级功能开发。
- 清洁状态要求:代码需达到可合并到主分支的标准(无重大 bug、文档完整、结构规整),通过 Git 提交(含描述性提交信息)和进度文件更新固化状态。
- 关键 trade-off:
- 优点:降低单次会话的上下文压力,减少功能半成品,后续 Agent 可直接接手开发。
- 缺点:开发效率看似降低(单次仅完成一个功能),但避免了返工成本,长期收益更高;对 Agent 的代码质量和提交规范要求严格。
技术点 4:端到端测试强制化(结合浏览器自动化工具)
- 解决问题:Agent 仅完成代码编写但未验证端到端功能,导致“标记完成但实际不可用”的虚假进度问题。
- 传统方式不足:无明确测试要求时,Agent 仅依赖单元测试或简单接口调用验证,忽略用户视角的端到端流程(如浏览器交互),遗漏实际使用场景的 bug。
- 设计方案:
- 强制要求编码 Agent 使用 Puppeteer MCP 等浏览器自动化工具,模拟人类用户操作流程(如点击“新建聊天”、输入查询、验证响应)。
- 测试结果作为功能“passes”状态修改 的唯一依据,未通过端到端测试的功能不得标记为完成。
- 关键 trade-off:
- 优点:大幅提升功能可用性,减少“纸面完成”的虚假进度,降低后续返工风险。
- 缺点:增加了 Agent 的工具使用复杂度和会话耗时;受限于浏览器自动化工具能力(如无法识别原生弹窗),部分场景测试覆盖不全。
技术点 5:会话初始化标准化流程
- 解决问题:编码 Agent 启动时需花费大量 tokens 探索环境状态、排查遗留问题,导致效率低下且易因环境异常引入新 bug。
- 传统方式不足:Agent 启动无固定流程,依赖自主判断环境状态,容易遗漏遗留 bug 或重复探索已有信息。
- 设计方案:
- 执行
pwd确认工作目录,明确文件操作范围; - 读取
claude-progress.txt和 Git 日志(git log --oneline -20),快速衔接历史进度; - 读取
feature_list.json,选择高优先级未完成功能; - 执行
init.sh启动开发服务器,运行基础端到端测试,验证环境可用性。
- 关键 trade-off:
- 优点:减少 Agent 的探索成本,快速定位环境问题,避免在破碎环境上开发新功能。
- 缺点:标准化流程占用部分会话 tokens;若基础测试用例设计不完善,仍可能遗漏环境异常。
三、关键流程 / 机制复盘
1. 整体工作流程(初始化+编码循环)
2. 编码 Agent 单会话流程
3. 流程核心说明
输入
- 用户高层级需求提示(如“构建 claude.ai 克隆版”);
- 工具集(bash、Git、Puppeteer MCP 浏览器自动化工具、文件读写工具)。
中间状态演进与步骤职责
- 初始化阶段(仅执行 1 次)
- 执行者:初始化 Agent
- 职责 :
- 拆解用户需求为结构化功能清单(
feature_list.json),所有功能初始标记为“passes: false”; - 编写
init.sh脚本(包含开发服务器启动、基础环境配置); - 创建
claude-progress.txt日志文件,记录初始化操作; - 初始化 Git 仓库并完成首次提交。
- 拆解用户需求为结构化功能清单(
- 输出:标准化初始环境(含 3 个核心文件+Git 仓库)。
- 编码阶段(循环执行至所有功能完成)
- 执行者:编码 Agent
- 会话内步骤:
a. 环境探测:
pwd确认目录 → 读取进度文件/Git 日志 → 读取功能清单; b. 环境验证:执行init.sh启动服务器 → 用 Puppeteer 测试基础功能(如聊天、主题切换),修复遗留 bug; c. 功能开发:选择 1 个高优先级未完成功能,编写代码; d. 功能测试:用浏览器自动化工具执行端到端测试,确保功能可用; e. 状态固化:Git 提交(含描述性信息)→ 更新claude-progress.txt→ 修改功能清单中该功能的“passes”状态为 true; - 输出:新增 1 个可用功能 + 清洁的代码仓库 + 更新后的进度/功能文件。
最易出问题的环节
- 初始化阶段:功能清单拆解不全面(遗漏核心需求)或测试步骤设计不合理(无法覆盖实际场景);
- 编码阶段:基础功能验证不充分(遗留 bug 未发现)→ 新功能开发叠加问题,导致后续环境破碎;
- 跨会话衔接:Git 提交信息不清晰或进度文件更新不及时 → 下一个 Agent 无法准确理解历史操作。
四、架构可视化
架构图核心逻辑
聚焦「双 Agent 协作+状态流转」,清晰呈现初始化 Agent、编码 Agent、核心产物、工具集的关系.
五、失败案例 & 经验教训
失败模式与解决方案流程图
核心失败模式(Failure Modes)
- 一次性贪多导致上下文溢出
- 表现:Agent 尝试在单个会话中实现整个应用,中途耗尽上下文窗口,留下半成品功能且无文档;
- 原因:无明确开发粒度约束,模型倾向于“快速交付”的直觉行为,忽略上下文窗口限制;
- 工程师易犯错误:设计 Agent 时未拆分任务粒度,过度依赖模型 的自主规划能力,未设置“单次会话最大工作量”约束。
- 过早宣告任务完成
- 表现:部分功能实现后,Agent 观察到已有进度即判定全量任务完成;
- 原因:缺乏全量需求清单作为参照,Agent 无法感知未完成功能边界;
- 工程师易犯错误:仅提供高层级目标,未拆解详细需求清单,未建立“完成标准”的量化指标。
- 遗留 bug 与无文档进度
- 表现:会话结束时代码存在未修复 bug,或进度未记录 → 下一个 Agent 需重新排查和猜测,浪费时间;
- 原因:无强制的“清洁状态”要求和进度记录机制,Agent 缺乏“协作意识”;
- 工程师易犯错误:未设计状态固化机制(如强制 Git 提交、进度日志),忽视 Agent 间“协作”的核心是“状态可继承”。
- 未验证端到端功能即标记完成
- 表现:代码语法正确,但实际用户流程中功能不可用(如点击按钮无响应),Agent 仍标记为“完成”;
- 原因:缺乏强制的端到端测试要求,Agent 仅验证代码层面的正确性,忽略用户视角的可用性;
- 工程师易犯错误:仅关注代码输出,未设计“用户视角”的测试流程,混淆“代码编写完成”和“功能可用”的边界。
反直觉结论
- 并非“能力越强的模型越能处理长时任务”:即使是 Opus 4.5 这样的前沿模型,无合理 harness 设计时,也无法完成生产级应用开发;
- 结构化格式(JSON)比灵活格式(Markdown)更适合 Agent 协作:模型对 JSON 的结构尊重性更高,能减少不当修改,保证需求清单的稳定性;
- “慢即是快”:限制 Agent 单次仅开发一个功能,看似降低效率,实则避免返工,整体进度更可控。
六、核心配置代码
1. init.sh 环境初始化脚本
#!/bin/bash
# 初始化开发环境:安装依赖 + 启动服务 + 基础测试
set -e
# 1. 安装项目依赖(以 Node.js 全栈项目为例)
echo "正在安装依赖..."
npm install express react react-dom puppeteer --save
# 2. 创建基础目录结构
echo "创建目录结构..."
mkdir -p src/{api,frontend,tests}
touch src/api/server.js src/frontend/App.js src/tests/e2e.test.js
# 3. 启动开发服务器(后台运行)
echo "启动开发服务器..."
node src/api/server.js
sleep 5 # 等待服务器启动
# 4. 基础健康检查
echo "检查服务器可用性..."
curl -s http://localhost:3000/health || (echo "服务器启动失败" && exit 1)
echo "环境初始化完成!可访问 http://localhost:3000 开始开发"
2. feature_list.json 功能清单示例
[
{
"category": "功能型",
"description": "新聊天按钮创建全新对话",
"steps": [
"点击页面顶部的'New Chat'按钮",
"验证页面跳转至新对话界面",
"检查聊天区域显示欢迎语",
"确认新对话出现在侧边栏列表"
],
"passes": false
},
{
"category": "功能型",
"description": "用户输入查询后获取 AI 响应",
"steps": [
"在聊天输入框中输入文本",
"按下 Enter 键或点击发送按钮",
"验证输入内容显示在聊天记录中",
"确认 5 秒内收到 AI 回复"
],
"passes": false
},
{
"category": "界面型",
"description": "支持主题切换(明/暗模式)",
"steps": [
"点击页面右上角的主题切换按钮",
"验证页面背景色切换",
"检查文字颜色适配主题",
"刷新页面后主题偏好保持一致"
],
"passes": false
}
]
3. claude-progress.txt 进度日志示例
# Claude 长时任务进度日志
## 2025-11-26 10:00:00(初始化阶段)
- 执行主体:初始化 Agent
- 操作:创建 init.sh 脚本、feature_list.json(203项功能)、claude-progress.txt
- Git 提交:init: 初始化项目环境与需求清单
- 状态:基础环境就绪,所有功能待开发
## 2025-11-26 14:30:00(编码阶段)
- 执行主体:编码 Agent
- 操作:
1. 验证基础环境正常(服务器启动成功)
2. 开发"新聊天按钮创建全新对话"功能
3. 用 Puppeteer 完成端到端测试(4个步骤全部通过)
- Git 提交:feat: 实现新聊天按钮功能,支持对话创建与侧边栏显示
- 状态:1/203 功能完成,环境清洁无遗留 Bug
## 2025-11-26 16:15:00(编码阶段)
- 执行主体:编码 Agent
- 操作:
1. 读取历史进度,确认下一个高优先级功能
2. 开发"用户输入查询后获取 AI 响应"功能
3. 测试发现响应延迟问题,优化接口调用逻辑后通过测试
- Git 提交:feat: 实现用户查询与 AI 响应功能,优化响应速度
- 状态:2/203 功能完成,核心聊天流程可用
代码使用说明
init.sh:需根据项目技术栈(如 Python/Java/Node.js)调整依赖安装和服务启动命令;feature_list.json:可通过初始化 Agent 自动生成,也可手动补充,核心是「功能描述+可测试步骤+状态标记」;claude-progress.txt:由编码 Agent 自动更新,需保证「操作可追溯、状态可量化」,便于后续会话快速衔接。
七、工程启发 & 可迁移经验
适用场景扩展
1. AI Agent 领域
通用经验
- 长时任务必须拆分“初始化-执行”双阶段,明确初始环境标准;
- 用结构化文件(如 JSON)固化需求、进度和状态,避免 Agent 自主修改核心规则;
- 强制“增量开发+状态固化”,每次会话仅完成单一目标,结束时固化成果;
- 可直接复用:功能清单设计、进度日志+Git 协同、端到端测试强制化。
2. 分布式系统领域
通用经验
- 离散节点(对应 Agent 会话)的协作核心是“状态可同步”和“职责可划分”(类似本文双 Agent 架构);
- 初始化节点(对应初始化 Agent)需提供统一的运行环境和协议(类似
init.sh和功能清单); - 每个节点执行后需提交“操作日志”(对应 Git 提交+进度文件),便于故障回溯和状态恢复。
3. 长任务 / 状态管理领域
通用经验
- 长任务必须拆解为可增量完成的子任务,明确每个子任务的“完成标准”;
- 状态管理需兼顾“可读性”(供后续执行者理解)和“不可篡改性”(避免核心规则被破坏);
- 每次状态变更后需执行“校验逻辑”(对应本文的基础功能测试),防止错误累积。
4. 自动化系统领域
通用经验
- 自动化工具的可靠性依赖“标准化输入”和“可验证输出”(本文的初始环境和端到端测试);
- 避免“黑盒自动化”,需记录每一步操作日志,便于问题排查;
- 设定“安全边界”(如本文禁止修改功能清单测试步骤),防止自动化工具因误判导致系统混乱。
Anthropic 特定 vs 通用工程思想
- Anthropic 特定:依赖 Claude Agent SDK 的工具调用能力(如 Git、Puppeteer)、上下文压缩机制,针对大语言模型的行为特点(如偏好结构化格式、易贪多)设计约束;
- 通用工程思想:
- 职责分离(初始化 vs 执行);
- 环境标准化(统一启动脚本、目录结构);
- 增量开发与状态固化;
- 需求量化与完成标准明确;
- 强制测试与校验机制。
八、隐含的设计哲学
- “模拟人类高效协作模式”是 Agent 长时任务的核心设计思路:文章的所有机制(双角色、进度日志、Git 协同、功能清单)均源自人类软件工程师的团队协作流程,本质是将“人类协作的隐性规则”转化为“Agent 可执行的显性机制”,而非依赖模型的自主进化。
- “约束大于自由”是提升 Agent 可靠性的关键:通过限制 Agent 的操作范围(如仅修改功能清单的 passes 字段)、开发粒度(单次一个功能)、输出格式(JSON 结构化),减少模型的“自主决策空间”,从而降低出错概率——这反映了 Anthropic 对 AI Agent 的认知:当前阶段,模型的“执行能力”强于“规划能力”,合理的约束能更好地发挥其执行优势。
- “状态可继承性”是长时任务自动化的基石:所有设计(进度文件、Git 日志、功能清单 )最终都服务于“会话间状态无缝衔接”,避免因上下文窗口限制导致的“从头再来”——这体现了系统工程中“无状态设计不可靠,有状态设计需保证状态可追溯”的核心认知。
- “测试是进度的唯一标准”:将端到端测试作为功能完成的必要条件,而非可选步骤,反映了“工程交付的核心是可用,而非代码存在”的认知升级,避免了“纸面完成”的虚假进度。