AI Agent上下文工程实战:从概念到性能优化完整指南
发布时间:2026/10/8 4:49:22 锦皓数字建站

很多人刚接触AI Agent时会有一个误解只要模型够聪明Agent的自然就会好用。我自己带过几个项目后可以负责任地说这个想法坑过不少人。模型只是生成能力的基础真正决定Agent能不能稳定跑完一个多步任务的往往是它每次调用时看到的那些上下文——你喂了什么、喂了多少、怎么组织。这也是为什么“上下文工程”这个词最近频繁出现在Agent相关讨论里它几乎成了Agent系统性能的天花板。这篇文章我想把上下文工程从概念到实操完整拆一遍它到底是什么、在主流Agent架构里如何流转、实际操作层怎么做预算和压缩、以及我自己踩过的坑和Rust方向的高性能实现思路。无论你是在搭第一个Agent原型还是准备把Agent投入生产环境这篇文章应该都能帮你少走不少弯路。1. 上下文是Agent的“记忆”和“工作台”先搞清楚这个东西到底是什么1.1 不止是输入框上下文在Agent里扮演的三个角色大模型本身是无状态的。它不会记住你上一轮说了什么也不会知道你的业务逻辑每次调用都是一次全新的“失忆”开始。上下文就是你在每次调用时塞给模型的那一坨信息看起来只是输入框里的文字但在Agent系统里它实际上是三个角色的叠加。第一个角色是工作台。像你在办公桌上临时摊开的文档、便利贴、计算草稿——Agent执行任务时需要把当前目标、已有的中间结果、工具返回的数据全部摆在上下文中模型才能基于这些“看得见的东西”继续推理。第二个角色是共享记忆。多轮对话或者多步骤任务里Agent需要记住用户前面说过什么、已经完成过哪几步这些历史都要靠上下文来承载。第三个角色是约束规范。系统提示词、输出格式要求、安全边界这些“行为准则”也是上下文的一部分。模型不会天生遵守你的输出格式只有你把要求写进上下文它才会照做。1.2 上下文不是知识它是“现用现取”的临时信息这里要区分两个概念模型本身的训练知识和调用时的上下文。训练知识相当于硬盘里存好的内容知识内化在权重里你无法在运行时直接改上下文则相当于内存每次请求都重新组装、用完即弃。这个区别决定了工程化思路完全不一样。训练知识不够你得去微调、去重新训练成本高、周期长上下文组织得不好你只需要改代码里的组装逻辑立刻就能生效。换句话说上下文工程管的是Agent的“内存管理”而不是“硬盘扩容”。我见过不少团队一遇到Agent效果不好就想着微调或者换更大窗口的模型结果发现问题是旧的错误信息一直被重复塞进上下文污染了后续推理——这种问题换更大的模型根本没有用把上下文整理干净反而立刻见效。1.3 从“能塞进去”到“塞得好”上下文工程的定义很多人理解的上下文工程就是把相关的信息拼起来扔给模型。能用但远不够好。真正的上下文工程要回答三个问题哪些信息值得放信息的排列顺序应该是什么放不下的信息怎么处理2. 模型负责能力上下文负责任务为什么上下文工程和微调解决的是两码事2.1 模型像发动机上下文像方向盘如果非要打个比方模型和上下文的关系很像发动机和方向盘之间的关系。发动机决定了这辆车能跑多快——模型的推理能力、知识广度、指令跟随水平这些是硬实力。方向盘则决定这辆车往哪走——上下文把当前任务的目标、约束、已知条件组装好模型才能在一个明确的框架内输出结果。一辆车只有发动机、方向盘乱晃根本到不了目的地。一套Agent系统只有强模型、上下文一塌糊涂输出就会是车轱辘话来回说、漏步骤、甚至编造中间结果。反过来一个中等水平的模型配上组织良好的上下文完全可能比“大模型加混乱上下文”表现更稳定。这不是玄学而是因为上下文直接决定了模型感知到的任务空间。2.2 微调与上下文工程的关键差异微调和上下文工程都能让模型输出更贴近业务需求但它们解决问题的层次完全不同。我整理了一个表方便照着判断自己该用哪种手段。维度微调上下文工程修改对象模型权重每次调用的输入内容生效速度需要训练和验证周期即时生效改了马上能测成本训练算力、数据标注、人工审核少量开发成本和token调用成本灵活度一种能力需要一次训练同一个模型通过上下文切换不同任务场景可解释性低权重变化难以追踪高每一轮上下文都能翻出来审查适用场景推理模式、输出风格、专业知识固化多轮对话、工具调用、知识检索、格式控制2.3 我为什么建议先做上下文工程在绝大多数Agent场景下上下文工程是比微调回报率高得多的投入。原因很简单你不需要动模型、不需要准备训练集、不需要担心灾难性遗忘代码层面就能看到变化。更重要的是上下文工程的每一次调整都是可回滚的——发现这轮改动让效果变差了切回上一版组装逻辑就行。微调一旦训练完发现问题想回退得重新训练非常痛苦。但这不代表微调没用。业务中需要模型长期稳定保持某种专业输出风格时微调依然是最优解。只是在这之前你值得先把上下文整理干净——很多“看起来需要微调”的问题其实只是上下文里的信息摆放不对而已。3. Agent主流架构里的上下文流转从对话式到规划式3.1 对话式架构上下文随着轮次线性膨胀最基础的Agent形式就是一个多轮对话循环。用户的每一条指令、模型的每次回复、工具调用的每个结果都会被追加进历史记录然后拼进下一轮请求的上下文里。这种架构的实现最简单但问题也最明显上下文窗口是有限的而对话历史是无限增长的。如果没有清理机制几十轮之后要么超窗要么前面的关键信息被截掉。我见过很多新手写对话式Agent觉得窗口200K就高枕无忧结果任务跑到中后段就开始胡言乱语。不是模型疯了是上下文里高质量信息的比例在降低。对话式架构的上下文工程核心就是给历史记录设计一套“淘汰与压缩”的策略而不是任由它膨胀。3.2 ReAct架构思考-行动循环中的上下文更新ReAct是目前最主流的Agent架构之一思路是让模型在一个循环里交替执行“推理”和“行动”两步先想一下当前要做什么、决定调用哪个工具然后查看工具返回的结果、继续下一步推理直到任务完成。在这种架构里上下文是动态更新的——每一轮循环结束后新得到的观察结果要被追加进去作为下一轮推理的依据。ReAct 的上下文工程难点在于“取舍”观察结果往往很长比如一次数据库查询可能返回几百行数据而模型下一轮其实只需要其中的几个字段。如果原样塞入很快上下文就满了而且大量无关内容会稀释注意力。经验做法是在工具返回层做一次“前置压缩”先把原始输出结构化成摘要再进入上下文。3.3 Plan-and-Execute架构规划上下文与执行上下文分离Plan-and-Execute架构把任务分成了两个阶段先由规划器生成一个完整的步骤列表然后执行器按步骤逐步执行。这种架构对上下文的组织方式和前面两种完全不同——规划阶段只需要任务目标和背景知识而执行阶段只关心当前这一步的输入输出不需要看到整个规划文本。把规划和执行拆开上下文就能做得非常干净。执行阶段的上下文窗口只需要容纳当前步骤的描述、相关工具的结果、以及少量的任务背景。这样既避免了整套计划占用大量token又减少了信息干扰。代价是规划质量直接决定了任务上限如果第一步规划错了后续执行得再完美也没有意义。3.4 多Agent协作架构上下文变成消息总线更复杂的系统中你会让多个Agent各自负责一个子任务由一个主Agent负责调度。这时候上下文不再是一条任务线而是一套消息总线。主Agent的上下文里需要包含每个子Agent的状态摘要子Agent的上下文则需要接收主Agent下发的任务描述。如果不同Agent之间共享的上下文格式不统一信息很容易在传递中丢失。我在做多Agent系统时专门用了一个结构化的事件表来统一消息格式每条消息包含发送方、接收方、事件类型、内容摘要、时间戳。这样主Agent在总结进度时不需要去读每个子Agent的完整输出只需要浏览摘要表就够了。多Agent场景下的上下文工程本质上是在设计一套可裁剪的信息交换协议。主流架构对上下文的组织方式各不相同但底层逻辑是一致的——根据任务需求决定当前模型“应该看到什么”而不是把能拿到的信息一股脑都丢进去。4. 实操上下文工程的四个层次预算、分层、检索、压缩4.1 Token预算先弄懂窗口是硬约束上下文工程绕不开token。token是模型处理文本的最小粒度单位不同模型的tokenizer规则不一样中文大概一个字对应1到2个token英文一个单词通常1到2个token。上下文窗口就是模型单次能处理的最大token数这是硬件和模型结构决定的硬上限不是调参能突破的。做Agent时我会先明确“内容”和“预算”的换算关系窗口大小大约能装下的内容量中文典型模型示例4K约2000-3000字早期的GPT系列8K约4000-6000字Gemini Flash等入门版本128K约6-10万字GPT-4o、Claude Sonnet等200K约10-15万字部分长上下文模型这里要特别提醒窗口大不意味着效果好。研究经验和我的实测都表明模型在超长上下文里的注意力会退化窗口中间的细节容易被忽略这被称为“迷失在中间”。所以窗口上限是200K不代表你真就要塞到180K再停止。合理的做法是为每轮请求做预算分配比如总窗口128K时系统指令预留5K工具规范和当前任务描述预留10K检索知识控制在30K剩下空间留给历史摘要和模型输出。给模型留足输出空间是最容易被忽略的点——很多Agent卡在半截输出上其实是输出预算被榨干了。4.2 信息分层不同生命周期的信息各归其位上下文里的信息生命周期完全不同有的只需要存在几秒钟有的需要贯穿几十轮任务。把它们混在一个桶里管理等于让出租车和垃圾车走同一条道。我习惯把信息分三层。短期工作记忆当前任务相关的瞬时信息。包括用户本次的意图、上一步工具返回的结果、模型刚产生的中间推理。这类信息优先级最高要完整保留但任务一旦结束就该清空不进入长期区域。情景记忆多轮对话的结构化历史。原始对话文本不可能无限保留需要做摘要和关键信息抽取。每次对话结束后把这一轮的用户意图、采取的动作、最终结论压缩成两到三句话存进情景记忆区下一轮直接引用摘要而不是完整历史。语义记忆长期知识库。包括产品文档、私有知识库、历史案例等。这类信息的量级通常是十万甚至百万级不可能全部进上下文必须靠检索按需注入。分层管理的核心原则很简单高价值的信息给好位置、给足预算低价值的只保留摘要或干脆索引而不进上下文。4.3 检索注入不是把知识库全搬进去检索增强生成RAG已经是Agent接外部知识的标配了。但有一个细节很多人没意识到检索到的资料从进上下文的那刻起就不再是“中立资料”而是模型推理的依据。检索错了Agent会比没有检索更糟因为模型会把错误资料当成事实基础。控制检索质量的关键在三个环节。第一是分块策略知识文档不能整篇embedding要按语义切块块大小通常在500到1000个字符之间相邻块之间重叠10%到20%避免一个完整概念被拦腰切断。第二是召回的数量控制向量检索返回Top-K之前最好加一个重排模型把语义相关度重新排序只保留高相关的3到5块进入上下文。第三是元数据标注每块内容入库时带上来源、日期、置信度进入上下文后模型才能判断信息的可信程度。我做过一次对比测试同样一个客服Agent不加重排时准确率只有70%出头加重排并限制Top-K后提升到90%而token消耗反而减少了将近一半——因为没用的噪声不进了。4.4 上下文压缩与摘要防止对话无限膨胀对话式Agent做到一定轮数上下文总会不够用。我的处理方法是组合“滑动窗口”和“摘要替换”两道闸。窗口尾部保留最近几轮的完整原文窗口之前的旧内容则被自动压缩成摘要。跑过长任务的开发者应该有这种感觉真正影响后续操作的关键信息其实很少大多数是过程排查时用不上的中转数据。摘要的价值就在于把那些中转信息丢掉只留下结论。工具输出是整个上下文里最容易膨胀的部分。一次API响应可能长达几千token但Agent下一步只需要其中的某个状态码。我的习惯是在工具调用层加上一个“输出压缩器”把原始返回先做结构化处理比如只提取字段名、变化值和错误码再决定是否完整进入上下文。长期跑下来整套Agent的单位任务token成本能降40%以上同时由于上下文更干净成功率还有提升。5. 一次真实的排错过程多步任务“失忆”背后的上下文问题5.1 现场能说不能做三步之后必翻车我测试过一个带知识库和工具调用的Agent让它完成“查询订单状态→根据物流规则判断是否异常→给用户发提醒邮件”这样一个三步任务。现象非常稳定第一步查询没问题第二步判断也能做对但到了第三步模型会忘掉前面查到的订单号还在邮件里写“您的订单可能存在异常”却不说明具体是哪个订单。初始怀疑是模型推理能力不够。但我换更强的模型跑问题依旧于是排除了模型能力把焦点转到上下文上。第三步请求发出去之前我抓取了完整的上下文内容发现第二步的“判断结果”确实在里面但背景知识里一段很长的物流规则说明占据了大量位置而订单信息排在很后面的位置几乎在截断边缘。模型看一眼前面的物流规则再回头找订单号注意力已经被拉散了。5.2 排查链路从现象反推上下文哪里出了问题排查上下文问题我有个固定的三级检查清单一看token分布二看信息排列三看历史污染。第一步统计token分布把上下文里每条内容的占比列出来看是不是占大头的是无关知识、真正核心的执行信息反而被挤在后面。第二步看排列顺序检查高优先级信息有没有被放在上下文的末尾位置——理论上越靠后的内容越容易保留住注意力所以最重要的执行信息应该尽量往后放。第三步查历史污染把过去几轮的消息逐条看一遍寻找有没有错误信息被当成既定事实留了下来。这次的问题恰好同时踩中前两条订单号被放在中段偏后而窗口尾部是无关的规则说明。5.3 根因一历史错误信息污染上下文那次调试还发现另一类问题。第二轮判断物流是否异常时如果Agent第一次调用工具失败它会在上下文里留下一条“查询失败”的记录到第三步模型可能把这个失败记录当成事实推断订单确实异常。这种“错误结论二次传播”比上下文截断更难发现因为单看每轮纪录都有道理但连起来看就会发现模型被自己上一轮的失败结果带偏了。修复方案是为工具调用结果增加状态标注和置信度。工具层返回时统一加一个字段标记异常情况比如“查询失败原因超时”并要求模型在推理时明确引用“哪次查询的哪个字段”作为依据。加了这条规则后模型输出里开始出现“根据步骤1查询到的订单号JD12345”再也不会凭空捏造了。5.4 根因二窗口截断恰好切掉了关键信息另一个高频坑是长文本截断。原始上下文里有一段用户提供的背景文档大概几千字我在组装上下文时直接按窗口上限截断了。问题在于截断位置恰好落在“订单号”三个字之前。窗口截断不像报错那么明显Agent还是能流畅地继续生成但生成内容里缺少关键参数。这个坑很难靠模型侧解决只能从上下文工程侧避免。我的对策是所有进入上下文的高价值信息段落都用结构化的格式包装好并且确保这类字段写在上下文更靠前的位置对超长背景文档不再做暴力截断而是先用摘要模型压缩到规定的长度再放进去。核心原则是宁可压缩不要截断。截断是随机地丢信息压缩是主动地保留高价值信息。5.5 修复效果同一组测试用例的对比数据修复完这几处之后我用同一组50条测试用例跑了回归对比结果如下指标修复前修复后任务成功率56%88%单任务token消耗约4200约2900关键参数遗漏率30%4%相比于换更大的模型这轮改动几乎零成本却带来了决定性的提升。这个过程也验证了一件事Agent的很多“失忆”问题不是记忆容量不够而是上下文里放错了东西——放太多低价值信息、排错了顺序、或者把历史错误留在了里面。6. 用Rust做上下文引擎高性能方向的一种选择6.1 为什么要考虑Rust而不是只有Python上下文工程做到生产级别一定会遇到性能和成本压力。Python生态在Agent领域最丰富但它不是唯一选项。如果Agent服务的并发量上来了上下文组装涉及的大量字符串拼接、对象拷贝、检索排序Python的GIL锁和内存开销会变成瓶颈。Rust在这个场景有几个突出优势。第一是零成本抽象和高性能上下文操作本质上是高频小对象的创建、复制、淘汰Rust能把这些操作的花销压得非常低又没有GC的停顿。第二是内存安全上下文引擎里跑着用户数据最怕指针悬垂或者数据竞争Rust编译器在编译期就能把这些风险挡掉。第三是并发友好Agent系统往往要同时处理多个会话的上下文Rust的所有权模型配合无锁数据结构能让多会话并行处理时更放心。6.2 核心模块设计环形缓冲和消息通道设计一个上下文引擎最核心的是数据结构和消息流通路。会话历史这种有上限的内容我倾向用环形缓冲区来管理——固定容量写入新数据时自动覆盖最旧的数据不需要频繁地分配和释放内存性能稳定。配合一个固定上限的预算计数器每一轮写入前检查总token数超了就触发压缩任务。多Agent协作场景下消息传递可以走异步通道。子Agent把结果发进通道主Agent的上下文管理器订阅需要的事件把事件摘要写入自己的上下文。异步的好处是不同Agent的时钟不必同步主Agent不必等所有子任务都完成再去组装上下文吞吐量会平滑很多。我把一段最小可用的上下文管理器结构写成了示意代码。它不保证直接编译但思路足够参考。struct ContextManager { // 固定容量的环形缓冲保存最近的对话历史 working_memory: RingBufferMessage, // 摘要存储保存被压缩掉的旧历史 summary_store: VecSessionSummary, // 检索器的引用用于按需拉取长期记忆 indexer: Arcdyn Indexer, // token预算上限 budget: usize, } impl ContextManager { fn build_context(self, query: str) - VecMessage { let mut ctx Vec::new(); ctx.push(self.system_prompt()); // 放入最近的对话历史 ctx.extend(self.working_memory.iter().cloned()); // 按相关性检索外部知识 let docs self.indexer.search(query, 5); ctx.extend(docs); // 检查预算超出则压缩最旧的非关键消息 Self::enforce_budget(mut ctx, self.budget) } }环形缓冲和预算检查是这里的关键。working_memory只保留最近N条消息summary_store保存旧历史的压缩摘要当build_context发现超出预算时就把最早但还有价值的信息摘要化而不是简单丢弃。6.3 Rust的Agent生态现状能用但要自己拼装Rust在AI Agent方向已经有了一些基础组件。有做向量检索的库有做ORM和异步运行时的高质量工具也有越来越多的模型SDK开始提供Rust语言绑定。但坦率地说整个Agent框架层还远不如Python的LangChain、LlamaIndex那么完整。你选择Rust大概率不是图它开箱即用而是图它在运行时性能和资源占用上的控制力。适合的场景包括高并发会话网关、上下文转发服务、嵌入到高性能后端服务里的Agent组件。如果是快速验证原型我还是建议先用Python把逻辑跑通再考虑把瓶颈模块用Rust重写。7. AI Agent学习路线里上下文工程应该排在第几层7.1 从Prompt到架构我的推荐顺序经常有人问AI Agent学习路线我的经验是“Prompt基础→上下文工程→架构设计→专项优化”这个顺序。先能写好单个调用再学会管理多轮之间的信息流转然后才谈得上设计一套多任务或多Agent架构。很多教程上来就讲LangChain、讲多Agent协作结果学习者连“为什么需要记忆管理”都没概念学完只是会调API。具体到上下文工程的学习建议按这四个阶段推进。第一阶段能解释token是什么会估算一段文本的token数懂得查询不同模型的窗口上限第二阶段能手动组装出一个包含系统指令、用户需求、工具说明的上下文并且学会排查基本信息污染问题第三阶段能做信息分层给会话加摘要和滑动窗口控制住token增长第四阶段能接检索理解分块、向量化、重排的关系并能设计一套多级记忆体系。7.2 实练项目做一个多步工具调用的Agent学习上下文工程光看文章效果有限我的建议是亲手做一个带工具调用的Agent。最经典的练习项目是“让Agent根据聊天记录自动整理待办事项并发送通知”——这要求它理解对话、抽取关键信息、调用外部工具、然后汇总结果每一环都在锻炼上下文组织能力。工具调用到了中段你自然会碰到上下文膨胀和关键信息丢失的问题然后被迫去做摘要、做压缩这种“被需求逼着学”的效果远好过按文档逐章刷。想再进阶一层可以给Agent加一个知识库让它基于私有数据回答问题。你会发现纯靠“把所有资料塞进上下文”走不通必须去设计分块策略、索引结构和检索重排。到这一步你对上下文工程的理解就超越了大多数只会写Prompt的同行了。7.3 上下文工程之后还有什么值得关注等上下文工程的基本功扎实了再往上看值得关注的方向是专门跑评估体系和路由机制。评估体系要回答“我的上下文组织方式是否真的变好了”这需要一整套可重复的测试集来衡量上下文质量。路由机制则是说面对不同类型的任务动态选择不同的上下文组装策略而不是一套模板打天下。这些方向都建立在上下文工程的基础之上但也对系统设计能力提出了更高的要求。回到上下文工程本身我这些年最大的体会是任何上下文方案都要先想清楚信息的生命周期。如果是一条一次性的工具返回结果就别费劲把它存成长期记忆如果是用户最核心的需求再占预算也要放进上下文。上下文工程做久了本质上就是在做成本和准确度之间的权衡而能把每一项信息都安排到它该去的位置Agent系统的表现一定会给你惊喜。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。