Agent Harness Design: 3 Patterns for Harnessing Claude's Intelligence¶
原文:Agent Harness Design: 3 Patterns for Harnessing Claude's Intelligence
发布日期:2026-04-02 | 作者:Lance Martin(Anthropic Claude Platform 团队)
引言¶
Agent harness 编码的是「模型做不到什么」的假设,但这些假设会随模型进化而过时——设计 harness 的核心就是不断移除多余的脚手架。
Anthropic 联合创始人 Chris Olah 曾说过,Claude 这样的生成式 AI 系统更像是「生长」出来的,而非「构建」出来的。研究者设定生长条件来引导方向,但最终涌现出的结构和能力并不总是可预测的。
这给开发者带来一个核心挑战:agent harness 编码了关于 Claude 自身局限的假设,但随着 Claude 越来越强,这些假设会快速过时。
什么是 Agent Harness?它是包裹在模型外围的软件脚手架——循环、工具、上下文管理和护栏——将原始智能转化为可工作的 agent。Agent harness 设计的实践就是决定什么该放在脚手架里,以及随着模型进步,什么该被移出。
本文分享三种模式,帮助团队构建能够跟上 Claude 智能演进的应用,同时平衡延迟和成本:
- 依赖模型已知的能力
- 持续追问「我可以停止做什么」
- 谨慎地用 harness 设置边界
模式一:依赖模型,而非 Harness——用 Claude 已知的能力¶
用 Claude 已经深度理解的通用工具来构建应用,而非为 agent 定制专用工具。
2024 年底,Claude 3.5 Sonnet 仅凭一个 bash 工具和一个文本编辑器工具就在 SWE-bench Verified 上达到 49%——当时的 SOTA。Claude Code 正是建立在这些同样的工具之上。Bash 并不是为构建 agent 而设计的,但它是 Claude 深度理解并且会随时间越用越好的工具。

我们观察到 Claude 将这些通用工具组合成不同的模式来解决各类问题。例如,Agent Skills、程序化工具调用和 memory 工具——全部由 bash 和文本编辑器组合而成。

模式二:持续精简 Harness——追问「我可以停止做什么」¶
Agent harness 编码了「Claude 做不到什么」的假设。随着 Claude 变强,这些假设需要被不断测试和移除。
Agent harness 编码的是关于 Claude 局限的假设。模型变强了,这些假设就该被挑战。
让 Claude 自己编排动作¶
一个常见假设是:每个工具调用的结果都应该流回 Claude 的上下文窗口来决定下一步。但把工具结果变成 token 来处理可能慢、贵、且没有必要——如果结果只需传给下一个工具,或者 Claude 只关心输出中的一小部分。
举个例子:读取一个大表格来推理其中某一列——整个表格进入上下文,Claude 为每一行不需要的数据付出 token 成本。当然可以在工具设计层面用硬编码过滤器来解决,但这没有触及核心问题——harness 在做一个 Claude 比它更擅长做的编排决策。

解决方案: 给 Claude 一个代码执行工具(如 bash 工具或语言专用 REPL),让它自己写代码来表达工具调用和调用之间的逻辑。这样 Claude 自己决定哪些结果需要透传、过滤或管道给下一个调用——只有代码执行的最终输出进入上下文窗口。

编排决策从 harness 转移到了模型。由于代码是 Claude 编排动作的通用方式,一个强编码模型也就是一个强通用 agent。Claude 用这种模式在非编码评测上也表现出色:在 BrowseComp(测试 agent 网页浏览能力的基准)上,让 Opus 4.6 自行过滤工具输出,准确率从 45.3% 提升到 61.6%。
让 Claude 管理自己的上下文¶
任务相关的上下文引导 Claude 对 bash 和文本编辑器等通用工具的使用。一个常见假设是系统 prompt 应该手工写好所有任务指令。问题在于:预加载大量指令不能扩展到多任务场景——每增加一个 token 都会消耗 Claude 的注意力预算,预加载很少用到的指令是浪费。
解决方案:Skills 机制。 每个 skill 的 YAML frontmatter 作为简短描述预加载到上下文中,提供 skill 内容的概览。完整内容由 Claude 在需要时通过 read file 工具按需加载——这就是渐进式披露(progressive disclosure)。

Skills 给了 Claude 自主组装上下文窗口的自由,而 context editing 是其反面——选择性地移除已过时或不相关的上下文(如旧的工具结果或 thinking blocks)。
通过 subagents,Claude 越来越擅长判断何时该 fork 到一个新的上下文窗口来隔离特定任务。Opus 4.6 使用 subagents 在 BrowseComp 上比最佳单 agent 方案提升了 2.8%。
让 Claude 持久化自己的上下文¶
长时间运行的 agent 可能超出单个上下文窗口的限制。一个常见假设是记忆系统需要依赖模型外部的检索基础设施。而我们大量工作的重心是给 Claude 简单的方式来自己决定持久化什么内容。
| 方法 | 机制 | 效果 |
|---|---|---|
| Compaction | Claude 总结过去的上下文以维持长任务的连续性 | Sonnet 4.5 无论预算多少都停在 43%;Opus 4.5 扩展到 68%;Opus 4.6 达到 84% |
| Memory Folder | Claude 将上下文写入文件,需要时读取 | Sonnet 4.5 在 BrowseComp-Plus 上从 60.4% 提升到 67.2% |

实例对比:长时间游戏任务(如 Pokemon)中的记忆使用
Sonnet 3.5 把记忆当流水账——记录 NPC 说了什么,而非什么重要。14,000 步后产生了 31 个文件(包括两个关于毛虫宝可梦的近似重复文件),但仍然停留在第二个城镇:
caterpie_weedle_info:
- Caterpie and Weedle are both caterpillar Pokemon.
- Caterpie is a caterpillar Pokemon that does not have poison.
- Weedle is a caterpillar Pokemon that does have poison.
- This information is crucial for future encounters and battles.
- If our Pokemon get poisoned, we should seek healing at a Pokemon
Center as soon as possible.
后代模型写的是战术笔记。Opus 4.6 在同样步数下只有 10 个文件(按目录组织),已获得三枚徽章,还有一个从自身失败中提炼的 learnings 文件:
/gameplay/learnings.md:
- Bellsprout Sleep+Wrap combo: KO FAST with BITE before Sleep
Powder lands. Don't let it set up!
- Gen 1 Bag Limit: 20 items max. Toss unneeded TMs before dungeons.
- Spin tile mazes: Different entry y-positions lead to DIFFERENT
destinations. Try ALL entries and chain through multiple pockets.
- B1F y=16 wall CONFIRMED SOLID at ALL x=9-28 (step 14557)
模式三:谨慎设置 Harness 边界¶
Harness 的核心价值在于执行 UX、成本和安全方面的约束——用声明式工具设置边界,用缓存策略控制成本。
设计上下文结构以最大化缓存命中¶
Messages API 是无状态的。Claude 看不到之前轮次的对话历史。这意味着 harness 需要在每一轮将新上下文与所有历史动作、工具描述和指令一起打包发送给 Claude。
通过设置断点可以缓存 prompt。具体来说,Claude API 将断点之前的上下文写入缓存,并检查是否与之前的缓存条目匹配。
由于缓存 token 的成本仅为基础输入 token 的 10%,最大化缓存命中率至关重要。以下是关键原则:
| 原则 | 说明 |
|---|---|
| 静态内容在前,动态内容在后 | 请求中稳定内容(系统 prompt、工具定义)放在前面 |
| 用 messages 做增量更新 | 在 messages 中追加 <system-reminder> 而不是修改 prompt 本身 |
| 不要切换模型 | 避免在会话期间切换模型。缓存是模型专属的,切换会使缓存失效。需要更便宜的模型时用 subagent |
| 谨慎管理工具定义 | 工具定义位于缓存前缀中。增删任何一个工具都会使缓存失效。动态发现场景用 tool search(追加而不破坏缓存) |
| 更新断点位置 | 多轮应用(如 agent)中将断点移到最新消息,保持缓存时效。使用 auto-caching 来自动处理 |
用声明式工具设置 UX、可观测性或安全边界¶
Claude 不一定知道应用的安全边界或 UX 界面。Claude 发出工具调用,由 harness 执行。Bash 工具给了 Claude 很大的操作自由度,但只给 harness 一个命令字符串——对所有动作都是同样的形状。将特定动作提升为独立工具(dedicated tools),能给 harness 提供带类型参数的 action-specific hook,可以拦截、门控、渲染或审计。

什么时候应该提升为独立工具:
| 场景 | 原因 | 示例 |
|---|---|---|
| 安全边界 | 不可逆操作需要门控 | 外部 API 调用通过用户确认来门控;edit 工具加入 staleness check 防止覆盖已变更的文件 |
| 用户展示 | 动作需要呈现给用户 | 渲染为 modal 向用户展示问题、提供多个选项、或阻塞 agent 循环等待用户反馈 |
| 可观测性 | 需要结构化日志 | 带类型的工具调用可以被记录、追踪和回放 |
持续重新评估: 是否需要独立工具应该不断被检验。例如 Claude Code 的 auto mode(发布时处于 research mode)提供了 bash 工具周围的安全边界:由第二个 Claude 读取命令字符串并判断是否安全。这种模式可以减少对独立工具的需求,但仅适用于用户信任整体方向的任务。对于某些高风险操作,独立工具仍有其存在价值。
Agent Harness 设计的未来¶
Claude 智能的前沿永远在变化。关于「Claude 做不到什么」的假设需要随每次能力跃升而被重新检验。
我们一再看到这种模式。在一个为长时间任务构建的 agent 中,Sonnet 4.5 会在感觉上下文限制接近时提前结束工作。我们添加了 context resets 来清理上下文窗口以解决这种「上下文焦虑」。但到了 Opus 4.5,这个行为消失了。我们当初为补偿而构建的 context resets 变成了 harness 中的死代码。
移除这些死代码很重要,因为它们会成为 Claude 性能的瓶颈。随时间推移,应用中的结构和边界应该基于这个问题来精简:「我可以停止做什么?」
要使用本文讨论的所有工具和模式,请查看 claude-api skill。
致谢¶
作者 Lance Martin,Anthropic Claude Platform 团队成员。感谢 Thariq Shihipar、Barry Zhang、Mike Lambert、David Hershey 和 Daliang Li 在相关主题上的讨论。感谢 Lydia Hallie、Lexi Ross、Katelyn Lesse、Andy Schumeister、Rebecca Hiscott、Jake Eaton、Pedram Navid 和 Molly Vorwerck 的编辑审阅和反馈。