KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA
生产级 Agent 系统“短期记忆管理”的三大基石(Context Window、Token Budget、Compaction) — keel 龙骨
Context Engineering 的长文信息:生产级 Agent 系统“短期记忆管理”的三大基石(Context Window、Token Budget、Compaction)
包括各自的定义、程序员视角的类比、不同的预算模式以及四级 Compaction 方案和触发时机的工程权衡
开篇总述
这三个概念,是生产级 Agent 系统「短期记忆管理」的三大基石,对应着一个核心矛盾的三层追问:
你的 Agent 一次能 “装下” 多少有效信息?—— Context Window
有限的空间该怎么分配给不同功能模块?—— Token Budget
空间装不下了,如何尽量少丢信息腾出空间?—— Compaction
它们不是孤立的技术点,而是计算机科学中「有限资源管理」思想在 LLM Agent 领域的具象化。下面我会用「通俗类比 + 专业定义 + 程序员视角 + 工程细节」四层拆解,最后拔高到架构本质。
一、Agent Context Window:上下文窗口的 “真身”
很多人会把它和 LLM 原生上下文窗口混为一谈,这是第一个认知误区。
1. 先分清两个边界
LLM 原生 Context Window:模型本身的物理硬上限。由模型结构、训练方式、推理显存共同决定,比如 GPT-4o 的 128k、Claude 3.5 Sonnet 的 200k(这两条是厂商 2024 年公布时的标称值,这类数字更新很快,动手前请以当前官方文档为准)。它是「输入 token + 输出 token」的总长度上限,超过就会直接报错或强制截断。
程序员类比:服务器的物理内存总容量(比如 32GB),是硬件决定的绝对上限。Agent Context Window:Agent 系统自定义的逻辑上限。它是 Agent 在单次推理循环中,实际送入 LLM 的有效上下文的最大边界,一定 ≤ 模型原生窗口。
程序员类比:操作系统给单个应用进程分配的最大可用内存配额(比如给该进程最多用 8GB),进程不能吃光所有物理内存,系统还要预留运行空间。
2. 为什么 Agent 必须单独定义 Context Window?
普通对话机器人的上下文只有 “用户问 + 助手答”,而 Agent 是多组件拼接的复杂上下文,一次完整推理至少包含:
固定开销:系统提示词(角色、规则)+ 工具函数定义
交互历史:用户输入 + 助手回复
推理过程:思考链(CoT)、规划步骤、自我反思
外部数据:工具调用记录、API 返回结果、检索到的文档片段
如果直接用满模型原生窗口,就没有空间留给模型生成输出,会直接出现 “生成一半被截断” 的致命问题,导致工具调用格式错误、推理链条断裂。
3. 工程师视角的关键细节
输出预留原则:必须给生成留空间,这一点没有争议;但"留多少"不存在跨模型、跨场景的通用阈值,它取决于你的输出形态——返回一段结构化 JSON 可能只需要几百 token,让模型写一份带推理链的重构方案则可能要几万。工程上可行的做法是先取初始值,再按真实流量校准:
- 以「输入侧预算 = 原生窗口 × 75%~80%」起步(例如 128k 窗口,输入侧约 100k);
- 上线后采集你自己的输出 token 长度分布,取 p95 / p99 作为校准目标——先预留的 20%~25% 只是起点,真正的数字来自你的数据;
- 仍然要有兜底:单个请求输出可能远超 p99(比如模型开始写一份完整文件),这时要么提前把任务拆成多轮产出,要么在生成中断时能从已产出部分续写,而不是让整个调用失败。
刚性校验:超过窗口就会触发错误,因此 Agent 框架必须在调用 LLM 前,用对应模型的 tokenizer 做精确计数校验,绝对不能靠 “字数估算”。
二、Token Budget:上下文里的 “资源分配表”
如果说 Context Window 是 “总蛋糕大小”,Token Budget 就是 “分蛋糕的规则”。
1. 专业定义
Token Budget(令牌预算,也叫 Context Budget)是上下文窗口内的模块化配额机制:给上下文中的每个功能模块设定最大 token 阈值,通过优先级规则动态调配,确保总长度不溢出,同时保障核心功能的资源供给。
2. 程序员视角的精准类比
这完全就是操作系统的内存分区管理 + 微服务的资源配额(ResourceQuota):
系统提示 = 操作系统内核占用的内存,优先级最高,永远不能动
当前用户输入 + 最新思考 = 当前运行的前台线程,优先级最高,必须保障
对话历史 = 后台闲置进程,优先级低,资源紧张时可以优先回收
工具返回结果 = 临时缓存,用完即可清理
举一个真实生产级代码 Agent 的预算分配示例(总输入预算 100k):
| 模块 | 预算配额 | 优先级 | 说明 |
|---|---|---|---|
| 系统提示 + 工具定义 | 6k | 最高 | 固定开销,不可裁剪 |
| 当前任务 + 最新 3 轮对话 | 10k | 最高 | 必须完整保留 |
| 代码规划 + 思考链 | 15k | 高 | 核心推理过程 |
| 工具调用 + 文件内容 | 45k | 中 | 弹性空间,可裁剪压缩 |
| 历史对话摘要 | 14k | 低 | 可进一步压缩、归档 |
| 突发缓冲 | 10k | - | 应对长文本工具返回 |
3. 两种预算模式
静态预算:每个模块固定死上限,实现简单,适合简单对话类场景;
动态预算:模块间可以弹性挤占,比如工具返回了长文件,就临时压缩历史对话的配额。凡是工具返回长度不可预测的长流程(代码 Agent 读文件、浏览器 Agent 抓网页),固定配额基本没法用,只能走动态。
但动态的代价是配额不再可解释:当某条历史被挤掉时,你需要能回答"为什么是它"——否则线上排查时只能归因于玄学。常见的折中是「静态软上限 + 受控借用」:每个模块先有一个软上限;超限时不直接无限膨胀,而是按优先级从低优先级模块的空闲额度里借;借不到才触发 Compaction 并记一条可观测事件(哪个模块超限、借了多少、挤掉了什么)。这样既保住弹性,又保留了事后复盘的能力。
三、Compaction:上下文满了的 “腾空间艺术”
当 token 预算快被打满,新的输入、工具结果塞不进来时,不能直接报错,也不能随便删东西 —— 这就是 Compaction 要解决的问题。
1. 专业定义
Compaction(上下文紧缩 / 上下文压缩)是一系列空间回收技术的统称,核心目标是:在尽可能保留关键语义信息的前提下,降低上下文的 token 占用量,从而腾出空间延续任务生命周期。
它不是简单的 “删除历史”,而是「清理 - 精简 - 归档」的组合操作;业内 “紧缩” 的译法更准确,因为它不仅有压缩,还有整理碎片、回收无效空间的含义。
2. 程序员视角的经典复刻
这就是计算机内存管理三件套的 Agent 版:
垃圾回收(GC):清理无效、重复、已完成的上下文(比如失败的工具调用、重复的文件内容),对应标记 - 清除算法;
内存紧缩(Memory Compaction):合并零散信息、精简冗余表述、浓缩历史,减少上下文碎片;
交换分区(Swap):把冷数据(久远的历史、不用的文档)移出上下文,存入长期记忆 / 向量库,需要时再检索回来。
3. 四级 Compaction 方案:从玩具到生产
(1)初级:截断裁剪(Truncation)
最粗暴的方案:直接删除最老的 N 条历史消息,只保留最新的部分。
优点:零额外开销、速度极快、实现零成本;
缺点:信息丢失严重,极易删掉任务目标、关键约束,导致 Agent “失忆”;
适用场景:简单对话机器人、短流程工具调用。
工程师避坑:裁剪不能只按时间倒序删,必须永久保留第一条用户输入(核心任务目标)和系统提示,否则 Agent 跑两步就忘了自己要干嘛。
(2)中级:摘要压缩(Summarization Compaction)
当前主流方案:当上下文达到预算阈值时,调用 LLM 将旧的对话历史、工具记录浓缩成一段精简摘要,用摘要替换原有的长文本。
比如 20k 的 10 轮对话历史,总结成 500token 的摘要,直接腾出 19.5k 空间。
优点:信息保留度远高于裁剪,实现难度中等,是性价比最高的方案;
缺点:细节会丢失,摘要本身需要消耗一次 LLM 调用,有成本和延迟;
常见实现:滚动摘要(每 5 轮总结一次)、阈值触发(达到 80% 预算触发)。
滚动摘要只解决“不重算”,没解决“多轮重写导致的细节淡化”:摘要会被反复合并,每并一次旧的一层就被重写一次,执行步骤、具体参数和关键节点会逐步退化成“处理了相关问题”。
要延长保质期可以给摘要分层——设轮次上限(例如 3 轮),触发上限时把最早那几批既有摘要整体重压成一条更高层摘要,而不是继续往同一条摘要上叠加。细节仍会丢,只是慢得多、天花板高得多;这不是“无损”,说成“延缓丢失”更准确。
(3)高级:结构化提取 + RAG 化归档
生产级方案:不再把上下文当成纯文本,而是拆解为结构化数据:
把工具返回的长文档、代码文件,提取关键事实、变量、函数签名;
把历史对话拆成任务节点、决策记录、结论条目;
所有非当前活跃的数据,全部存入向量库 / 结构化记忆库,上下文只保留当前步骤必需的信息。
优点:空间利用率高;关键事实被抽成结构化条目后,不会像滚动摘要那样被反复复述稀释,因此更耐得住多轮累积,适合跨天、跨周的长周期任务。但必须说清楚:它同样是有损的——损失发生在"抽取"这一步,抽取器没认出来的信息就永久落到上下文之外了。所以它的保留上限取决于两件事:抽取覆盖率、以及之后的检索召回率。换句话说,这里只是把损耗从"摘要重写"搬到了"抽取 + 检索",并没有消除。
缺点:实现复杂,需要配套记忆系统和检索能力。
(4)前沿:令牌级压缩(Token-level Compaction)
用专门的压缩模型对 prompt 做 token 级别的精细压缩,删掉或压缩掉对当前任务冗余的 token,保留原文结构。它和摘要的核心区别是:不改变语义结构,只是用更省的 token 重新表示原始文本,类比文件的 zip 压缩(而摘要是有损重写,类比把一篇文章改写成提要)。
微软的 LLMLingua 系列是这个方向有代表性的开源实现。工程上不要直接照抄论文里的压缩率:论文给出的数字是在特定任务、特定可容忍准确率下降幅度下测的,换到你的场景可能完全不成立。落地方式通常是先取一个保守比例试用,再用你自己的评测集压测——观察"压缩率 ↔ 任务准确率"曲线,找你愿意接受损失的那个点。
另一个容易被忽略的成本:压缩本身要跑一次模型推理。如果省下的输入 token 费用抵不过这次推理的费用和延迟,它就是亏的——所以这一层通常只在输入足够长(比如系统提示 + 大量检索片段反复重发)时才划算。
4. 触发时机的工程权衡
阈值触发:达到预算的 75%~85% 时触发,是最常用的方案;
周期触发:每执行 N 个 Agent 循环触发一次,适合稳定的长流程任务;
事件触发:调用大返回量工具(如网页浏览、文件读取)后主动触发。
四、深刻拔高:三者背后的架构本质
理解到这里还只是 “懂技术”,真正吃透要看到背后的底层逻辑。
1. 核心矛盾:有限窗口 vs 无限任务
Agent 和普通 Chatbot 最本质的区别,是任务生命周期的长度:
聊天机器人是单轮 / 短轮交互,上下文装得下就行;
Agent 是长周期、多步骤、自主执行的任务,记忆需求是持续增长的。
Context Window 是容器、Token Budget 是分配规则、Compaction 是回收机制,三者共同构成了 Agent 的「短期记忆管理系统」,解决的就是 “有限的注意力窗口,如何支撑无限的任务流程” 这个核心矛盾。
2. 存储层级思想的完美复刻
这本质上是计算机体系结构中「分层存储」思想的又一次落地,是半个世纪的经典方法论在新范式下的重演:
| 计算机存储层级 | Agent 记忆层级 | 核心特点 |
|---|---|---|
| CPU 寄存器 | LLM 注意力焦点 | 速度最快,容量最小,只存当前计算单元 |
| CPU 缓存 | Agent Context Window | 存放当前活跃数据,容量有限,速度快 |
| 内存 | 短期向量记忆 | 容量更大,速度稍慢,按需加载 |
| 硬盘 / 对象存储 | 长期知识库 / 文件记忆 | 容量近乎无限,速度最慢 |
整个 Agent 记忆调度,和 CPU 缓存置换、操作系统虚拟内存的设计逻辑完全一致:用分层结构平衡速度、容量、成本。
3. 生产级 Agent 的分水岭
一个 Agent 是 Demo 玩具还是生产工具,看它的 Compaction 水平就可以判断:
只会截断的,是玩具级,跑 3 步就会失忆;
会做摘要压缩的,是入门级产品,能处理中等复杂度任务;
能做到结构化归档 + 按需检索的,才是生产级 Agent,能支撑跨天、跨周的长周期工作。
4. 工程师的设计哲学:没有最优,只有权衡
永远不要追求 “最完美的压缩”,所有方案都是三角权衡:
信息保留度 ↔ 空间节省率 ↔ 计算成本
大窗口不是银弹:长上下文不仅推理成本线性上涨,还存在 “Lost in the Middle”(中间信息注意力衰减)问题,塞进去模型也看不见。合理的预算分配 + 精准的 Compaction,远比盲目追求百万级上下文更有工程价值。
常见认知误区澄清
误区:上下文窗口越大越好
不太对。窗口变大不是免费的:注意力计算开销随长度增长、费用随 token 数上升(具体曲线取决于注意力实现与推理优化,不要用"线性"一句话概括,压测你的实际部署才能知道);更关键的是长上下文普遍存在中间信息注意力衰减(Lost in the Middle)——塞进去不等于模型会用到。所以窗口只是上限,决定效果的是你往里面放了什么。要判断"该不该换更大窗口",可量化的问法是:在当前预算下任务的召回率是多少?加长窗口后召回率提升多少、单 token 成本与延迟涨多少?用增量比值去决策,而不是默认越大越好。误区:Compaction 就是写个 prompt 总结一下
错。摘要只是 Compaction 的一种。去重、裁剪、结构化提取、冷数据归档都是 Compaction 的组成部分,生产级方案一定是组合拳。误区:Token 预算只算输入文本
错。LLM 的 Context Window 是输入 + 输出的总长度,输出必须预留配额。这是 90% 的 Agent 新手都会踩的坑 —— 输入塞太满,导致生成到一半被截断,工具调用格式错误、推理中断。
一句话总结三者关系
Context Window 是容器,画定了短期记忆的最大边界;
Token Budget 是规则,决定了空间怎么分、优先级是什么;
Compaction 是机制,负责在空间不足时,用最小的信息损失换最长的任务寿命。
三者共同支撑起 Agent 的 "工作记忆",是所有 Agent 架构的底层基础设施。
本文主要是对工程实践的结构化梳理,涉及具体模型数值的部分请以厂商官方文档与你的实测为准(本文提到的模型上下文数字检索于 2026-09)。