干货!万字长文解析 Agent 框架中的上下文管理策略
0x01. 背景1什么叫上下文工程Context Engineering“上下文工程”简单来说就是在一些LLM的约束下如上下文窗口大小、注意力长度的限制优化上下文token的效用从而持续获得理想输出的工程实践。一个好的context engineering追求用最少的、信号最强的token集合最大化期望输出的概率。因为随着Agent不断地运行会不断产生新的数据这些数据可能对下一轮推理有用因此必须放到上下文中作为模型的“短期记忆”。Context engineering就是从不断变化的信息中精心挑选出能放入有限上下文窗口的内容。如果说之前早期的Prompt Engineering适用于单轮文本生成任务那么Context Engineering就适用于需要多轮推理、长时间运行的智能体需管理不断演变的上下文状态。prompt engineering 和 context engineering的区别context engineering(右)上下文工程需要从海量信息文档、工具、记忆文件等中筛选形成最优上下文窗口2为什么Context Engineering对构建一个强大智能体来说至关重要Agent 每调用一次工具就会返回一个工具的Observation这个结果会被追加到聊天记录中。生产环境中的 Agent 可能会进行长达数百轮的对话因此随着时间的推移历史记录message会越来越长。而且工具调用的Observation经常会特别长比如模型执行 Read 命令读取了一个文件的部分内容或者执行Bash命令输出了很长的log。这样长的Observation不断地拼接到上下文message中最后很有可能超过了模型最长能够接受的上下文长度比如128K~1M。虽然现在的LLM能够接受越来越长的序列了但它们和人类一样会随着上下文增长而出现注意力涣散的现象模型准确回忆信息的能力会下降而且推理也会变慢。这种现象被称为 “上下文腐败”context rot。虽然不同模型的性能下降曲线不同但所有模型都存在这个特点会在远低于能接受的最长序列长度时就出现context rot的现象比如最长支持1M token但是在200K token的时候就已经开始context rot了。导致这种现象的原因包括• 注意力分散每个token都关注上下文中的所有其他token形成了 n^2 级别的两两关系。当 n 变大时这种关注力被摊薄导致注意力分散。• 训练数据偏差模型在训练时接触的长序列远少于短序列因此对长距离依赖关系的处理经验不足。• 位置编码插值等技术可以让模型适应更长的序列但通常会牺牲一定的精度。0x02. 上下文工程在上面一节我们说到上下文工程的指导原则是找到能够最大化期望输出概率的最小高信号 token 集合。那么这一部分我们就介绍一些常见的上下文管理方式。1上下文卸载与检索Context Offload Retrieval将信息转移到文件系统中因为上下文窗口是有限的所以我们不能将所有信息都塞进 Agent 的短期记忆上下文窗口中而应将其“卸载”到外部存储并在需要时精确检索。这种思想催生了多种工程实践下面会结合 Manus、Cursor、Claude Code 等案例进行详细介绍。一种最粗暴的解决上下文过长的方式当然就是截断了。在处理过长的输出如Shell 命令结果、MCP 返回时如果简单采取截断的方式就可能导致关键信息永久丢失掉。例如一个报错信息可能在日志的末尾截断后 Agent 就无法定位到问题或者一个长列表的中间几行恰好包含了我们需要的重要线索截断后就无法获取到了。更根本的问题是Agent 需要基于所有先前状态预测下一步动作但我们无法提前预判哪个观察结果在十步之后会变得至关重要。所以任何不可逆的压缩都带有风险。(a) 将上下文卸载到文件系统紧凑化, CompactionManus提出了一个核心理念将文件系统视为终极上下文。这是因为文件系统天然具有无限容量、持久化、可随机访问的特性Agent 可以像人类一样通过路径、文件名、时间戳等元数据来组织信息。最关键的是这样的压缩策略是可逆的。例如• 当 Agent 访问一个网页时只要保留 URL就可以将网页内容从上下文中移除。后续需要时Agent 可以重新请求该 URL。• 当处理文档时只要保留文件路径就可以省略文档内容需要时再用 cat 或 tail 读取。• 在日志中完整的输出content可以被移除只保留一个path路径。这种“可逆压缩”确保上下文长度缩减的同时信息并未真正丢失——它们只是被卸载到文件系统中了随时可以重新加载进来。https://manus.im/en/blog/Context-Engineering-for-AI-Agents-Lessons-from-Building-Manus把上下文的一些很长的信息卸载到文件系统中同时Manus 也鼓励 Agent 主动将中间结果写入文件。例如执行一个复杂查询后将结果保存到output.log然后上下文中只保留一句话“结果已写入 /tmp/query_result.json”。Agent 后续可以通过head、tail、grep等命令渐进式地查看或一次性读取整个文件。这种方式既减少了上下文占用又保留了完整信息。(b) 检索推理前检索 vs. Just-in-time检索很多早期的Agent 都依赖于 RAGRetrieval-Augmented Generation这样的推理前检索(pre-inference retrieval)方式来获取信息——预先对知识库的文本进行向量化然后在推理前预先检索相关片段。但 Manus、Claude Code 这些新锐 Agent Scaffold 则采取了不同的方法弱化甚至抛弃 RAG转而让 LLM 自己生成搜索命令像人类一样主动探索大文件或者代码库即just-in-time检索。为什么要弱化RAG呢因为RAG包含的组件太多太复杂了。我们要考虑的事情也会变得很复杂某个步骤稍有差池就会导致整体的效果受影响。比如说如何对代码进行合理分块按函数、按行数还是按语法结构选择什么embedding模型、如何计算相似度而且对于一些非结构化数据比如PDF、图片RAG 很难有效处理。如果说我们从Claude Code等SOTA的agent框架中学到了什么的话那就是Keep Things Simple, Dummy我们要让框架的逻辑尽可能地简单把有难度的事情交给模型本身。Just-in-time检索的优势以Claude Code为例Claude Code 在处理大型的数据时会生成一些复杂的 Bash 命令进行查询如ripgrep、jq、find等利用自己对代码的深刻理解使用精细而复杂的正则表达式定位相关代码块无需将大段大段的数据加载进上下文。这也模仿了人类认知我们不会去记忆所有的信息但是我们知道什么时候该查找、知道去哪里查找信息。这种方式的优势在于• 灵活性搜索的内容可以根据当前需求动态调整不受预索引的限制。RAG 索引需要定期更新而直接搜索始终反映最新状态。• 渐进式寻找例如在debug的时候Agent 可以像人类一样先 grep 查找函数定义再搜索调用这个函数的位置然后打开某个文件查看上下文——每一步都基于前一步的结果。2上下文摘要(Context Summarization)“他们沉回了来时的大地。而他们的孩子则被留了下来对黄金时代—— 时间出现前的那个时代只剩模糊的记忆。” ——《人之涛》刘宇昆当上下文窗口即将被填满且没有办法进一步做紧凑化的时候我们不得不采用另一种手段摘要化。这是一种有损压缩它会将对话历史浓缩成一段摘要从而释放空间。但这必然会导致信息的模糊和丢失——模型无法再访问精确的代码行或工具输出的完整内容。因此摘要化只能作为上下文窗口即将耗尽时的最后手段。而且摘要化必须设计得可恢复让 Agent 在必要时也能找回丢失的细节。具体的做法就是将完整的对话历史dump到一个持久化文件中。这个文件就像一个黑匣子保留了所有原始消息、工具调用及其结果。Agent 在后续交互中如果发现摘要中缺少关键细节可以通过工具如grep、Read主动检索这个历史文件找回丢失的信息。左超过了context limit右做压缩。但是压缩之后发现有信息丢失所以再从之前的对话记录中搜索找回。为了确保模型能够平滑地继续工作通常还会保留最后几次完整的工具调用及其结果。这样模型可以清楚地知道自己从何处中断保持风格和语气的连贯性避免因上下文重置而失忆。那么什么时候使用紧凑化什么时候使用摘要化呢我们应当优先采用可逆的紧凑化策略如将大文件输出写入磁盘只保留路径。但当已经无法再紧凑化而且上下文也确实即将耗尽时再使用带备份的摘要化——完整dump聊天记录然后再摘要这样就可以让有损的压缩变得可恢复。这两种手段结合起来Agent 理论上就能够处理无限长的任务而无需无限大的上下文窗口同时保留了关键信息在有限中创造无限。Agent 优先使用 Compaction如果已经无法再继续做紧凑化了才转而使用 Summary。Summary是最后手段下面以Claude Code的压缩流程为例介绍压缩的过程。有两种情况会触发Claude Code的压缩机制• 一是自动触发Claude Code会监控当前上下文的 token 使用量。当对话内容接近模型的上下文窗口上限时系统自动触发压缩。• 二是手动触发用户也可通过/compact命令主动执行压缩。这里给出我在Claude Code中对话时实际运行了/compact命令之后的打屏输出。具体的内容因为涉及到我的聊天记录所以脱敏了。只看整个skeleton就可以了解它的工作原理。Compact summary ⎿ This session is being continued from a previous conversation that ran out of context. The summary below covers the earlier portion of the conversation. Summary: 1. Primary Request and Intent: 用户在上一轮对话xxxx结束后对 xxxx产生了好奇连续提出了四个问题 ...... 2. Key Technical Concepts: ...... 3. Files and Code Sections: ...... 4. Errors and fixes: xxxx, 我把它们搞混了 5. Problem Solving: ...... 6. All user messages: ###用户所有的input ...... 7. Pending Tasks: - 无明确待办任务。上一轮关于xxxx的任务已完成用户表示会验证但尚未反馈验证结果。 8. Current Work: 最后回答的问题是xxxx。 回答要点 ...... 9. Optional Next Step: 无明确下一步任务。用户的问题已全部回答且没有新的待办事项。如有需要可继续讨论 xxx或回到上一轮的 xxx 文档验证工作。 If you need specific details from before compaction (like exact code snippets, error messages, or content you generated), read the full transcript at: /root/.claude/projects/PATH/SESSION_ID.jsonl在返回摘要文本后用这段摘要替换掉旧的对话历史腾出空间。而且我们从这个摘要的输出就可以看到原始对话被完整地保存到了本地的JSONL文件/root/.claude/projects/PATH/SESSION_ID.jsonl 中。如果需要精确的代码片段或变量名Agent完全可以按照摘要的提示主动读取 JSONL 文件中的相应部分来“回忆”。这种方式虽然牺牲了即时访问的便利性但确保了信息的可恢复性。3上下文隔离多智能体架构面对一个复杂的任务我们可以将任务分解然后由主智能体协调多个专门化的子智能体sub-agents来处理具体任务。每个子智能体都拥有干净的上下文窗口并且运行在自己的上下文窗口中拥有独立的system prompt和工具使用权限(tool access)。主Agent会根据每个subagent的功能描述自动决定什么时候该把什么任务委托(delegate)给哪个合适的 subagent。当然用户也可以直接显式地要求使用特定的subagent。使用这种多智能体架构的几个好处是•节省主Agent的上下文因为subagent的上下文和主agent是隔离的所以子智能体当然可以深入探索产生较多的token也不要紧反正它不会污染主对话的上下文。它只返回精简的摘要给主Agent这样主Agent的上下文也不会变得很长。•权限控制限制 subagent 可用的工具如某些Agent只能执行只读操作。比如。Claude-Code中就有一个专门的内置subagent叫Explore它就是一个只读 agent专门用于搜索和分析代码库而General-Purpose 则是一个全能型的subagent因此可以使用所有的工具。•特定领域专业化为特定领域编写专门的系统提示提高任务质量。例如Claude-Code就有很多内置的subagent包括专门负责代码库探索的 Explore、负责理解代码库并进行规划的Plan 、适用于同时进行探索和修改的全能型Agent General-Purpose 等。•节约调用成本可以把某些简单的任务路由到更快、更便宜的模型。例如Claude-Code中Explore 这个任务比较简单所以使用的是快速、低成本的 Haiku而Plan 和 General-purpose 比较复杂且重要所以是继承的主Agent模型通常是 Sonnet 或 Opus多智能体架构对于上下文管理的贡献是什么呢重点就在于每个 subagent 拥有完全独立的上下文窗口不会与主对话共享历史。subagent 看不到主对话的早期交互除非显式传递信息主对话的上下文也不会被 subagent 的输出污染。举个例子有一些会产生大量输出的任务如运行测试、获取文档、处理日志那么主agent就把它委托给 subagent让详细的输出留在 subagent 上下文中只将摘要返回主对话从而保持主对话上下文的简洁。下面是多智能体架构的一些分类按运行模式分• 前台运行模式subagent 运行时阻塞主对话用户必须等待它完成才能继续与主Agent交互。所以运行时每个操作的permission会实时传递给用户用户需要实时决定要不要accept不同的操作。• 后台运行模式subagent 在后台运行用户可以在它执行的同时继续与主Agent进行其他对话。因为这个subagent在后台运行用户没法实时决定各个操作是否要accept所以在启动subagent之前就会收集所需的权限运行中自动拒绝未批准的操作请求然后自动运行就可以了。按调用关系分• 并行调用多个 subagent 同时独立运行彼此之间没有依赖关系。例如可以同时让多个 subagent 分别分析不同模块最后由主Agent汇总结果。Claude-Code示例同时调用三个Explore subgent• 链式调用多个 subagent 顺序执行后一个 subagent 依赖于前一个的输出。例如先用 code-reviewer 找出性能问题再用 optimizer 根据 review的结果进行优化。下面以Claude Code为例介绍subagent运行的示例。Claude Code 采用了极简的设计这正是“Keep Things Simple, Dummy”的典范。当遇到需要分解为多个子任务的情况时主 Agent 生成自己的克隆作为子 Agent。但是每个子 Agent不能再派生出更多子 Agent这是为了避免无限递归和过度复杂的嵌套。每个子 Agent 执行完毕后其结果以工具响应的形式返回主历史主 Agent 继续推进。此外主 Agent 内部有一个TODO list跟踪需要完成的子任务始终关注着最终目标。简单问题主循环直接通过迭代调用工具解决。复杂问题主 Agent 创建一个自己的克隆子Agent来处理子任务。子任务完成后结果返回给主Agent上下文主 Agent 继续推进。下面是一个调用subagent的例子。我输入的问题分析 opencode 项目的 agent 系统找出关键入口文件、核心数据结构、以及 sub-agent 是怎么被调用的用中文写一份分析报告存到/tmp/agent-analysis.md之后主Agent调用了一个General-Purpose的subagent这个subagent在后台运行● Agent(Analyze opencode agent system)⎿ Backgrounded agent ##表明是后台运行的subagent⎿ Prompt: ###给subagent的任务描述请分析 opencode 项目的 agent 系统实现。具体要做的事1. 用 Glob 找到 agent 相关的源文件在 packages/opencode/src/ 下2. 用 Grep 搜索关键词subagent、spawn、AgentTool 等找到 sub-agent 调用3. 读取核心文件理解- agent 的入口在哪里- agent 的核心数据结构是什么- sub-agent 是如何被创建和管理的4. 把分析结果用中文写成一份报告存到 /tmp/agent-analysis.md报告格式opencode Agent 系统分析1. 关键文件列表2. 核心数据结构3. Sub-agent 调用机制4. 与 Claude Code 的对比推测请认真探索不要只猜测要基于实际读到的代码。● Agent 已在后台运行实时看它的进度之后它就在后台运行了这个任务会触发Glob → Grep → 多次 Read → Write 等多种工具。过了大概两分钟后它就完成了于是屏幕上出现● Agent Analyze opencode agent system completed之后就可以看到它已经把报告帮助咱们生成好了。4上下文缓存什么是 KV CacheKV缓存Transformer 模型在生成每个 token 时需要计算所有之前 token 的Key和Value向量用于注意力机制的计算这些 KV 向量就构成了上下文的状态。KV Cache就是将这些中间计算结果保存下来当后续请求包含相同的前缀时可以直接复用避免重复计算。名词解释Prefill预填充Prefilling 是只在生成第一个输出 token 之前模型对所有输入 token 进行并行处理的阶段。在这个阶段模型计算每个输入 token 的Key和Value向量构建用于后续解码的 KV Cache。prompt是The quick brown fox, 在生成下一个token(“jumps”)之前先对输入prompt进行prefill操作为什么缓存对 agent 来说至关重要Agent 的工作流程通常是多轮工具调用的重复用户输入 → agent 根据当前上下文选择一个动作 → 执行动作得到Observation → 将Observation追加到上下文继续下一轮随着轮次增加上下文不断增长而每次模型的输出长度相对较短。有统计表明平均Agent的输入输出 token 比高达 100:1。这意味着每轮推理的大部分时间都花在处理历史上下文上。如果没有缓存每次请求都要从头计算所有历史 token导致延迟、成本剧增。KV Cache能复用相同prefix的结果。例如在多轮对话中前几轮的历史内容可以作为prefix被缓存后续请求只需处理新追加的内容。这样即使上下文很长TTFTTime to First Token首字延迟仍能保持很低。而且命中缓存和未命中缓存的调用成本也相差甚远以 Claude Sonnet 为例缓存的输入 token 价格为 0.30 美元/百万 token而未缓存的则高达 3 美元/百万 token相差 10 倍KV 缓存的 Agent 设计——以Claude Code为例缓存命中要求新请求的前缀与已缓存的内容完全一致哪怕多一个空格、换行符或者 JSON 键的顺序不同都会导致缓存失效。所以我们要做的就是保持prompt prefix的绝对稳定。•核心原则就是上下文只追加不修改。不要试图在system prompt开头加入时间戳、会话 ID 等变化的内容而是始终以追加方式添加新内容。如果需要对历史进行修正就使用新的消息而不是直接修改已有记录。•确保序列化确定性许多编程语言在序列化JSON时不保证键顺序导致相同内容产生不同哈希值。例如Python的json.dumps(obj)默认键无序而sort_keysTrue可保证稳定顺序。Claude Code中有自动缓存和手动缓存两种模式。自动缓存就是在请求顶层添加一个cache_control字段系统就会自动将最后一个可缓存的内容块作为缓存断点将整个请求prefix从开头到该块存入缓存。默认的缓存生命周期是5 分钟每次命中缓存会自动刷新延长 5 分钟。当然通过付费也可以将这个时间延长到1小时。{ cache_control: { type: ephemeral, ttl: 1h } }配置自动缓存的方式很简单就像这样curl https://api.anthropic.com/v1/messages \ -H content-type: application/json \ -H x-api-key: $ANTHROPIC_API_KEY \ -H anthropic-version: 2023-06-01 \ -d { model: claude-opus-4-6, max_tokens: 1024, cache_control: {type: ephemeral}, ###放在这里 system: You are a helpful assistant that remembers our conversation., messages: [ {role: user, content: My name is Alex. I work on machine learning.}, {role: assistant, content: Nice to meet you, Alex! How can I help with your ML work today?}, {role: user, content: What did I say I work on?} ] }  自动缓存的示例缓存的断点随着上下文的增长而不断后移 除了自动缓存之外我们还可以对稳定性极高的内容如system prompt、工具定义使用显式断点确保它们被缓存。Claude Code允许最多4 个缓存断点包括显式和自动缓存。自动缓存会占用其中一个槽位因此如果已经设置了4 个显式断点自动缓存将失败。 自动缓存和显示缓存的结合示例如下 plaintext { model: claude-opus-4-6, max_tokens: 1024, cache_control: { type: ephemeral }, // 自动缓存 system: [ { type: text, text: You are a helpful assistant., cache_control: { type: ephemeral } // 显式断点 } ], messages: [{ role: user, content: What are the key terms? }]}学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】