什么是 Agent 的上下文窗口?为什么它是 Agent 工程中最核心的约束?
参考答案
上下文窗口(Context Window)就是大模型一次能处理的文本长度上限,用 token 数来衡量。主流旗舰模型一般在 128K~200K token 之间。对 Agent 来说,窗口里需要塞的东西特别多:系统提示词、工具定义、对话历史、工具调用结果、中间推理过程,全都挤在这一个有限空间里。
它是 Agent 工程最核心约束的原因有三个:
1)Agent 是多轮执行的,每一轮循环都产生新内容:思考过程、工具调用、返回结果,不断累积。一个复杂任务跑个 20-30 轮循环,上下文轻松膨胀到几十万 token,很快撞到天花板
2)窗口大不等于好用。研究表明模型在超长上下文中注意力会衰减,中间部分的信息容易被忽略,这就是**“Lost in the Middle”**问题。塞了 10 万 token 进去,模型可能只对头尾各 1-2 万 token 敏感
3)上下文长度直接决定成本和延迟。token 越多 API 费用越高、推理越慢。一个不做上下文管理的 Agent 跑个复杂任务,一次对话花掉 5-10 美元 API 费用很常见,响应时间也从几秒拉到几十秒
扩展知识
上下文膨胀的真实案例
拿 Cursor Agent 举例。你让它重构一个项目,它需要读文件、改代码、跑测试、看报错、再改,每一轮循环都会把文件内容、diff、测试输出塞进上下文。一个 2000 行的文件读进去就是大几千 token,跑 10 轮循环就可能用掉 5-8 万 token。
如果不做管理,到后面几轮模型开始”忘记”前面的修改意图,产出质量断崖式下降。
Claude Code 和 Cursor 在实现上都做了积极的上下文管理:自动压缩早期对话、对大文件只读取相关片段、工具返回结果做截断。
工程上的应对策略
对话历史压缩是最基础的策略。把较早的对话轮次用摘要替代,比如前 10 轮对话压缩成一段 500 token 的总结,保留关键决策和结论,丢掉中间的试错过程。Claude Code 的 /compact 命令就是干这个的。
工具结果截断也很关键。一次数据库查询可能返回几千行数据,全塞进上下文既浪费 token 又干扰模型注意力。实践中一般只保留前 50-100 行,或者让模型自己指定只要哪些字段。
动态工具加载是另一个重要手段。如果 Agent 接入了 50 个工具,光工具描述就占 1-2 万 token。解决办法是根据当前任务上下文只加载相关的 5-10 个工具,用不到的不塞进去。
滑动窗口与分层记忆
滑动窗口机制就是只保留最近 N 轮的完整对话,更早的逐步丢弃或压缩。这个做法简单有效,但有个明显缺陷:如果用户在第 3 轮提了个关键需求,到第 20 轮时可能已经被滑出去了。
分层记忆是更高级的方案:把重要信息写入外部存储,比如向量数据库或文件系统,需要的时候通过检索拉回来。这样上下文窗口里只保留当前任务最相关的信息,历史知识按需召回。
Claude 的 memory 文件、Cursor 的 .cursorrules 本质上都是这种思路的体现。
为什么不能无脑等模型窗口变大
有人会问,模型窗口不是越来越大吗?等它到 1000 万 token 是不是就不用管了?答案是不行:
1)成本跟 token 数线性甚至超线性增长,100 万 token 的推理费用可能是 10 万 token 的 15-20 倍
2)延迟随 token 数增加,首 token 延迟从几百毫秒涨到几秒甚至十几秒
3)Lost in the Middle 问题并没有随着窗口变大而消失,模型对中间内容的注意力依然明显弱于首尾
所以上下文管理不是临时方案,是 Agent 工程的长期核心能力。
面试官追问
提问:实际项目中怎么监控 Agent 的上下文使用情况?到了上限怎么办?
回答:一般在 Client 层做 token 计数,每轮循环前算一下当前已用量。接近阈值时触发压缩:先压缩最早的几轮对话为摘要,如果还不够就截断工具返回结果。如果压缩完还是超了,就得结束当前会话、把关键上下文持久化到文件,开一个新会话继续。Cursor 和 Claude Code 都有类似的自动 compact 逻辑。
提问:Lost in the Middle 问题有没有什么工程上的缓解办法?
回答:最直接的办法是把最重要的信息放在上下文的开头和结尾。系统提示词放开头,当前轮次的关键信息放末尾,中间放不太重要的历史。还有一种做法是在关键信息旁边加显式标记,比如”[重要] 用户的核心需求是 xxx”,用文本标记来引导模型注意力。不过这些都是经验性的 trick,从根本上解决还是得靠模型架构改进。
提问:工具定义太多占 token 怎么优化?除了动态加载还有别的办法吗?
回答:还有几个思路。一是精简工具描述,很多工具的 description 写得太啰嗦,压缩到关键信息就够了,能省 30-50% 的 token。二是工具分组,把相关工具合并成一个”超级工具”,通过参数区分子功能,比如把”查用户””改用户””删用户”合成一个”用户管理”工具。三是用两阶段调用,第一阶段只给模型工具名称列表,模型选完再加载完整定义,避免一次性塞入所有 schema。