🏠 总目录📚 本教程 12 · Harness 骨架
📑 本页目录(点开跳转)

12 · Harness:长时任务的骨架

28 分钟 | ⭐⭐⭐ 本教程最重要的一节


🎯 一句话

Harness = 把原始模型智能变成可用 Agent 的那一整套东西(循环 + 工具 + 上下文管理 + 护栏)。 而这一节最重要的一句话是:

模型决定「做什么」① 循环控制什么时候继续、什么时候停② 状态管理上下文裁剪 + 进度持久化③ 错误处理失败了要不要重试、几次④ 终止条件步数 / 成本 / 无进展检测⑤ 可观测性每步都能记录和回放Harness = 包在模型外面的那层工程结构⭐ 模型决定「做什么」,Harness 决定「怎么把它跑稳」⚠️ 最容易漏的是④ —— 很多实现只设了「成功就停」,没设无进展检测,结果在死循环里烧 token
模型决定「做什么」,Harness 决定「怎么把它跑稳」。⚠️ 最容易漏的是④ —— 很多实现只设了「成功就停」,没设无进展检测,结果 Agent 在死循环里反复尝试同样的失败操作,把 token 烧光。

「Harness 的每个组件都编码了一个『模型自己做不到某事』的假设—— 而这些假设会随模型进步而过时。」


🧠 一、长任务为什么会失败

让 Agent 连跑几小时到几天(做完整 App、迁移代码库),朴素做法必撞的五头怪

失败模式 表现 根因
过度野心 想在一个上下文窗口干完全部,留下一堆半成品和破损状态 没有分解机制
过早宣告完成 下个会话看到部分功能能跑,就宣布"项目完成!" 没有客观完成标准
上下文焦虑 感知到接近 token 上限,开始草草收尾、偷工减料 模型的自我保护行为
目标漂移 跑几十轮后,做的事和最初目标越偏越远 目标没有被反复重申
状态丢失 会话重启后不知道做到哪,重复劳动或互相破坏 状态只存在上下文里

所有 harness 设计都是在对付这五头怪。 记住它们,你就知道每个组件为什么存在。


🏗️ 二、Harness 的四个组成

① 循环 Loop
  • 什么时候继续、什么时候停、怎么恢复
② 工具 Tools
  • 它能碰到什么(第 7 章)
③ 上下文管理 Context
  • 压缩、外置状态、子 Agent(第 4 章)
④ 护栏 Guardrails
  • max_steps、超时、预算、权限(第 15 章)

💡 模型生成文本,harness 决定这些文本能触碰什么。


📉 三、Harness 减法的三种模式

核心心态:harness 设计不只是「我还该加什么」,更重要的是「我可以停止做什么」。

模式一:依靠模型,而非 harness

   用 Claude 已深度掌握的【通用工具】,而不是发明专用工具

   📌 Claude 3.5 Sonnet 仅用 bash + 文本编辑器
      就在 SWE-bench Verified 上达到 49%
      —— Claude Code 本身也主要靠这两个工具

💡 为什么通用工具更好:模型在训练中见过海量 bash/文件操作的例子, 而你发明的 my_custom_edit_tool 它一次都没见过。熟悉度本身就是能力。

模式二:给 harness 做减法

让 Claude 自己做什么 怎么做 实测效果
编排自己的动作 给代码执行工具,让它自行过滤/管道化输出 BrowseComp 45.3% → 61.6%
管理自己的上下文 Skills 渐进式披露 + context editing 子 Agent 再加 2.8%
持久化自己的上下文 压缩 + 记忆文件夹 BrowseComp-Plus 60.4% → 67.2%

模式三:谨慎设置边界

边界 说明
缓存友好的上下文设计 稳定内容在前、动态在后;不要中途换模型(缓存是模型专属的)
声明式工具服务于安全与可观测 bash 杠杆大但可观测性差;专用工具的类型化参数便于拦截和记录
可逆性准则 难以撤销的动作值得用户确认

🧬 四、长时运行架构的三代演进

这是本章最有价值的部分——它展示了 harness 是怎么随模型进步而变化的。

第一代:初始化 Agent + 编码 Agent

要解决:过度野心 + 过早宣告完成

   【初始化 Agent】(只跑第一次)
     ├─ 生成 init.sh 启动脚本
     ├─ 生成 claude-progress.txt 进度文件
     ├─ 初始 git commit
     └─ ⭐ JSON 格式的完整功能清单
        (示例项目 200+ 项,初始全标 failing)

   【编码 Agent】(后续所有会话)
     ├─ 一次只做一个功能
     ├─ 每次变更都提交
     └─ 宣布完成前严格端到端测试

两个关键细节

细节 为什么
用 JSON 而非 Markdown 模型更不容易随意修改或覆盖 JSON 文件(格式刚性提供保护)
像人一样测试 给浏览器自动化工具,让 Agent 像真人用户一样点击验证——能发现纯代码审查发现不了的 bug

第二代:GAN 式生成-评估分离

核心洞察

模型评估自己的工作时有系统性正面偏差,主观任务上尤其明显。 把生成与评估分离,远比让生成者自我批判有效。

   【规划 Agent】把 1–4 句需求扩展成详细产品规格
        ↓
   【生成 Agent】按 Sprint 迭代实现,交 QA 前先自检
        ↓
   【评估 Agent】通过浏览器自动化测试运行中的应用
        ↑ 实现前先协商「Sprint 契约」定义成功标准

⭐ 让主观评估可行的关键技巧

   ❌ 「这个设计美吗?」        ← 无法回答,评估会流于形式
   ✅ 「这个设计是否符合以下四项标准?」
      · 设计质量  · 原创性  · 工艺  · 功能性

   💡 把主观判断【转化成可回答的具体条目】——这是所有 LLM 评估的通用技巧

成本对比(复古游戏制作器案例)

方案 耗时 成本 结果
单 Agent 20 分钟 $9 玩法损坏、流程僵硬、输入不可用
完整 harness 6 小时 $200 10 个 Sprint 覆盖 16 项功能、UI 精致、游戏可玩

💡 20 倍成本买的是「能用 vs 不能用」,不是「好 vs 更好」。

⚠️ 但要注意演进:对某一代模型必不可少的 Sprint 级分解, 到下一代反而成了多余开销。

🔑 「有用的 harness 设计空间不会随模型进步而缩小,而是会移动。」

第三代:模型自己写 harness

Claude 可以为当前任务现场写出专属的多 Agent 系统(JavaScript 文件 + 派生子 Agent 的函数)。

要对抗的三种失败

失败 说明
Agent 惰性 提前收工
自我偏好偏差 偏袒自己的结果
目标漂移 多轮后原始目标失真

六种常用模式:分类后执行、扇出后综合、对抗式验证、生成后过滤、锦标赛、循环到完成。

⚠️ 什么时候别用: - 没有真正并行需求的常规编码 - 不值得多 Agent 协调开销的任务 - 一个上下文窗口就能解决的问题


🧰 五、可以照抄的最小 harness

# 一个能对付"五头怪"的最小骨架
class MinimalHarness:
    def __init__(self, model, tools, goal):
        self.goal = goal
        self.state_file = "progress.json"      # ⭐ 对付"状态丢失"
        self.max_steps = 50                     # ⭐ 护栏
        self.token_budget = 100_000

    def run_session(self):
        state = self.load_state()               # 从文件恢复,不靠上下文
        # ⭐ 对付"目标漂移":每个会话开头重申目标 + 当前状态
        system = f"""目标:{self.goal}

当前进度:{state['done']} / {state['total']} 项已完成
下一项:{state['next_task']}

规则:
1. 一次只做【一个】功能项,做完立即更新 progress.json 并提交
2. 宣布完成前必须运行验证脚本并通过     ← 对付"过早宣告完成"
3. 不要开始新功能,直到当前这个通过验证  ← 对付"过度野心"
"""
        for step in range(self.max_steps):
            if self.tokens_used > self.token_budget * 0.75:
                self.compact()                  # ⭐ 对付"上下文焦虑"
            ...
        self.save_state(state)                  # 会话结束前落盘

这个骨架里每一行都对应一头怪——这就是 harness 设计的思维方式。

progress.json 有个正式名字:工作记忆(working memory)。 它是04b · Agent 记忆四层结构里的一层——只服务于当前这个任务,任务做完就该整个丢掉。 知道它是「哪一层」很有用,因为四层的写入和淘汰规则完全不同,混在一起就会烧钱或者出错

这里的东西 是哪一层 任务结束后
progress.json 里的 next_task / done 工作记忆 整个丢掉,留着只会污染下一个任务
「这个项目用 pnpm 不用 npm」 长期记忆 留下,下次开工直接生效
「上次改这个文件把 CI 跑挂了」 情景记忆 留下,是下次的避坑依据

⚠️ 最常见的错法是把三者全塞进同一个 progress.json——文件越滚越大, 每个会话开头都要整个读回上下文,Token 成本随任务时长线性上涨,而其中大部分早就没用了。 04b 讲的就是怎么分层、怎么判断一条该不该写、以及过期的怎么忘掉


🔁 六、Harness 的定期体检

每次模型升级后,问这五个问题

   ① 哪些提示词是为了绕过旧模型的缺陷写的?   → 试着删掉,跑评测
   ② 哪些专用工具可以换成通用工具?           → 模式一
   ③ 哪些编排逻辑可以交给模型自己做?         → 模式二
   ④ 哪些分解粒度可以放粗?                  → Sprint 级 → 功能级
   ⑤ 哪些护栏还有必要?                      → 但安全护栏别乱删 ⚠️

⚠️ 注意第 ⑤ 条功能性的变通可以删,安全边界不能删(第 15 章)。 「模型现在更聪明了所以不用沙箱了」是错误的推论—— 安全护栏防的是外部攻击,不是模型能力不足。


🕳️ 七、六个常见坑

症状
状态只存在上下文里 会话一断全丢 外置到文件(JSON)
没有客观完成标准 Agent 说完成了其实没有 功能清单 + 验证脚本
目标只在第一条消息里说过 跑几十轮后跑偏 每个会话开头重申
harness 从不做减法 越堆越复杂,模型升级后成累赘 定期体检五问
让生成者自评 永远说自己做得好 生成-评估分离
主观标准无法执行 「做得好看点」→ 评估流于形式 转成可回答的具体条目

📚 延伸阅读

👉 这一节对应的框架:LangGraph 主攻的正是这里最难的半截 —— 状态怎么外置、断了怎么接着跑。对照关系在 16b · 框架这层皮



✅ 检查点

  1. Harness 是哪四部分组成的?
  2. 长任务失败的五头怪是什么?
  3. 本章最重要的那句话是什么?它的实践含义是什么?
  4. 减法的三种模式分别是什么?
  5. 为什么长时任务的状态文件推荐 JSON?
  6. 为什么要把生成和评估分离?
  7. 「这个设计美吗」该怎么改写才能让评估可行?
  8. 模型升级后哪些 harness 组件可以删,哪些不能?
👀 答案
  1. 循环、工具、上下文管理、护栏。
  2. 过度野心、过早宣告完成、上下文焦虑、目标漂移、状态丢失。
  3. 「harness 的每个组件都编码了一个『模型做不到某事』的假设,而假设会过时」。含义:要定期问「我可以停止做什么」,而不只是「还该加什么」。
  4. ①依靠模型而非 harness(用通用工具如 bash)②给 harness 做减法(让模型自己编排/管理/持久化上下文)③谨慎设置边界(缓存友好、声明式工具、可逆性准则)。
  5. 模型更不容易随手修改或覆盖 JSON——格式刚性提供了保护。Markdown 太"软"容易被整体重写。
  6. 模型自评有系统性正面偏差,主观任务尤其明显。分离比让生成者自我批判有效得多。
  7. 转成可回答的具体条目:「是否符合以下四项标准:设计质量/原创性/工艺/功能性」。
  8. 功能性的变通可以删(为旧模型缺陷写的提示、过细的分解);安全边界不能删——它防的是外部攻击,不是模型能力不足。

🛑 可以停在这里

走神救援

Harness=循环+工具+上下文管理+护栏。⭐核心命题:每个组件都编码了一个「模型自己做不到某事」的假设,而假设会随模型进步过时 → 要定期问「我可以停止做什么」。五头怪:过度野心、过早宣告完成、上下文焦虑(快到上限就草草收尾)、目标漂移、状态丢失。减法三模式:①用通用工具而非自造——熟悉度本身就是能力,Claude 3.5 Sonnet只靠bash+文本编辑器就在SWE-bench Verified拿49%;②让模型自己编排/管理/持久化上下文——BrowseComp 45.3%→61.6%、子Agent再加2.8%、BrowseComp-Plus 60.4%→67.2%;③谨慎设边界——缓存友好(⚠️不要中途换模型)、可逆性准则三代架构:一代=初始化Agent(JSON功能清单200+项、初始全标failing)+编码Agent(一次一个功能、每次变更就提交、完成前端到端测试);⭐用JSON不用Markdown,格式刚性让模型不容易覆盖像真人一样点一遍能发现纯代码审查发现不了的bug。二代=生成-评估分离,因为⭐模型自评有系统性正面偏差;⭐把「这个设计美吗」改成「是否符合设计质量/原创性/工艺/功能性四项标准」;单Agent 20分钟$9但产物不可用,完整harness 6小时$200、覆盖16项功能——20倍买的是「能用vs不能用」。三代=模型自己写harness。⚠️上一代必不可少的Sprint级分解,下一代反成多余开销——设计空间不会缩小,只会移动。升级后做体检五问(删旧提示、专用换通用、编排交还模型、粒度放粗),⚠️但安全护栏不能删:它防的是外部攻击,不是模型能力不足。

下一节 👉 13-多Agent协作.md

打卡记录保存在你的浏览器里,首页能看到总进度