
做AI Agent开发有一段时间的人基本都会遇到同一个问题上下文好像永远不够用模型回答的“幻觉”越来越多上下文一长就报错同一套提示词换个场景就彻底失灵。我之前在团队里负责过一个带工具调用的AI代理项目前期只顾着把功能跑通上下文全靠手撸全局变量硬撑到几十轮对话之后上下文里的垃圾信息比有效信息还多模型开始“自说自话”工具调用也频繁出错。后来我意识到AI代理的上下文不只是一个“提示词拼接”问题它是一个需要像软件代码一样去设计、测试、部署、维护的工程对象。也就是说上下文必须有自己的开发生命周期。这篇文章就聊聊我是怎么从“能用”走向“可控”的也会把上下文生命周期里涉及到的采集、构建、评测、监控和回收这几个核心环节讲清楚适合正在做Agent、RAG应用或AI工作流并且被上下文问题折磨过的开发者参考。1. 为什么你的AI代理上下文必须谈生命周期1.1 上下文不是“越多越好”它也是需要治理的资产很多开发者一开始的心态是上下文窗口有128K那我就把所有东西都塞进去反正模型能处理。真实情况远没有这么乐观。模型的能力边界很大程度上被上下文质量限制着塞进去的干扰信息越多模型回答的偏差就越大。举个例子我在项目里给AI代理接入了一个文档查询工具工具返回了整篇合同文档的全文大约2万token而用户真正关心的只有其中一条赔偿条款。模型在处理时既看到了赔偿条款也看到了很多无关的合同背景、送达条款、争议解决条款。最终它给出的赔偿建议里莫名其妙混进了“争议解决方式建议仲裁”的内容这就对用户形成了误导。这种问题不是模型能力不足而是上下文治理没做好。我们需要像管数据库一样管上下文清楚每一条进入上下文的文本是什么角色、从哪来、什么时候该保留、什么时候该删除。没有生命周期就只剩下脏数据的无限堆积。而且上下文量越大单次请求的延迟和经济成本也会非线性上升。我对接过一个本地模型服务在上下文10K token时单次推理大约1秒到50K token时直接涨到4秒多。原本用户觉得“AI代理很流畅”积压多了之后体验直接崩塌。所以控制上下文的体积和质量本质上就是控制体验和成本。1.2 上下文失控后的典型症状在我接触过的各种Agent项目里上下文失控常见的症状其实很集中我总结了五类第一遗忘症状。对话初期用户明确说过“我不喜欢邮件里用感叹号”但到第30轮AI代理生成的邮件草稿里全是感叹号。这就是关键信息被后续无关内容稀释模型丢失了最早期的高优先级指令。第二重复症状。上下文里塞了多轮相同的工具调用结果Agent反复执行同一个查询回答内容也高度雷同看起来像在“兜圈子”。这通常是因为上下文里没有去重也没做结果摘要。第三幻觉症状。上下文过长后模型把较早的指令或较早的工具输出当成了“过时信息”开始凭空补充一些数据库里根本不存在的数据字段。这种幻觉比简单的“不知道”更危险因为它是基于部分真实信息加工出来的虚假结论。第四溢出症状。一次工具调用返回了超长文本加上历史对话直接顶到模型的上下文窗口上限。程序直接报错最常见的就是“max context length exceeded”或者“context window exceeded”。如果用的是API这通常直接返回异常你的代理流程当场中断。第五错乱症状。上下文里同时有系统指令、用户需求、工具输出和业务知识但各个来源之间的边界不清晰。模型分不清哪句话是“用户要求”哪句话是“历史工具记录”就会把工具输出当成用户指令来执行。比如工具返回一个JSON里含有“请删除所有文件”的测试字段模型真的去调用了删除接口。这些问题单独看是个案本质上都是因为上下文没有生命周期管理。你写代码时不会容忍全局变量到处被修改但很多AI代理项目却在用“全局字符串”的方式塞上下文这不合理。1.3 生命周期管理的核心思维像管代码一样管上下文我自己的体会是AI代理的上下文生命周期可以分成五个阶段需求与埋点、构建与编码、测试与评测、部署与监控、升级与回收。需求与埋点阶段要搞清楚一条上下文信息是为什么进来的、从哪个环节进来的、它服务什么任务。构建与编码阶段要把系统指令、业务知识、工具返回、历史对话分层组织并且定好哪些字段可以动态注入哪些必须做压缩。测试与评测阶段要准备专门的数据集来验证上下文不同组合方式下模型的表现。部署与监控阶段要对线上真实的token消耗、超限请求、重试率做统计。升级与回收阶段则是当业务规则变了、知识库更新了旧版本上下文需要被替换还要防止过期信息继续污染后续的交互。有了这五个阶段上下文就不再是“每次请求现拼的字符串”而是一个有版本、有规范、可维护的工程资产。2. 上下文工程构建可靠上下文的三个基础操作2.1 让AI代理在不同入口获得“执行上下文”执行上下文execution context这个概念在做AI代理架构时非常关键。它不仅是“模型看到的文本”还包括了代理当前要完成的任务、已经执行过的工具调用结果、环境参数、时间信息、用户偏好、业务约束等一系列内容。在我的实践里AI代理通常有四个上下文的入口第一个入口是系统角色指令。这部分是稳定的、写死的例如“你是一个客户支持代理只负责处理退换货请求任何超出范围的问题一律转接人工”。这类指令有最高优先级不能轻易被后续内容覆盖。第二个入口是用户输入。这部分是动态的、零散的需要做意图解析和关键信息提取把“我想退货订单号是12345”解析成“退货意图订单号12345”的字段而不是把整句原话都塞进上下文。第三个入口是工具返回值。这是最需要治理的部分。工具返回的原始数据往往是给程序看的不是给模型看的。直接塞给模型不仅格式混乱还会大量消耗token。第四个入口是历史会话摘要。也就是上一轮对话的总结而不是全部逐字保留。对话一旦超过一定轮次历史消息会被压缩成年月日、用户意图、已完成操作、待办事项等结构化摘要。为了避免这几个入口的数据互相污染我通常会在上下文中明确标注每一段的“来源标签”例如[SYSTEM_STATE]放系统指令和业务规则[USER_REQUEST]放用户当前请求的解析结果[TOOL_RESULT:search_contract]放工具返回的摘要结果[HISTORY_SUMMARY]放历史会话摘要这个做法类似于给JSON字段加命名空间模型看到标签后就能分辨哪些内容是“指令级别的”哪些内容只是“参考资料”哪些内容已经“过期需要忽略”。2.2 模型感受野之外AI代理如何“指定上下文”不少朋友问过我像“Cursor怎么把上下文给到AI”“AI编码如何指定上下文”这类问题本质上是在问如何把项目代码、历史修改记录、技术栈说明这些信息用模型容易理解的方式放进上下文中。这里有一个经验AI代理指定上下文时应该遵循“动态选择、静态构建、精简注入”三个原则。动态选择是指不要把所有文件内容都加载进去而是在每个交互节点先做一次检索只挑选与当前任务相关的文件片段。我做过一个项目代码库有几千个文件但实际定位一个bug可能只需要看3到5个文件。如果全量塞入不仅上下文爆炸模型还会被无关代码干扰。静态构建是指把项目结构的目录树、技术栈说明、编码规范这一类长期不变的元信息单独做成一个“项目描述块”每次请求时固定注入。这样做的好处是模型有了一个“全景认知”再去理解具体的代码补丁就会容易很多。精简注入则是指对每个要注入的代码片段做预处理。我会把代码里的注释、空行、以及未被引用的import语句删掉只保留核心函数和调用链。如果是需要模型生成代码我会提供函数签名、已有的依赖接口、期望返回格式而不提供整个文件的全部实现。像FastAPI项目里常用的依赖注入在AI代理里也有对应的“依赖上下文”概念。你可以把用户认证信息、数据库连接状态、当前API版本号这类系统级信息做成独立的依赖上下文对象在每次代理执行时自动注入这样就不会挤占真正的“任务上下文”。2.3 上下文压缩省token也省心的关键手段上下文压缩在整个生命周期里占据重要地位。我见过很多团队一开始不重视压缩结果API账单高得惊人。实际上压缩上下文既是为了节约token也是为了降低模型的认知负担。常用的压缩策略有四种第一种是截断策略。最简单的做法是把最早的历史消息直接丢弃只保留最近N轮。这个策略实现简单但容易丢失早期重要信息。我会在截断前先判断历史摘要中是否有“需要长期记住的用户偏好”如果有先把这部分并入稳定上下文。第二种是摘要策略。用模型对历史对话做一轮摘要生成结构化的记录包括用户目标、已完成事项、关键偏好、当前状态。这就像开了一场会议之后发一份会议纪要之后参会者只需要看纪要不需要重新听3个小时的会议录音。第三种是结构化裁剪策略。对工具返回值进行字段级裁剪删掉模型不需要的字段比如数据库返回里的created_at、updated_at这类时间戳。也可以在工具端就设置参数比如只返回前10条结果而不是全部100条。第四种是向量检索策略。适用于RAG场景把知识库切片做向量化把全局的上下文换成“与当前问题最相似的TopK段落”。这个方案效果比较稳但引入向量数据库后整个架构的复杂度也会上升需要额外维护切片和索引。在实践里我比较推荐做“分级压缩”即系统指令和业务规则永远不压缩历史对话按轮数做分段摘要工具结果按重要性做结构化裁剪。优先级从高到低是系统指令 用户即时指令 待执行的工具参数 工具结果摘要 历史轮次摘要 历史原始消息。3. 实操过程给AI代理上下文搭建一套完整生命周期管线的步骤3.1 第一步梳理输入源绘制上下文数据流图凡事开始前先画图可能显得不酷但没有一张数据流图后面迟早会乱套。我习惯用表格整理上下文来源上下文来源示例稳定性必填性是否需要压缩系统指令角色设定、权限边界高必填不压缩用户画像地区、偏好中选填按需摘要业务知识库段商品说明、FAQ中视场景向量检索取TopK对话历史多轮消息记录低必填轮次摘要工具实时结果数据库查询、API返回低视场景字段裁剪外部环境状态时间、天气、库存低选填只取关键字段运行日志与报错异常信息、追踪栈低报错时必填截取关键行表里每一条都标注了稳定性、必填性和压缩策略后续写代码时就能清楚知道哪部分应该固定注入哪部分应该动态检索哪部分应该直接丢掉。对于AI代理中“上下文数据流图的分解”我的理解是数据流不能只有一条“用户消息—模型回复”的单线而是要有多个分支。典型的流程是用户输入先进入“意图识别模块”识别结果决定是否需要调用工具、是否需要发起检索、是否需要查询历史摘要最后才把组装好的上下文发送给模型。也就是说上下文是分阶段、按需组装出来的不是请求来的时候一次性堆出来。这一个阶段最容易出错的地方是很多人会忽略“系统指令”和“业务知识库”的重叠。系统指令描述的是“我的代理该如何表现”业务知识库描述的是“代理应该知道哪些事实”两者一定要分开存储和维护否则改一句话模型可能连身份角色都搞错了。3.2 第二步设计上下文版本化结构上下文版本化是我个人非常推崇的做法。既然代码有Git版本管理上下文也应该有版本记录。实操上我会在每次构造上下文时给整个“上下文包”附一个版本号例如ctx_v1.3.0。系统指令、业务知识库、历史摘要策略都跟随这个版本号走。发布新版本后旧版本至少在线上保留一周方便出问题时快速回滚。上下文包的数据结构大致是这样{ context_version: ctx_v1.3.0, created_at: 2025-06-18T10:30:00Z, session_id: conv_123456, blocks: [ { block_type: system_instruction, source: static_config, content: 你是一个订单处理助手只能操作当前用户的订单禁止访问他人数据。 }, { block_type: user_state, source: profile_service, content: 用户偏好喜欢简洁回复不接受邮件中带感叹号。 }, { block_type: tool_result, source: order_service.get_by_id, content: 订单12345状态已发货物流单号SF1234567890, truncated: true }, { block_type: history_summary, source: summarizer.v2, content: 用户此前询问过退款政策已告知7天无理由退货。 } ] }有了这个结构开发者调试问题时就能很快定位“哦模型答错了是因为tool_result里的物流信息被截断了”而不是一头雾水地去猜“为什么模型会给出这个答案”。上下文版本化还有一个好处就是方便做A/B实验。当我想验证“新的摘要策略是否比旧的摘要策略更好”时可以同一批真实对话分别走v1.2和v1.3版本然后对比两个版本的最终回答质量和用户满意度。这在传统的开发流程里很难做到但因为它本质上是“代码版本对比”所以很自然就能融入已有的CI/CD生态。3.3 第三步实现上下文构建器而不是写死字符串很多Agent项目最初的实现是直接拼接一个超长字符串但随着业务逻辑变复杂这种方式几乎无法维护。我会建议用“上下文构建器”Context Builder模式把不同的信息块拆成独立组件。这里的核心是设计一个链式API# python context ContextBuilder(session_idconv_123456) context.add_system(load_system_instruction(order_assistant_v3)) context.add_user_state(user_profile.get_preferences(user_id)) context.add_tool_result(order_service.get_order_detail(order_id), max_length500) context.add_history(history_summarizer.compress(messages, max_tokens800)) final_messages context.build()每个add方法内部处理各自的数据清洗和压缩逻辑互不干扰。将来想替换某个模块只需要替换这一个方法的实现不需要改动整个流程。即使不用Python这个设计思想在所有语言中都适用。核心是把“上下文如何组装”的逻辑从“业务代码”中剥离出来单独成为一层。这样调试时我们面对的是一堆结构清晰的数据块而不是一个万行字符串。另外我建议在构建器内部统一维护一个token预算表。例如系统指令占1000 token用户状态占200 token工具结果占800 token历史摘要占1000 token合计3000 token。超出预算时构建器会自动触发压缩逻辑或报错提醒。这就跟数据库连接池有max_connections一样提前设好上限避免意外。3.4 第四步建立评测集给上下文变化做回归测试上下文一旦改动影响的是所有下游行为。所以必须有“上下文评测集”这相当于给AI代理做单元测试和回归测试。我建评测集的思路是收集真实线上遇到的问题把它们整理成一个个“输入—期望行为”的样例对。例如用户说“我要退订单12345”期望AI代理只查询该订单并引导用户进入退货流程不推荐任何相关商品。用户连续询问5个不同的商品库存期望AI代理在第6轮仍然记得第一个商品名称并且能回答“你之前问过A商品现在要买吗”。用户问“你们上班时间是几点”期望即使上下文里没有相关信息AI代理也不能编造必须回答“我暂时无法确认”并转人工。评测集建好之后当上下文压缩策略调整或系统指令改动我用同一批评测集跑一遍看通过率是否变化。通过率下降说明这次改动引入了回归问题。通过率持平或上升才允许发布上线。在工具调用场景里评测集还可以进一步细化为“是否正确调用了工具参数”。例如用户说“帮我找最近的维修点”如果上下文工程做得好模型解析出的工具参数应该是{latitude: ..., longitude: ...}而不是又生成了一堆没有任何实际调用的说明。这个评测步骤看似耗时实际上是大规模部署AI代理的必经之路。不做评测就敢直接改上下文的基本都会在线上遇到“上一版还好好的这版突然傻了”的问题。3.5 第五步运行时监控与上下文回收上下文并不是一次构建就完了运行时监控同样重要。我监控的指标主要有四类第一类是上下文体积趋势。统计每轮请求的token消耗观察它在长时间会话中是否持续上涨。如果持续上涨说明压缩策略失效或历史截断没生效需要及时介入。第二类是超限率。记录“超过上下文窗口限制”的次数一旦超限率升高就要排查是哪个工具返回了超大结果或历史摘要损失了太多早期信息。第三类是有效信息占比。这个指标需要人工抽样或让另一个模型来做。比如每100轮抽样10轮看模型回复里的关键信息是否与用户输入高度相关。如果用户花了8轮问一个问题模型在第8轮还答非所问那就是有效信息占比过低。第四类是上下文污染率。观察是否存在系统指令被用户输入覆盖、工具输出被当成用户请求的情况。这类问题靠自动化指标不好直接检测一般要靠专门的异常追踪链路把每次工具调用的前后上下文快照保存下来出问题后做回溯。上线阶段的另一个重点是“上下文回收”。当一轮会话结束时我不建议直接把整个上下文丢弃。因为用户可能会隔几分钟回来继续问。更稳妥的做法是把最终状态写入会话存储下次用户回来时先恢复用户偏好、历史摘要、当前意图三元组而不再恢复之前的原始工具输出。这有点像你在IDE里写代码不用的import会被自动清理状态由“脏乱临时变量”变成“干净持久化变量”。没有这一步AI代理的长期会话能力会随着轮数增加而急剧退化。4. 常见问题与排查技巧实录4.1 上下文超出限制Claude、GPT、本地模型都逃不开的坎很多用户在使用各种大模型的时候都会遇到“超过上下文限制会怎么样”的问题。从API行为来说结果很直接请求被拒绝返回一个错误不会给你部分回答也不会自动截断。我在一个本地模型项目里就踩过这个坑。本地模型通过FastAPI提供服务请求体里有messages数组其中一条历史消息特别长模型直接就报了上下文溢出错误。那一次我的处理方式分三步第一步先检查是不是有单条消息特别长。一条消息如果占据了上下文窗口的80%那就不是“压一压历史消息”能解决的而是要从源头限制工具返回值的大小。第二步在构建器里给每条消息设单独的max_length超过长度就做截断或摘要。有点像给每条SQL查询加LIMIT不让你一次取回全部数据。第三步对历史对话整体执行“滑窗摘要”策略。保留最近5轮原始消息更早的消息统一合并成一段摘要。这样无论用户聊多少轮上下文总长度都保持在上限内。我还遇到过一个比较隐蔽的问题模型API返回的错误信息本身也会占用上下文。当时我做了重试机制但错误信息被原样塞回了上下文。于是下一次调用时模型不仅没解决原问题反而把“上次的错误信息”当成了背景知识。解决方法是错误信息只保留关键字段而且打上[SYSTEM_ERROR]标签再设置一个特殊指令提示模型忽略系统错误信息只关注用户需求。4.2 上下文错乱与幻觉加大约束条件而不是只调temperature聊到“大模型能力边界幻觉、上下文、温度”这个话题我会说很多人试图通过调低温度来解决幻觉这在某些场景有效但换个场景可能会让模型变得更“机械”输出反而更差。更核心的解决思路是约束上下文而不是调整模型参数。模型产生幻觉的一个重要原因是上下文里的信息边界模糊模型分不清“哪些是事实哪些是臆测”。所以我会在系统指令里加这样一段注意你只能回答基于系统指令、用户输入和工具结果中明确存在的信息。如果这些来源中不存在相关信息必须直接声明“没有相关信息”禁止推测或编造。与此同时我会给工具结果加上时间戳和置信度级别{ source: inventory_api, timestamp: 2025-06-18T10:00:00Z, confidence: 0.95, data: 库存数量为12件 }模型看到“这个数据是来自API的有时间戳置信度高”就不太容易把内部臆测混进回答。这和人一样当你看到标注了来源和时间的新闻你对它的信任程度和处理方式就会不同。关于温度我的经验是在需要“确定性”的工具调用场景温度设置为0或接近0在需要“创意生成”的内容场景可以适当调高。这个参数不能替代上下文工程它只负责控制模型的随机性所以不要指望调低温度能弥补上下文里的脏数据。4.3 服务端报错An error occurred during SSL communication这个报错我遇到过好几次。表面上看起来是通信层面的问题比如证书、网络代理、防火墙但在AI代理的上下文工程里它还可能有一个非常隐晦的原因你传递给下游服务的“执行上下文”里包含了过期的认证信息或错误的代理配置。我在一个FastAPI服务里集成本地模型时曾经在代码里配置了一个转发代理但代理地址写错了。每次调用模型服务都会在后面偷偷带上这个错误代理导致SSL握手失败。这个问题的排查思路是首先把报文打印出来看完整错误信息确认是哪个环节的SSL失败。其次确认目标服务地址的证书是否有效。如果是自签名证书Python的requests库会直接拒绝需要显式指定verifyFalse或添加CA_BUNDLE。再次检查是否有全局代理环境变量影响了内部调用很多情况下服务部署在容器里环境变量HTTP_PROXY、HTTPS_PROXY会干扰内部API调用。不过要强调一点这属于常规技术排查与网络访问策略无关我们只是调试本地服务之间的通信问题所有请求都在自己的服务架构范围内。这类问题的通用解决思路是分层排查先跳过代理直连目标服务看还报不报错再检查证书再检查上下文里是否加载了过期配置。不要一上来就怀疑模型很多时候恰恰是上下文管道里的一个配置项出了问题。4.4 常见问题速查表我整理了一份上下文生命周期里高频问题的速查表方便各位直接查问题现象可能原因解决方向模型遗忘了早期用户诉求早期关键信息被后续内容稀释将用户偏好提取到独立的高优先级上下文块模型重复调用同一个工具工具结果未缓存或未摘要对工具结果做去重相同参数的结果复用上下文超限报错单条消息过长或历史累积过多对工具输出做字段裁剪对历史做滑窗摘要幻觉信息增多上下文来源边界不清晰加来源标签加时间戳明确禁止编造模型把历史工具输出当用户指令上下文缺少分块标签为每类上下文块打上固定前缀标签上下文版本升级后效果变差缺少回归评测建立评测集上线前跑一遍全量回归本地模型服务SSL报错代理配置或证书问题分层排查网络配置确认服务间通信变量token成本持续上涨压缩策略失效按优先级分级压缩监控每轮token消耗长时间会话后回复质量下降上下文回收机制缺失会话结束后保存结构化摘要下次只恢复摘要4.5 上下文调试时的三件套如果只让我留三条调试经验我会留这三条第一日志里必须能看到每次模型请求的完整上下文。我们项目里有一个“上下文重现面板”传入时间戳或会话ID就能看到这次请求发给模型的具体文本。这样出了问题不会猜而是直接看现场。第二每次改动上下文工程都必须重新跑一遍评测集。任何代码库改动都要跑单测上下文工程也一样。不跑直接上线的基本就是给自己埋雷。第三把“上下文血缘”记录下来。也就是每条进入上下文的业务数据追溯到它来自哪个API、哪个数据库表、哪个人工配置。这个血缘信息可能在日常运维中用不到但一旦线上出了幻觉问题或合规问题它可以救你于水火。5. 从开发期到运行时AI代理上下文后续还能这样迭代上下文生命周期管理不是一个一蹴而就的事我自己也是踩了几次坑之后才慢慢把“生命周期”这个思维固化到代码里。在这套体系运转起来以后我发现迭代方向还能继续延伸。其中一个方向是让本地模型参与上下文预处理。像我之前提到过的我们可以用一个小参数模型先对历史对话做摘要、对工具结果做字段提取再把精简后的内容交给更大更强的模型做最终推理。这样做的好处是能明显降低大模型的token消耗。从实测来看在我自己的项目里同样一轮完整对话经本地小模型预处理后最终进入大模型的token量少了一半回答质量也没有明显下降。另一个方向是探索上下文编排中的动态路由。简单说就是根据用户当前请求的复杂度决定把哪些上下文块放入最终的提示词。比如用户只问了一个商品的价格那就完全不需要把订单历史的20轮摘要放进去。只有遇到复杂任务比如“帮我比较5个方案的风险和收益”才需要把所有相关的业务知识段落和全部工具结果聚合进来。这就像写代码时的按需加载能避免每轮请求都被“全量代码扫描”拖慢。这个方向再往前推一步就是把上下文本身也变成可检索、可组合的“微模块”。背景知识、会话记忆、用户画像、历史决策理由这些以后都可以拆成微模块由调度器根据任务需求动态组合。这样整个AI代理的上下文就从“一次拼一个巨长提示词”变成“按需组装多个小型上下文模块”既灵活又容易调试。写在最后的一点体会如果要把我做AI代理项目最值钱的感悟浓缩成一句话那就是上下文是AI代理的行为边界也是它最大的安全隐患只有把上下文当成严谨的工程对象来对待AI代理才能真正从“玩具”走向“工具”。在实际操作中我强烈建议你从小处入手。不用一上来就给所有会话都上全套生命周期。你可以先拿一个高频场景做试点比如“多轮对话工具调用”的复合场景把上下文构建器、压缩策略、评测集这三件套先搭起来。跑通之后你会发现后面处理其他AI代理项目时方法论可以直接复制效率高得不止一点。这个内容后续还可以往“上下文自动评估器”方向扩展用另一个模型来给每一次上下文组装质量打分把“凭感觉调提示词”变成“按数据调上下文”那就是更大的价值了。