第二章 Harness Engineering 进阶
Harness Engineering 让 Agent 从玩具变生产力。但只要你真的把 Agent 跑起来,不出两小时就会撞上同一堵墙——上下文爆了。这篇深入讲一个被严重低估的核心技术:Context Compaction(上下文压缩)。
一、为什么长任务一定会撞墙?
做过 Agent 工程的人都知道这个现象:
•
前 30 分钟,Agent 思路清晰、工具调用精准
•
1 小时后,开始重复之前做过的事
•
2 小时后,忘了任务目标
•
3 小时后,在一个循环里出不来,token 烧完
这不是模型能力问题,是上下文管理问题。
😀
Claude Opus 4.7 支持 200K 上下文,但实际跑 Agent 时,有效工作窗口大概只有60K-80K。一旦超过这个数,模型的注意力就开始显著分散——Lost in the Middle 现象。所以 Agent 长任务的真正瓶颈,不是"上下文窗口多大",而是——你能把多少有效信息,持续压在有效窗口内。
二、Context Compaction 是什么?
一句话定义:在 Agent 运行过程中,定期把历史上下文"压缩"成更短但信息密度更高的表示,替换掉原始历史。
类比一下:
•
没压缩的 Agent:像一个学生做完 100 道题,每道题都把整张草稿纸留着
•
有压缩的 Agent:每做完 10 道题,把草稿整理成一页笔记,再扔掉草稿
•
效果差距:前者 30 道题就没地方写了;后者 300 道题依然从容。
三、三种主流压缩策略
滑动窗口 + 摘要(Sliding + Summarize)
最简单的策略:保留最近 N 轮对话原文更早的对话,每 M 轮压缩成一段摘要摘要替换原文,腾出上下文空间
代码块
JSON
def compact_context(history, keep_recent=10, compact_every=20):
recent = history[-keep_recent:]
old = history[:-keep_recent]
summaries = []
for i in range(0, len(old), compact_every):
chunk = old[i:i+compact_every]
summary = llm.summarize(chunk, focus="key decisions and outcomes")
summaries.append(summary)
return summaries + recent
适用场景:对话型 Agent、客服、简单工作流
局限:摘要会丢失细节,对需要精确引用历史决策的任务不适合
分层记忆(Hierarchical Memory)
复杂一点但效果更好:把上下文分成三层,每层压缩粒度不同:
#QTTyrBhJevDi text { white-space: pre; }#QTTyrBhJevDi .fb0 { stroke: var(--N900-FG, 0.15); }#QTTyrBhJevDi .fb0 {stroke: rgba(31,35,41, 0.15)}#QTTyrBhJevDi .fx0 { stroke-miterlimit: 10; }#QTTyrBhJevDi .fx0 {stroke-miterlimit: 10}#QTTyrBhJevDi .fa1 { fill: rgb(187, 191, 196); }#QTTyrBhJevDi .fa1 {fill: rgb(187, 191, 196)}#QTTyrBhJevDi .fx1 { font: 400 12px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#QTTyrBhJevDi .fx1 {font-style: normal}#QTTyrBhJevDi .fx2 { text-anchor: middle; }#QTTyrBhJevDi .fx2 {text-anchor: middle}#QTTyrBhJevDi .fx3 { dominant-baseline: central; }#QTTyrBhJevDi .fx3 {dominant-baseline: central}#QTTyrBhJevDi .fx4 { stroke: none; }#QTTyrBhJevDi .fx4 {stroke: none}#QTTyrBhJevDi .fc0 { fill: var(--text-caption); }#QTTyrBhJevDi .fc0 {fill: #646a73}#QTTyrBhJevDi .fa2 { fill: var(--text-link-disabled); }#QTTyrBhJevDi .fa2 {fill: rgb(187, 191, 196)}#QTTyrBhJevDi .fa3 { fill: rgb(247, 247, 247); }#QTTyrBhJevDi .fa3 {fill: rgb(247, 247, 247)}#QTTyrBhJevDi .fx5 { font: 400 16px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#QTTyrBhJevDi .fx5 {font-style: normal}#QTTyrBhJevDi .fx6 { text-anchor: start; }#QTTyrBhJevDi .fx6 {text-anchor: start}#QTTyrBhJevDi .fx7 { dominant-baseline: alphabetic; }#QTTyrBhJevDi .fx7 {dominant-baseline: alphabetic}#QTTyrBhJevDi .fc1 { fill: rgba(0, 0, 0, 0.9); }#QTTyrBhJevDi .fc1 {fill: rgba(0, 0, 0, 0.9)}#QTTyrBhJevDi .fb1 { fill: var(--N900-FG, 0.15); }#QTTyrBhJevDi .fb1 {fill: rgba(31,35,41, 0.15)}#QTTyrBhJevDi .fb2 { fill: rgb(187, 187, 187); }#QTTyrBhJevDi .fb2 {fill: rgb(187, 187, 187)}#QTTyrBhJevDi .fb3 { fill: rgb(221, 221, 221); }#QTTyrBhJevDi .fb3 {fill: rgb(221, 221, 221)}#QTTyrBhJevDi .fa4 { fill: var(--bg-body); }#QTTyrBhJevDi .fa4 {fill: #fff}ABC1234层级工作记忆(Working)短期记忆(Short-term)长期记忆(Long-term)内容最近 5-10 步最近 1 小时任务启动后全部压缩粒度原文保留摘要化,中等颗粒结构化存储(关键决策、已完成步骤、失败尝试)
Agent 每次推理时,按需从不同层级召回信息,而不是塞入全部历史。
关键设计:长期记忆通常存成结构化 JSON,而不是自然语言,这样召回时可以精确定位。
代码块
Plain Text
检索式压缩(Retrieval-Based Compaction)
最高级的策略:把所有历史步骤存到向量数据库,每次推理前根据当前任务状态检索最相关的 K 条历史。
流程:Agent 每完成一步,把这步的 (action, observation, reflection) 写入向量库
下一步推理前,根据"当前目标 + 最近操作"做 embedding
检索只把 top-K 相关历史塞进上下文
优势:上下文窗口利用率极高,几乎可以跑无限长的任务
代价:工程复杂度高、检索质量依赖 embedding 模型
四、Claude Opus 4.7 的原生支持
Opus 4.7 这次有两个新特性是专门为长任务设计的,值得重点用起来:
Task Budget(任务预算)
代码块
JSON
response = client.messages.create(
model="claude-opus-4-7",
task_budget={"total_tokens":
500_000},messages=[...])
模型会看到"剩余预算倒计时",主动规划工作节奏。组合技:Task Budget + Context Compaction。预算告诉模型"总共还有多少 token 可用",压缩告诉模型"历史已经整理过,可以安全丢弃"。两个机制一起上,Agent 能自主规划长任务的节奏。
文件系统记忆增强
Opus 4.7 明显加强了基于文件的笔记能力。实战中推荐的模式:workspace/├── task.md
代码块
JSON
workspace/├── task.md
任务目标,只读
├── progress.md
Agent 自己维护的进度日志
├── decisions.md
关键决策记录
├── failed_attempts.md
踩过的坑
└── current_plan.md
五、几个容易踩的坑
坑1:摘要模型选太便宜
•
很多人用 Haiku 做摘要省钱,结果摘要丢了关键信息。
•
建议摘要用 Sonnet 级别以上模型,省一点钱带来的质量损失不划算。
坑2:压缩频率过高
•
每 3-5 步就压缩一次,会让模型看不到完整推理链。
•
建议 10-15 步压一次。
坑3:忘了保留失败记录
•
摘要时只记录"做了什么",不记录"什么尝试失败了"——结果 Agent反复走同一个坑。
•
failed_attempts.md 是必备文件。
坑4:不做回归评估
•
压缩后的 Agent 是否和无压缩一样聪明?必须做对比评估。
•
建议准备一组 benchmark 任务,定期跑"有压缩 vs 无压缩"的对比。
六、写在最后
Harness Engineering 的核心思想只有一句话:让模型在工程约束下稳定发挥。
Context Compaction 是这个思想最重要的实践之一。它决定了你的 Agent 是一个跑 30 分钟就崩的演示,还是一个跑 8 小时稳定输出的生产系统。
😀
2026 年做 AI 产品,模型能力的差距已经没那么大了——真正拉开差距的是工程侧:谁能把上下文管理好,谁能把失败恢复设计好,谁能把观测和回滚做稳,Context Compaction 是这一组能力中最值得先掌握的。