引言:Agent 的"肥胖症"
当你让 AI Agent 执行一个看似简单的任务——比如"分析这份季度财报并生成投资摘要"——你可能不会意识到,它正在以指数级的速度"发胖"。每多一轮对话,每多一次工具调用,上下文窗口就像被吹胀的气球,Token 消耗从几千飙升到几万、几十万。
这不是夸张。根据 JetBrains Research 2025 年的实证研究,Agent 上下文增长遵循一个残酷的规律:上下文膨胀速度远超任务完成速度,导致"昂贵的噪声"——大量 Token 被消耗,但对任务结果几乎毫无贡献。
图二展示的三条曲线,正是这场"Agent 肥胖症"的三种病程:
- Baseline(橙色):不裁剪自然增长,Token 累积呈指数级爆炸
- 策略一(紫色):减缓增长斜率,从源头控制输入
- 策略二(蓝色):过程裁剪(Self-GC),锯齿波式优雅循环
- 策略三(黄色):激进 Compact,高频次断崖式压缩
本文将系统拆解这三种策略的工程原理、适用场景与取舍逻辑,为 Agent 系统的成本治理提供一份可落地的决策框架。
一、Baseline:不裁剪的自然增长——一场无声的破产
1.1 为什么上下文会"自然发胖"?
Agent 的工作机制决定了它的"易胖体质":
多轮工具调用的累积效应。每次调用外部工具(如搜索、代码执行、数据库查询),返回值都会被完整填入历史记录。一段 5000 Token 的 JSON 日志、一张 2000 Token 的网页摘要、一次 3000 Token 的错误堆栈——这些"一次性"内容永久驻留在上下文中,即使它们的价值在下一回合就衰减为零。
System Prompt 与工具定义的"死重"。每次请求都会重复发送完整的系统指令(可能长达数千 Token)和工具定义(每个工具包含名称、描述、参数 schema)。当 Agent 调用 20 个工具时,仅工具定义就占据上万 Token——而这些信息在每一轮都完全相同。
自注意力机制的二次方诅咒。Transformer 的计算复杂度与序列长度呈 O(n²) 关系。10K Token 需要约 1 亿次注意力计算,50K Token 就是约 25 亿次。这意味着:上下文膨胀不仅增加成本,还降低推理速度,形成"越胖越慢、越慢越贵"的恶性循环。
1.2 成本账:一个数字的震撼
以 Claude Sonnet 4 的定价为例(假设 2026 年标准定价):
| 场景 | 轮数 | 平均上下文 | 单轮成本 | 累计成本 |
|---|---|---|---|---|
| 轻量问答 | 10 | 8K | \(0.024 |\)0.24 | |
| 代码调试 | 20 | 25K | \(0.075 |\)1.50 | |
| 深度研究 | 50 | 80K | \(0.24 |\)12.00 | |
| 长期项目 | 100 | 200K | \(0.60 |\)60.00 |
但这只是未启用缓存的"裸奔"成本。如果缓存命中(Cache Read),成本可降低 90%。然而,大多数 Agent 框架并未设计缓存友好的前缀结构,导致大量重复计算。
JetBrains Research 的实验显示:在 SWE-bench Verified 上,不加管理的 Agent 上下文平均消耗是优化后的 2.1 倍,而任务成功率反而更低——因为"Context Rot"(上下文腐蚀)让模型在长序列中迷失焦点。
核心结论:Baseline 不是"免费选项",而是"最昂贵的默认配置"。
二、策略一:降低增长斜率——源头治理的工程学
2.1 核心思想:让输入"瘦身",而非事后"抽脂"
策略一的核心是几乎无损的工程优化,目标是在信息进入上下文之前,就过滤掉冗余和噪声。这如同在餐桌上控制饮食,而非餐后催吐——更健康、更可持续。
图二中,紫色曲线的斜率明显低于橙色 Baseline,且呈线性增长而非指数增长。这得益于三个工程实践:
2.2 实践一:Skill 接口的"反原子化"
许多 Agent 框架将工具设计得过度原子化——每个工具只做一件事,导致 Agent 需要连续调用 10 个工具才能完成一个复合任务。每次调用都会生成工具调用记录和返回值,这些历史记录永久堆积。
优化原则:
- 批量操作优于单次操作:设计一个
batch_search代替 10 次search - 复合查询优于链式查询:
analyze_and_summarize代替fetch→parse→summarize的三轮调用 - 延迟执行优于急迫执行:让 Agent 先规划全部所需信息,再一次性批量获取
2.3 实践二:API Payload 的结构化过滤
工具返回的原始数据往往包含大量调试级 metadata、冗余字段、格式噪音。例如,一个 API 返回的 JSON 可能包含 _version、timestamp、request_id 等字段,这些对 Agent 推理毫无价值,却占据大量 Token。
优化策略:
- Schema 白名单:定义工具返回值的必要字段,过滤无关字段
- 自动摘要接入点:在工具层(而非 Agent 层)对长返回值进行预摘要
- 数值精简:将浮点数精度截断到合理位数,数组截断到合理长度
2.4 实践三:Prompt Cache 友好设计
Prompt Cache 是降低成本的核武器——Claude 的 Cache Read 价格比标准输入便宜 10 倍(\(0.30 vs\)3.00 per MTok)。但缓存的前提是:前缀必须字节级完全相同。
常见错误:
# ❌ 错误:每次时间戳变化,导致缓存永久失效
system_prompt = f"Current time: {datetime.now()}\nYou are a coding assistant..."
正确做法:
# ✅ 正确:稳定前缀 + 后置变化
system_prompt = "You are a coding assistant...\n---\nCurrent time: {datetime.now()}"
关键原则:
- 变化内容后置(时间戳、动态状态)
- JSON 序列化必须确定性(key 顺序固定)
- 只能追加,不能修改前缀
2.5 策略一的效果评估
根据 Shannon Lab 的实测数据,策略一可减少 30-50% 的无效 Token 输入,且几乎零信息损失。这是所有 Agent 系统必须首先实施的基础工程——它不需要算法创新,只需要工程纪律。
三、策略二:过程裁剪(Self-GC)——优雅的锯齿波
3.1 核心思想:在运行时做"垃圾回收"
策略二(蓝色曲线)呈现独特的锯齿波形态:Token 累积到一定阈值后,突然下降,然后重新开始线性增长。这对应一个周期性清理机制——在任务运行中识别并移除"垃圾信息",同时保留恢复指针。
图二的注释说明:"优选正常循环"——这暗示了策略二追求的是一种可控的、可持续的循环模式,而非一次性的断崖式压缩。
3.2 Self-GC 的运作机制
Self-GC(Self-Garbage Collection)的概念源于编程语言的垃圾回收机制,但应用于 Agent 上下文管理。其核心流程:
识别阶段:标记哪些历史信息是"垃圾"
- 已 Resolved 的中间状态("问题已修复,无需保留调试过程")
- 重复的工具调用结果(多次获取相同数据)
- 过期的试探性步骤(错误路径的尝试)
- 过程噪声(临时变量、中间推导、确认性寒暄)
清理阶段:移除标记内容,但保留"墓碑信息"
- 不直接删除历史,而是替换为占位符(如
[Observation-3 removed: issue resolved]) - 保留关键决策记录和最终结论
- 通过外存(Sidecar)保留完整恢复指针
恢复阶段:当需要追溯时,从 Sidecar 加载原始信息
- Sidecar 是上下文外的独立存储(如文件、数据库、向量记忆)
- 恢复指针是一段元数据,告诉 Agent"某段信息已被归档,可在此恢复"
- 仅在需要时才触发完整加载,避免常驻上下文
3.3 "可控有损"的哲学
策略二的关键设计哲学是**"可控有损"**——承认完全无损是不可能的,但损失是可控的:
| 信息类型 | 处理方式 | 损失程度 |
|---|---|---|
| 最终决策与结论 | 永久保留 | 零损失 |
| 关键错误信息 | 保留摘要 | 轻微损失 |
| 已解决的中间步骤 | 替换为占位符 | 中等损失(可恢复) |
| 重复/冗余数据 | 完全删除 | 高损失(无价值) |
| 临时推导过程 | 归档到 Sidecar | 可选恢复 |
3.4 与 JetBrains Research 的"Observation Masking"不谋而合
2025 年 NeurIPS 的实证研究(JetBrains Research)揭示了一个惊人的发现:简单的"观察掩码"(Observation Masking)——用占位符替换旧的工具输出——在大多数场景下比 LLM 摘要更便宜且更有效。
数据显示:在 Qwen3-Coder 480B 上,Observation Masking 不仅降低了 52% 的成本,还提升了 2.6% 的任务成功率。原因是 LLM 摘要会"平滑掉"错误信号,导致 Agent 在应该停止时继续消耗 Token。
这验证了策略二的核心假设:保留关键信号 + 清理冗余噪声,优于试图用摘要压缩一切。
3.5 Sidecar 模式:Agent 的"外脑"架构
Sidecar 是策略二的基础设施支撑。它的设计原则:
- 分离存储:Sidecar 数据不参与 LLM 上下文,不消耗 Token
- 按需加载:仅当 Agent 明确需要追溯时才加载
- 结构化索引:为归档内容建立快速索引(如问题 ID、文件名、时间戳)
- TTL 机制:自动清理过期归档,防止 Sidecar 本身无限膨胀
一个具体的 Sidecar 实现示例:
class SidecarMemory:
def archive(self, turn_id: str, content: str, reason: str):
"""将历史内容归档到 Sidecar"""
self.store[turn_id] = {
"content": content,
"reason": reason,
"timestamp": time.time(),
"summary": self.generate_summary(content) # 保留简短摘要
}
def recover(self, turn_id: str) -> Optional[str]:
"""按需恢复原始内容"""
return self.store.get(turn_id, {}).get("content")
四、策略三:激进 Compact——高频次断崖式压缩
4.1 核心思想:用"摘要"换"空间"
策略三(黄色曲线)呈现剧烈的锯齿状:Token 累积到阈值后,断崖式下跌到接近原点,然后重新开始。这对应高频次的 Compaction(压实)——用 LLM 将大量历史消息压缩为精炼摘要,然后用摘要替代原始内容。
Compaction 的核心操作:
async def compact_context(messages: list, target_tokens: int = 400) -> str:
prompt = f"""Compress this conversation into a factual summary.
Focus on:
- Key decisions made
- Important discoveries
- Unresolved questions
- Named entities and their relationships
Keep the summary under {target_tokens} tokens.
Use the SAME LANGUAGE as the conversation.
"""
return await llm.generate(prompt, max_tokens=target_tokens, temperature=0.2)
4.2 适用场景:Coding Agent 的"天堂"
策略三对某些场景极度有效,特别是代码类 Agent(Coding Agent):
- Git diff 提供物理恢复:如果摘要丢失了某段代码细节,可以通过 Git 历史完整恢复
- 编译器/测试作为验证:摘要声称"修复了空指针异常",编译器可以快速验证
- 代码结构可推导:从摘要中的高层描述,可以重构具体实现
这意味着:在 Coding 场景,Compaction 的"信息损失"是可逆的——因为原始信息存在于版本控制和可执行验证中。
4.3 白领场景的"陷阱"
然而,策略三对白领场景(文档处理、数据分析、商业决策)可能是危险的:
| 场景 | 风险 | 原因 |
|---|---|---|
| 证据链 | 永久失真 | URL、Row Value、引用来源被揉成摘要后,无法追溯原始证据 |
| 合规审计 | 不可接受 | 审计要求保留完整操作记录,摘要不满足合规要求 |
| 复杂决策 | 丢失脉络 | "为什么选择方案 A"的推理过程被压缩后,无法复盘决策依据 |
| 多轮协商 | 丢失条件 | 谈判中的条件让步、时间点、承诺细节在摘要中模糊化 |
图二的注释明确警告:"白领场景的证据(URL、Row Value)一旦被揉成摘要,就会永久失真。"
4.4 触发阈值的设计艺术
Compaction 的触发时机是一门艺术:
- 太早触发:频繁压缩消耗额外 LLM 调用,且打断连贯性
- 太晚触发:上下文已过度膨胀,模型注意力已分散
- Shannon 的经验法则:预算使用率达 75% 时触发,目标压到 37.5%
示例配置:
compaction_config = {
"trigger_token_count": 50000, # 50K 触发
"target_ratio": 0.5, # 压缩到 50%
"min_turns_before_compact": 5, # 至少 5 轮
"preserve_last_n_turns": 3 # 保留最近 3 轮不压缩
}
五、三策略对比:如何为你的 Agent 选型?
5.1 决策矩阵
| 维度 | 策略一(降低斜率) | 策略二(Self-GC) | 策略三(激进 Compact) |
|---|---|---|---|
| 信息损失 | 几乎无损 | 可控有损 | 高频有损 |
| 实施难度 | 低(工程优化) | 中(需运行时管理) | 中(需 LLM 调用) |
| 成本节省 | 30-50% | 50-70% | 70-90% |
| 适用场景 | 所有 Agent | 多轮对话、工具调用 | 代码、可验证场景 |
| 风险 | 无 | 需恢复指针 | 不可逆信息丢失 |
| 维护负担 | 低 | 中 | 中 |
5.2 组合策略:三层防御体系
生产环境中,最佳实践是三层防御的组合:
第一层:策略一(源头治理)
- 设计阶段优化 Skill 接口,减少原子化调用
- 实现 API Payload 过滤,剔除冗余字段
- 优化 Prompt Cache 结构,确保高命中率
- 目标:减少 30% 的无效输入
第二层:策略二(运行时裁剪)
- 定期清理已 Resolved 的中间状态
- 用占位符替换旧工具输出(Observation Masking)
- 通过 Sidecar 归档历史,保留恢复指针
- 目标:进一步减少 40% 的上下文膨胀
第三层:策略三(压实保底)
- 当第二层仍无法抑制增长时,触发 Compaction
- 保留最近 N 轮完整记录,仅压缩老旧历史
- 在 Coding 场景可激进,在白领场景需保守
- 目标:将上下文维持在安全水位
5.3 场景化推荐
| 场景类型 | 推荐策略 | 理由 |
|---|---|---|
| 代码生成/调试 | 三策略全开 | Git 提供恢复能力,可承受高频 Compact |
| 客服/对话 | 策略一 + 策略二 | 对话历史不可丢,需保留恢复路径 |
| 数据分析 | 策略一 + 策略二(保守) | 原始数据是证据,不可被摘要替代 |
| 研究/写作 | 策略一 + 策略三(低频) | 可接受适度压缩,但需保留引用来源 |
| 自动化运维 | 三策略全开 | 工具输出可验证,日志可外查 |
六、前沿研究:2025-2026 的关键进展
6.1 SWE-Pruner:自适应上下文裁剪
2026 年 1 月的论文《SWE-Pruner: Self-Adaptive Context Pruning for Coding Agents》提出了一种训练轻量级神经网络(0.6B 参数)进行任务感知裁剪的方法。其创新点:
- 将当前任务目标(如"聚焦错误处理")作为裁剪提示
- 动态选择相关代码行,而非固定阈值裁剪
- 在 SWE-Bench Verified 上实现 23-54% 的 Token 减少,同时提升成功率
6.2 ACON:失败驱动的压缩优化
ACON(Optimizing Context Compression for Long-horizon LLM Agents)框架通过分析"哪些压缩导致失败"来迭代优化压缩提示,实现:
- 26-54% 的峰值 Token 使用降低
- 95%+ 的任务准确率保持
- 无需梯度训练,兼容闭源模型
6.3 DMF:确定性记忆框架
DMF(Deterministic Memory Framework)用完全确定性的管道替代 LLM 摘要,基于经典 NLP 分析和向量几何计算"生存分数"(Survival Score),实现:
- 零 Token 记忆准备成本
- 5x-242x 的 Token 节省(相比 Mem0)
- 完全确定性,消除摘要的不确定性
6.4 Anthropic 的 Compaction API
Anthropic 在 2026 年 1 月推出的 compact-2026-01-12 beta 功能,将 Compaction 自动化:
- 当输入超过阈值时自动触发
- 生成 Compaction Block 插入对话
- 对应用层透明,无需修改代码
- 支持 Claude API、AWS Bedrock、Google Vertex AI、Microsoft Foundry
七、实施路线图:从 Baseline 到三策略
7.1 第一阶段:诊断(1-2 天)
- 测量当前成本:统计 Agent 的平均轮数、每轮 Token 消耗、Cache 命中率
- 识别最大浪费源:哪些工具调用最频繁?哪些返回值最冗长?
- 评估 Context Rot:在长对话中,模型是否出现"遗忘早期需求"的现象?
7.2 第二阶段:策略一实施(1 周)
- 重构工具接口:合并原子化工具,减少调用次数
- 实现 Payload 过滤:为每个工具定义返回值白名单
- 优化 Cache 结构:确保 system prompt、工具定义稳定前缀化
- 效果验证:对比优化前后的 Token 消耗和任务成功率
7.3 第三阶段:策略二实施(2 周)
- 设计垃圾识别规则:定义哪些历史可以被标记为"垃圾"
- 实现 Sidecar 存储:选择存储方案(文件系统、数据库、向量存储)
- 实现占位符替换:将旧工具输出替换为摘要占位符
- 恢复机制测试:验证从 Sidecar 恢复原始信息的完整性和延迟
7.4 第四阶段:策略三实施(可选,1 周)
- 定义压缩策略:哪些内容可压缩?保留哪些不可压缩?
- 设计触发机制:基于 Token 阈值或轮数阈值
- 实现三段式保留:保留开头(Primers)+ 摘要(Summary)+ 最近(Recents)
- 质量回测:对比压缩前后的任务成功率,确保无显著退化
八、结语:Agent 的"身材管理"
Agent 的上下文管理,本质上是一场**"身材管理"**:
- Baseline 是放任自流:无限增长,直到"胖死"(超限或破产)
- 策略一是健康饮食:控制输入,减少热量摄入
- 策略二是规律运动:定期清理,保持代谢循环
- 策略三是间歇断食:高强度压缩,快速降低体重
没有一种策略是万能的。最佳实践是组合使用:用策略一减少输入,用策略二管理运行时,用策略三作为最后的保底。如同健身需要饮食 + 运动 + 休息的协同,Agent 的成本治理也需要三策略的层叠防御。
最终目标是:让 Agent 以最小的高信号 Token 集合,最大化任务成功的可能性。这不仅关乎成本,更关乎 Agent 能否在复杂任务中保持清醒、聚焦和高效。
记住:上下文不是越大越好。正如 Chroma 的研究揭示的——Context Rot 会让信息检索效率随长度递减。Agent 的智慧不在于"记得多",而在于"记得准"。
参考论文与资源
- SWE-Pruner (2026.01) - Self-Adaptive Context Pruning for Coding Agents, arXiv:2601.16746
- ACON (2026 ICLR) - Optimizing Context Compression for Long-horizon LLM Agents
- DMF (2026.06) - Deterministic Memory Framework for Conversational AI Agents, arXiv:2606.03463
- JetBrains Research (2025.12) - Smarter Context Management for LLM-Powered Agents
- Shannon Lab (2026) - Context Engineering 四策略框架 (Write/Select/Compress/Isolate)
- Anthropic (2026.01) - Compaction API beta (
compact-2026-01-12) - Context-Preserving Token Pruning (2026.05) - ContextGuard for Omni-LLMs, arXiv:2605.11605
- TACO (2026.05) - Self-Evolving Framework for Terminal Agents via Observational Context Compression, arXiv:2604.19572
标签: #Agent #上下文工程 #Token成本 #ContextEngineering #AI优化 #小凯
讨论回复
1 条回复推荐
智谱 GLM-5 已上线
我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。