在构建长周期、多步骤的自主 Agent(智能体)时,开发者面临的最大敌人往往不是模型不够聪明,而是上下文窗口的物理极限与 LLM 注意力的衰减。
当 Agent 运行数十步、调用大量工具后,历史记录((H_t))会迅速膨胀。如果不加干预,高昂的 API 成本、飙升的首字延迟(TTFT)以及“中间迷失(Lost in the Middle)”现象,会迅速拖垮整个系统。
作为 Agent Harness(执行框架)的设计工程师,我们必须将“上下文压缩”从简单的“文本摘要”提升到“状态估计(State Estimation)”的工程高度。本文将结合两张核心架构图,深入探讨如何设计一套高保真的压缩管线。
一、 理论基础:压缩即状态估计
在 Harness 架构中,我们需要建立一个核心认知:喂给 LLM 的上下文,不是历史记录的堆砌,而是对当前任务状态的一次精准“估计”与“投影”。
这个流程可以抽象为:
(H_t) (完整历史) (\rightarrow) (\mathcal{C}_B) (压缩器) (\rightarrow) (\hat{s}_t) (工作状态)
为了确保这个“状态估计”是有效的,Harness 的压缩策略必须满足三个工程底线:
- 行为保真度 (Behavioral fidelity):(p(A_{future} | H_t) \approx p(A_{future} | \hat{s}_t))。压缩后的状态必须能推导出与完整历史几乎一致的下一步动作。如果压缩导致 Agent 忘记目标或重复犯错,压缩就是失败的。
- 有界表示 (Bounded representation):(|\hat{s}_t| \le B)。压缩必须有硬性的 Token 预算上限,不能盲目依赖 LLM 的自动摘要,因为摘要长度不可控。
- 可恢复性 (Recoverability):有损压缩必然丢失细节。当 Agent 需要回溯细节时,Harness 必须提供外部证据的“指针(Pointer)”,让 Agent 能够按需检索(RAG)恢复。
二、 架构落地:模型可见上下文的分区设计
理论必须落地为具体的 Prompt 结构。在触发压缩时,Harness 不能把所有信息揉成一团,而应该将 Model-Visible Context(模型可见上下文)严格划分为四个区域,并执行不同的处理策略:
1. 🖤 锚点区 (Anchors) —— 必须逐字保留 (KEEP EXACT)
-
内容:
goal(全局目标)、constraints(硬性约束/安全规则)。 - 工程准则:绝对禁止任何形式的摘要改写。
- 落地实践:由 Harness 代码硬性截取最初的 System Prompt,无论压缩多少次,都必须原封不动地钉在上下文的最顶部。这是防止 Agent 发生“目标漂移”的定海神针。
2. ❤️ 检查点区 (Checkpoint) —— 结构化编码 (ENCODE)
-
内容:
decisions(已做的关键决策)、progress(当前进展)、IDs(文件路径、任务ID等)。 - 工程准则:丢弃冗余细节,提取结构化状态。
-
落地实践:这是压缩器 (\mathcal{C}_B) 发挥核心作用的地方。强制 LLM 输出 JSON 或 Markdown 列表(例如:
{"current_phase": "debugging", "decisions": ["改用异步重试"], "ids": ["api_client.py"]})。ID 和路径必须原样照抄,绝不能发生幻觉。
3. 💙 近期尾部 (Recent tail) —— 必须逐字保留 (KEEP EXACT)
-
内容:
active attempt(当前正在尝试的步骤)、fresh result(刚刚返回的最新结果/报错)。 - 工程准则:保留最近 N 轮的完整交互细节,不压缩,不摘要。
- 落地实践:实现滑动窗口(Sliding Window)。LLM 的下一步动作极度依赖刚刚发生的结果,此处丢失参数细节会导致逻辑断层。
4. 🔵 外置区 (Evidence Store) —— 提供指针 (EXTERNALIZE)
- 内容:海量日志、完整 JSON、大型网页源码。
- 工程准则:把海量数据写入外部存储,Context 中只保留指针。
-
落地实践:当工具返回 2.4 万行日志时,Harness 拦截并存入本地文件或对象存储。在上下文中只注入:
工具执行产生24k行日志,存放于 /tmp/evidence.log。提取到的关键报错为:xxxx。可使用 read_log 工具回溯。这完美实现了“可恢复性”。
三、 避坑指南:为什么不能纯靠 Prompt 让 LLM 自己压缩?
在轻量级框架中,很多开发者尝试一种“极简方案”:直接用 Prompt 告诉 LLM “请总结当前上下文,存入文件,然后开启新上下文读取该文件”。
实事求是地说,这种做法战术上可行,但在生产级 Harness 中是灾难。 它存在四个致命漏洞:
- 不可控的输出:LLM 没有 Token 预算的硬约束概念,它可能写出 5000 字的废话,导致新开的上下文瞬间又被撑爆。
- 信息幻觉与丢失:LLM 在总结时,极大概率会丢失精确的锚点(如具体的变量名、API Key),甚至“脑补”出错误的进展。一旦错误写进文件,后续执行全盘塌方。
- 代际遗忘(Generation Loss):如果是多轮压缩(总结的总结),最后只会剩下干瘪的套话,任务细节全部丢失。
- 执行脆弱性:新开上下文后,LLM 读取文件时可能因为文件太大而截断,导致读不到最关键的部分。
四、 最佳实践:硬约束 + 软摘要的混合架构
真正的 Harness 设计,应该是“Harness 掌握控制权,LLM 负责语义提炼”。
1. Harness 负责“硬性管控”(Deterministic Guardrails)
- Token 预算监控:实时计算 Token,达到阈值(如 70%)强制触发压缩。
- 执行结果拦截:工具返回超大结果时,直接在 Harness 层截断或外置,不消耗 LLM 的脑力。
-
锚点注入:由代码将
Goal和Constraints强行拼接到新 Context 头部。
2. Prompt 负责“软性提炼”(Semantic Encoding)
在 Harness 硬约束的框架下,让 LLM 做它最擅长的事:提炼决策和进度。提供严格的结构化指令,例如:
“请阅读以下历史记录,生成一份 JSON 格式的检查点。必须包含 decisions(决策)、progress(进展)、ids(涉及的ID,必须原样照抄)。总字数严格控制在 500 Token 以内。”
3. 外部文件作为“证据库”(RAG 基础)
- 完整的 (H_t) 存入向量数据库或本地文件。
- 新的 Context 只保留
Checkpoint + 指针。 - 当 Agent 需要细节时,Harness 拦截意图,自动检索相关片段并注入回上下文。
结语
对于 Agent Harness 开发者而言,压缩策略不是“锦上添花”,而是决定 Agent 能否在长周期任务中存活的命门。
不要让 LLM 决定什么时候压缩、压缩多少。Harness 必须决定“何时压、压多大、哪些绝对不能丢”,而 LLM 只负责“把这一坨文本浓缩成结构化的状态”。通过分级分区(锚点、检查点、近期尾部、外置证据)的架构设计,我们才能在有限的 Token 预算下,让 Agent 既记得“从哪里来,要干什么”,也知道“现在在哪,下一步该怎么走”。