上下文工程实战:从Token管理到记忆架构,让AI Agent稳定落地

发布时间:2026/10/8 11:06:32
上下文工程实战:从Token管理到记忆架构,让AI Agent稳定落地 1. 为什么Agent的表现忽好忽坏问题出在上下文身上做AI Agent项目这一年多我最深的体会是大多数Agent“翻车”不是模型不够强也不是代码写得不对而是上下文没管好。同样的任务上下文里堆的东西不一样Agent的输出质量能差出一个量级。今天想系统拆一下上下文工程Context Engineering这件事——它到底是什么、为什么成了Agent落地绕不开的关卡、以及我在实际项目中怎么一步步把它从“玄学”变成可设计的工程。先看一个典型的翻车现场。我给一个客服类Agent配了完整的FAQ文档、历史工单记录、用户画像数据想着信息越全越好。结果Agent上线后频繁答非所问用户问退款流程它扯到了物流时效用户问发票它开始复述会员权益。排查到最后发现系统把当天的全部缓存数据和一份2万多字的运营手册直接塞进了系统提示词真正和“退款”相关的信息只占上下文的不到10%。模型不是不会答是它根本“看不到”重点。这就是上下文工程要解决的核心问题你喂给模型什么、以什么顺序喂、喂多少、什么时候喂直接决定了Agent的上限和下限。上下文工程不是提示词工程换个名字它更像一套完整的“信息调度系统”——管理token、管理记忆、管理检索、管理输出约束让模型在有限的注意力窗口内始终聚焦在“当下最该看的信息”上。有人把上下文工程称作Agent时代的“第二语言”这个比喻很准。以前写代码你靠变量、函数、数据库管理状态现在写Agent你靠的是上下文里的每一段文本管理模型的“工作状态”。上下文就是Agent的瞬时记忆、长期记忆、工具说明书、任务手册、输出模板的集合体。谁把这一层管明白了谁就掌握了Agent稳定性的命门。2. 上下文窗口里的成本账为什么一个大模型只有十万token还是不够用很多人上来就问“长上下文是不是越大越好”这个问题问早了。先要算清楚一笔账你的Agent跑一个任务到底要消耗多少上下文空间2.1 上下文消耗的四个去向拿我自己做的RAG类Agent举例一次完整的用户请求上下文被四类内容瓜分系统指令区角色设定、行为约束、输出格式、安全规范通常固定占用我一般控制在800-1500 token以内。这里有两条注意系统指令虽小但它始终占据窗口头部位置对模型的全局行为影响最大不能为了省空间砍得太狠但如果指令写得冗长最坏的情况是挤占后面任务数据的空间等于变相缩短有效处理长度。对话历史区多轮对话累积下来的用户消息和助手回复这是最容易被忽视的“幽灵占用”。一轮正常对话大约消耗500-1000 token聊到20轮就是1万到2万token。不少项目做到一半才发现——我还没传文档呢怎么窗口就满了多半就是历史区膨胀了。检索数据区从知识库或工具返回的相关内容这部分是任务刚需通常希望给到15%-35%的窗口占比。但实际中经常失控我见过一次函数返回3万token原始表结构的案例等塞进窗口后模型反而不知道用户问的是什么了。任务指令区当前这一步的具体指令比如“根据上述资料回答用户问题并输出JSON”这个区间一般小而纯粹几百token解决。四块加起来你会发现一个残酷的现实标称“200K上下文”的模型可用的有效工作区可能只有一半甚至更少。长上下文模型真实可用的有效工作区通常要按50%-70%估算因为模型在超长输入下的注意力分布会变稀疏。更何况还有输入成本问题——很多API按token计费你每次请求都塞满垃圾成本直接起飞。我有个上线运行的项目单次请求从8000 token优化到4000 token后月度API账单直接降了40%。2.2 token预算表一个可落地的分配方案我现在的做法是给每个Agent建一张token预算表先定总额再分配区块建议占比说明系统指令2%-8%固定行为约束精简到不能再少对话历史10%-30%优先保近期老对话做摘要替代检索数据30%-60%任务核心按问题精准召回任务指令2%-5%当前步骤的即时指令预留缓冲10%-20%防止单次突发数据撑爆窗口这张表不用死守但它的价值在于每次请求前你的代码应该清楚地知道“这轮我要往窗口里放什么、放多少、哪些可以被丢弃”。一旦预算失控先从对话历史开刀这是我踩坑之后最深刻的教训。3. Agent的失忆症构建能让它“记住重点”的分层记忆架构Agent做多轮任务时最经常翻的车就是“失忆”——早几步算出的中间结果到后面几步全忘了。这个问题的根源在于模型本身没有真正的记忆它只看得见当前窗口里写了什么。3.1 四层记忆架构的划分我参照认知科学里人类记忆的分类方式把Agent的记忆拆成四层每一层的存储介质、调用时机完全不同工作记忆Working Memory当前窗口内正在处理的信息包括用户输入、工具返回值、中间推理结果。这一层的特点是一步一清空绝不做持久化。情景记忆Episodic Memory和具体时间、场景绑定的历史事件比如“30分钟前用户要求改订单地址”“上一轮助手已经推荐了两款笔记本”。我通常用消息队列或数据库存原始记录并在需要时把最近几轮的关键摘要注入窗口。语义记忆Semantic Memory剥离了时间场景的通用知识比如产品规格、政策条款、代码仓库说明。这一层放向量数据库靠检索触发不是每次请求都加载。程序记忆Procedural MemoryAgent知道“怎么做任务”的方法论比如标准操作流程、之前成功解决过的类似问题。这一层固化到系统指令或few-shot示例里相当于给它一份操作手册。3.2 工作记忆的显式管理一个容易忽略的细节四层里最容易出问题的是工作记忆——因为它直接占用窗口而模型不会主动帮你清理。我在项目里引入了“工作记忆管理器”把跨步骤的中间数据单独维护——用一个结构化对象保存下来只在后续步骤需要时以压缩摘要的形式重新注入上下文。这不只是在代码里多维护一个变量真正关键的一步是设计好“什么该留在长期清单里、什么用完即扔”否则管理器本身就成了新的负担。举个例子一个多步骤的订单处理Agent第一步解析了用户意图第二步查询了库存第三步计算了价格。如果不做清理三步的原始输出全部堆在上下文里很快窗口就爆了。我的做法是每完成一步就把该步的原始输出浓缩成一两句话的结果摘要覆盖到工作记忆里原始输出直接丢弃。这样三步走完上下文只多了三句话。3.3 另一个高频翻车点并发多实例之间共享了同一套长期记忆如果你没有给记忆加namespace隔离两个用户聊天时会把对方的“情景记忆”检索回来——这在我早期复盘时抓到过A用户的订单记录被当成B用户的检索结果塞进了上下文。这类问题不体现在代码报错上而是体现为莫名其妙的回答串线排查起来很费劲。我现在的做法是所有记忆写入时强制带session_id和user_id读取时用复合条件过滤宁可漏召回也不能跨用户错召回。4. 上下文生命周期从“一次喂饱”到“按需投喂”的工作流设计“把所有可能用到的信息一次性塞进窗口”是一个看起来很省事、实际最不省心的设计。好的上下文工程应该像给一个人交代任务一样分阶段给信息而不是一次性把整本手册拍在他脸上。4.1 三步递进的上下文投喂节奏我在一个复杂任务Agent上把上下文拆成了三个注入阶段效果非常明显。第一阶段是“开场白注入”——只给系统指令和任务的约束框架第二阶段是“按需加载”——任务执行到哪一步、需要哪部分知识就检索哪部分第三阶段是“收尾汇总”——把各步骤产物汇总成最终输出。这样的好处有三点每步的token开销更小、模型注意力更集中、历史记录也更干净。这个思路本质上是把“上下文准备”从一次性的动作改成了随任务推进持续发生的动作。你在每一轮模型调用之前都应该问自己这一轮它到底需要知道什么不需要的一律不喂。4.2 子Agent模式下的上下文隔离对复杂业务场景我越来越推荐“分工协作隔离”的架构主Agent只保留高度概括的全局记忆具体的专业技能分别交给下游的子Agent处理。比如一个数据分析Agent主控负责理解用户问题和编排子任务SQL生成Agent只专注于写查询报表Agent只专注于生成可视化描述。每个子Agent的上下文是独立的——SQL生成Agent绝不应该看到跟报表相关的模板文件它的窗口里只需要数据库Schema和查询任务。这种上下文的“物理隔离”比在单一Agent里反复切换角色要稳定得多。它等于用系统的结构换单点的简单而单点简单恰恰是让模型发挥稳定的核心手段。4.3 上下文超时与过期策略别让旧信息污染新任务另外要专门提一下“上下文过期”这件事。实时性敏感的任务比如查天气、查库存、查价格如果上下文中存在一个半小时前的旧数据模型很容易把它当作当前事实。我现在的做法是给每块检索数据打时间戳超过策略阈值就触发数据刷新。缓存要设置TTL比如订单状态类缓存设30秒一般商品信息5分钟全量资料类15分钟。别小看这个细节它就是Agent“说胡话”的高频原因之一。5. 检索、排序、压缩决定上下文质量的三板斧做了这么多铺垫落地上最关键的问题还是具体往上下文里放什么、怎么放我靠三件事提升上下文质量——高质量检索、相关性排序、智能压缩。5.1 检索不是“搜到就行”RAG类的Agent翻车十有八九是检索质量不过关。只做关键词匹配的项目查“退款”会搜出一堆含这两个字但完全不相关的运营日志。我的做法是混合检索策略先用向量召回扩大候选集再用关键词和实体匹配做重排。有一说一这一步非常依赖对具体业务数据的理解没有通用银弹——有些领域词向量表示很差就必须靠词表兜底。具体的混合检索流程可以这么搭向量检索取Top 200BM25取Top 100合并去重后交给重排模型或者用结构化的打分规则筛出Top 5-8作为最终注入内容。重排之后一定要过滤掉低分结果这一点很多人忽视——宁可少给信息也不要给噪声。模型对噪声的容忍度远比我们想象的低。5.2 压缩的三种姿态截断、摘要、提取压缩不是简单的“截前留后”要看信息类型截断只适合日志类、流水类数据丢中间保留头和尾。摘要适合长文档、历史对话用一次轻量模型调用把要点拎出来。提取适合结构化检索比如“从工单记录中提取用户ID、问题类型、处理结果”三个字段比塞进整段原文高效得多。我强烈推荐为Agent增加“摘要工具”——大模型Summarizer专门负责把长历史浓缩成带时间线的要点列表。对话进行到第15轮时把前14轮压缩成100 token的摘要比硬塞5800 token的原始历史效果好得多。这个工具虽然多花一次API调用但长期看既省钱又提升效果。5.3 排序逻辑近处的、相关的、带结论的往前放上下文里的信息顺序也会影响模型注意力。我总结了三条排序规则时间上越新的越靠前直接回答用户问题的内容优先于背景知识带明确结论的内容优先于带过程推断的内容。举例来说用户问“这笔订单为什么还没发货”上下文里如果有“该订单因库存不足被拦截”的结论性标签就应该放在订单流转原始记录之前。结论在前模型就不用自己从头猜。6. 长上下文模型的幻觉边界什么时候该信任什么时候该外置上下文工程做到一定程度你会碰上一个更麻烦的问题模型面对超长上下文时的能力衰减。这不是危言耸听业界针对长上下文评测做过不少实验结论基本一致——“大海捞针”测试模型可以做得很好但真实任务下要找的信息一旦多于一个点、或者需要跨多段信息做推理定位和综合能力都会明显下降。6.1 有效上下文长度与退化现象我自己的实践体验是在超过某个阈值后模型对中部信息的利用率会下降这被社区叫做“lost in the middle”。所以我设计系统时遵循一个原则关键任务信息放在上下文开头或者结尾尽量避免把核心数据埋在中间段。如果一次请求的信息量注定很大我宁可把任务拆成多步把每步的信息量控制在模型的高质量区间内。另一个需要警惕的事情是长上下文模型给出的自信回答里有相当比例是“编的”。我遇到过Agent信誓旦旦说“订单已发货”实际上数据库里根本没有这条记录。后来我做了约束涉及事实性输出的内容全部要求模型先调用查询工具获取数据严禁仅凭上下文记忆作答。凡是没有数据支撑的表述必须在回答里明确标注“推测”或“建议核实”。6.2 结构化强制把“自由发挥”的空间关小当任务本身要求精确时我会在上下文里给出严格的输出Schema并让模型先输出一个“证据列表”再输出答案。比如客服Agent回复前强制它列出用户问题、命中的知识条目、结论依据。没有证据条目的回答会被直接拦截。虽然这会让每次输出多花一点token但换来的是“可审计、可纠错”这是生产级Agent的必要条件。7. 上下文可观测性把“玄学”变成debuggable工程最后一个很想强调的点上下文工程没有可观测性就是空中楼阁。很多项目里开发者在调试Agent时像在猜谜——一会儿好一会儿坏根本说不清是哪次请求的哪段上下文出了问题。我从一个失败的教训里学到的经验是为Agent的一套完整链路专门加“上下文日志”。7.1 上下文日志的记录维度每次模型调用之前我都在日志里记录这五类信息当前窗口的token占用总量和比例分布各区块的来源标签比如system、history、retrieval、tool_result每块内容对应的业务主键比如知识库ID、会话ID本轮任务指令的完整文本最终模型输出的引用来源。有了这份日志你才能回答那个最致命的问题——“上次它为什么这么说”。排查“Agent乱说话”的时候第一件事不是改prompt而是翻上下文日志看看它当时到底看到了什么。绝大多数情况都能定位到某一类信息被错放或漏放而不是模型本身出了问题。7.2 断言与拦截机制把错误挡在用户面前之前更进一步的做法是给上下文加载加上“断言机制”。比如检索结果注入前检查和当前用户问题做相关度评分低分直接丢弃知识库命中内容如果过期时间超过阈值标记为“待验证”或直接不入上下文每轮对话结束后记录上下文健康评分低于阈值就触发告警。这套机制我跑顺之后Agent出错的排查时间从小时级降到分钟级。我身边的架构师普遍反馈这是回报率最高的投入。8. 上下文工程的落地清单我在项目中反复验证的几条原则写到这里把这一路踩坑经验浓缩成一份执行清单。每一条都是被实际项目验证过的按优先级从高到低排列先定token预算表再写业务代码。窗口是稀缺资源不预算必失控。对话历史设置硬上限超出即摘要。永远不要让原始历史无限堆积。检索必须经过重排和过滤噪声比缺失更可怕。关键事实类输出强制要求工具调用禁止裸奔式凭记忆回答。每轮调用前问一次“这轮模型真正需要什么信息”不需要的不喂。上下文摘要工具必须独立成工具函数所有步骤共享调用。所有上下文写入和读取都带隔离标识防止多实例互相污染。全链路记日志包含token分布、内容来源、输出证据。没有日志就没有调试入口。这份清单不是理论推演是我把数个Agent项目从demo推进到生产环境后逐步固化的工程约束。上下文工程没有一劳永逸的解决方案它更像一个持续调优的过程——预算在变、数据在涨、模型在换但你只要把“上下文质量”放在和“模型选型”同等重要的位置来对待Agent的稳定性和可用性就会有质的提升。最后再分享一个小技巧我习惯在每个Agent项目启动时先写一份“上下文设计文档”把上面的预算表、记忆分层、生命周期、检索策略、日志方案全部落到纸面。这份文档在后期的排错和交接中帮了极大的忙。上下文工程难的不是某一个点而是把各个环节串成一个自洽的系统。把这个系统搭稳了Agent才真正从“玩具”变成“工具”。