
从零开始搭过几个 Agent 之后我才意识到上下文工程才是决定 Agent 智商上限的关键。标题里写了“深度解析”但其实我更想聊的是实操。很多朋友上来就关心模型选型、Agent 框架、工具调用结果调来调去Agent 该犯傻还是犯傻。后来我复盘了一下问题几乎都出在同一个地方上下文没管好。上下文工程不是什么新词但在 AI Agent 这个体系里它比单纯写 Prompt 要复杂得多。因为 Agent 是多轮交互、多工具协同、多任务并行的系统它的上下文是动态的、会被污染的、会超出窗口的。这篇文章不搞理论堆砌我直接把实际踩过的坑、用过的方案、调过的参数都摊开讲希望帮你少走几周弯路。1. 上下文工程到底是什么1.1 先搞清楚 Agent 的工作方式要理解上下文工程得先清楚 Agent 到底怎么干活。你扔给它一个任务它不会像普通聊天那样一句话回答完事而是会拆解目标、调用工具、观察结果、调整策略可能来来回回好几轮。举个例子你让 Agent 帮你“整理一份竞品分析报告”。它先要搜索资料然后读取网页内容再做对比表格最后生成 Markdown 文件。每一步之间都需要依赖一个东西对话历史。前一步的搜索结果、读取的数据、中间结论都得放进后续的上下文里Agent 才能继续判断“下一步该干什么”。这个对话历史就是上下文的物理载体。上下文工程简单说就是怎么组织、筛选、压缩、编排这些历史信息让模型在每一步都能拿到最需要的、且不超出窗口限制的上下文。我刚上手时犯过一个很典型的错误把所有中间结果一股脑全塞进上下文。结果就是上下文窗口很快被撑爆Agent 开始丢前面的关键信息甚至把上一次搜索的旧数据当成当前结果来用。那时候我还没意识到这不是模型不行是我没做上下文管理。1.2 它和 Prompt Engineering 的区别很多教程喜欢把上下文工程和 Prompt Engineering 混在一起讲这其实会误导人。Prompt Engineering 关注的是“你给模型的那段初始指令怎么写”比如角色设定、任务目标、少样本示例这些是静态的、一次性的。而上下文工程关注的是“整个任务生命周期中每轮该喂什么模型”这包括用户输入、模型输出、工具结果、记忆摘要、检索片段这些是动态的、不断演化的。用个生活化的类比Prompt 是给新员工的第一天培训手册上下文工程是之后每一天的工作日报、会议记录、项目文档管理。手册写得再好如果每天的信息流乱七八糟员工照样干不好活。在 Agent 场景下上下文工程的重要性远超 Prompt Engineering。因为 Agent 根本不是一个静态任务它是动态流程。你甚至可以把上下文工程理解成给 Agent 做记忆管理——哪些该记住哪些该忘记哪些该重点强调都是有讲究的。1.3 上下文工程的四个核心维度我把实际工作中涉及的上下文工程拆成四个维度后面每一章都会围绕它们展开上下文构建初始系统提示词怎么写用户需求怎么结构化工具定义如何注入上下文管理多轮对话如何截断、摘要、压缩不让历史无限膨胀上下文检索需要外部知识时如何把最相关的片段找出来放进上下文上下文编排多个工具、多个任务并行时如何组织每轮实际发送的上下文内容。这四个维度不是孤立的它们共同决定了一个 Agent 的有效上下文利用率。我见过不少项目模型用的顶级款工具也齐全但 Agent 表现就是不如预期原因就是这四个维度里至少有一个是瘸腿的。2. 上下文构建第一步就决定成败2.1 系统提示词的结构化设计很多人写系统提示词就是一段大作文从“你是一个 AI 助手”写到“请务必注意”中间夹杂各种要求。我建议你改用结构化写法把系统提示词当成一个配置文档来写。我目前用得比较顺的模板大概长这样[角色定义] 你是XX领域的资深专家擅长把复杂问题拆解为可执行步骤。 [任务目标] - 接收用户的原始需求 - 判断是否需要调用工具 - 输出结构化结果 [工具使用规则] - 只有需要实时数据时才调用搜索工具 - 工具返回结果必须先总结再使用 - 若工具调用失败如实告知用户不编造结果 [输出格式] - 结论先行 - 使用列表和表格组织复杂信息 - 每个结论附带简要依据 [限制条件] - 不要重复用户指令 - 不要输出与任务无关的内容 - 遇到模糊需求时先提问澄清再执行这么写的好处有三个一是模型更容易“理解自己的职责边界”不会做着做着跑偏去闲聊二是后续想调整某一部分不用重写整段改一个区块就行三是方便程序化拼接比如动态注入用户名、时间、场景标识等信息。2.2 用户需求的结构化预处理用户输入往往是含糊的。比如“帮我看看最近的 AI Agent 趋势”这句话扔给 Agent它能搜出来一堆东西但大概率不是你想要的——你想要的可能是技术趋势、框架热度、应用案例甚至某些特定平台的数据趋势。所以我在实际项目中会在用户输入进入上下文之前先做一次意图识别与需求补全。这一步可以交给模型也可以靠规则模板原始需求: {用户输入} 请将上述需求解析为结构化任务 1. 任务目标一句话说明用户想得到什么 2. 关键约束有哪些限定条件时间、地域、领域、数量等 3. 需要的信息源是否需要搜索、读取URL、查询数据库等 4. 输出要求用户期望的呈现方式报告、表格、代码、摘要等这么做过之后Agent 后续的每一步都有了明确的依据。相当于先把用户的模糊指令翻译成内部可理解的任务清单再塞进上下文。这一步看起来多消耗了一些 token但对后续避免瞎跑非常有帮助。2.3 工具定义要写清楚“触发条件”Agent 的核心能力是调用工具但模型什么时候该调用工具完全取决于工具的描述信息。我在最初搭建 Agent 时工具描述写得极其简单比如“搜索工具输入关键词返回搜索结果”结果模型把所有问题都交给搜索工具连数学计算都去搜。后来我把工具描述改成了带触发条件的版本工具名称: web_search 功能: 搜索引擎查询 适用场景: - 用户需要实时信息、最新新闻、特定数据 - 任务涉及的事实需要外部验证 - 当前知识库中无明确答案 不适用场景: - 纯数学计算 - 代码调试应使用代码执行工具 - 用户只是寻求建议而非事实查询这个改变非常明显。工具调用的准确率提升了Agent 不再为了调用而调用。工具描述本质上也是上下文的一部分而且是指导模型行为的关键上下文值得多花一点功夫写清楚。2.4 动态上下文注入除了固定的系统提示词很多场景需要动态注入一些信息。比如用户的地理位置、当前时间、历史偏好、会话目标。这些信息如果放在系统提示词里写死那每个会话都得重新整一个提示词成本高还不灵活。我的做法是把动态信息放在系统提示词后面的一个独立区块每次会话开始前用代码拼进去[会话动态信息] - 当前时间: 2025-XX-XX XX:XX - 用户偏好: 喜欢简洁回答、重视数据来源 - 本会话目标: 完成竞品分析报告 - 已完成的步骤: 资料收集、竞品初筛这样模型在每个轮次都能知道“自己进行到哪一步了”即使中间插入新问题也不会完全丢失主任务。动态上下文注入是构建阶段最容易被忽视的一环但却是后续管理的基础。3. 上下文管理窗口不够用压缩来凑3.1 Token 计算的现实问题上下文窗口是有限的。GPT-4 级别的模型常见的有 32k 或 128k 窗口听起来很大但实际用起来消耗极快。我拿一个真实的 Agent 任务来估算一下系统提示词约 500 token用户需求结构化解析约 300 token第一次搜索关键词及结果摘要约 800 token第一次工具读取页面正文约 4000 token中间推理过程约 500 token第二次工具调用及结果约 1500 token……三轮工具下来很可能就吃掉了 15k 以上的 token。如果是长任务比如“写一篇一万字的行业分析”光中间过程可能就干到 50k。窗口一满模型就开始遗忘早期内容表现为前后矛盾、参考漏掉、逻辑断裂。所以上下文管理的第一课是别把窗口当无限用要把它当有限资源来计划。3.2 截断策略最基础的保底手段最原始的上下文管理方法就是截断——只保留最近的 N 条消息更早的直接丢掉。这种策略实现简单适合任务短、上下文不太重要的场景。但它的缺点也很明显丢掉的内容里面可能包含任务的核心目标、用户关键约束、早期的重要数据。一旦被截断Agent 就会“失忆”。我建议的截断策略不是按消息条数截断而是按层级截断第一优先级保留系统提示词、用户最终目标、当前子任务指令第二优先级保留最近两轮的工具结果和模型推理第三优先级保留早期但可能仍需要的背景信息可压缩后保留可丢弃重复的中间输出、已总结过的原始内容、调试日志。按这种优先级做截断比单纯取最后 N 条消息要可靠得多。3.3 摘要压缩让历史信息保留“骨架”截断是被动丢弃摘要则是主动提炼。当上下文接近上限时把早先的对话历史交给模型让它生成一段精炼摘要替代原文进入上下文。我常用的摘要指令是这样的请将以下对话历史压缩为摘要保留 1. 用户的核心目标与所有明确约束 2. 已经完成的关键步骤和重要结论 3. 尚未完成的任务与下一步计划 4. 任何用户强调过的格式或风格要求 历史内容: {历史消息列表}这里有个细节很关键摘要不是一次性做好的而是要分级维护。我建议把历史分成几个块每块单独摘要再对摘要做一次更上层的摘要形成树状结构。需要某段细节时再回溯到下一层摘要甚至原始内容。这种分级摘要方案比每次全量压缩要灵活得多。从成本上看每做一次摘要会多花一些 token但对比整个任务跑到一半因为上下文溢出而失败这点成本完全可以接受。3.4 结构化记忆短期、长期、工作记忆分层我的 Agent 里会把记忆分成三层分别管理工作记忆当前任务进行中的中间状态比如“正在分析 A 公司已完成财务数据收集”这部分直接放进上下文中每轮更新短期记忆当前会话中产生的重要结论、用户偏好、关键数据用摘要或结构化字段维护跨轮次注入长期记忆跨会话持久化的用户画像、项目背景、历史偏好存在数据库里需要时检索注入。这三层对应不同的存储方式与注入策略。工作记忆每次直接追加短期记忆在每轮开始时做一次归纳长期记忆通过语义检索按需取用。我踩过最大的坑是把所有记忆塞进 Prompt。结果 Prompt 越来越长关键信息反而被淹没。后来改用分层存储才意识到记忆的价值不在量而在能被准确定位和及时取出。3.5 上下文窗口溢出的兜底方案即使做了压缩和摘要极端情况下还是会遇到窗口溢出。这时我准备了兜底方案任务拆解如果任务本身就超过窗口承载能力先把主任务拆成多个子任务每个子任务单独执行最后汇总结果结果固化先将已产出的中间结果写入外部存储文件或数据库释放窗口空间再继续后续步骤重新摘要对当前整个上下文做一次强制压缩只保留目标、约束、最近结果和下一步计划。这套兜底方案保证我即使遇到超长任务Agent 也不会因为窗口溢出而“崩溃”最多是处理速度慢一些。4. 上下文检索让外部知识精准进来4.1 什么时候需要外部知识注入不是所有任务都需要检索外部知识。我习惯把任务分为三类纯生成型写文案、总结、翻译、头脑风暴这类不需要外部知识内部知识型涉及项目资料、历史文档、个人偏好这类需要局部检索实时信息型最新新闻、市场数据、技术动态这类需要搜索或读取 URL。上下文检索的核心难点不在于“找到相关信息”而在于“在有限的上下文窗口里只放最相关的信息”。把整篇文档塞进去虽然信息完整但 token 消耗巨大而且会稀释重点。RAG 的思路这里完全适用先检索再重排最后只把 Top-K 片段拼入上下文。4.2 检索片段如何选择和排序我在 RAG 流程里常用的是三步走向量检索把用户当前的问题向量化在知识库中找相似度最高的片段重排Rerank用重排模型对候选片段按真实相关性重新打分这一步往往比单纯向量相似度准得多动态选择根据当前上下文剩余空间决定最终放入几个片段。具体放几个片段取决于剩余窗口和问题复杂度。我一般控制在 3 到 8 个片段之间。宁可少放几个高质量片段也不要塞一堆边缘相关内容。检索片段在上下文中的位置也有讲究。我发现把最关键的一个片段放在用户输入之前效果往往比堆在后面更好。因为模型对开头和结尾内容的注意力相对更强中间内容容易被稀释。4.3 工具返回结果的即时压缩搜索工具、网页读取工具返回的内容通常又臭又长。如果直接把整篇网页正文塞进上下文什么都干不了。我建议所有工具的返回结果在进入上下文之前先经过一次即时压缩。我的做法是在工具调用后接一个轻量提取流程原始内容: {工具返回的原文} 请提取与本任务直接相关的信息 - 关键事实和数字 - 引用来源 - 与当前任务目标的关联点 - 需要排除的无关内容 输出为结构化摘要控制在200字以内。这个流程会让每个工具调用增加一次模型调用成本但它换来的是后续每轮都能轻装上阵。实测下来整个任务的成功率和稳定性大幅提升。如果为了省这一步的 token后面上下文爆炸、推理混乱代价反而更高。4.4 引用溯源防止模型“张冠李戴”工具结果被压缩之后有一个风险模型记不清某个数据是从哪来的然后混在一起乱输出。我开发了一个简单但有效的方法给每个工具结果加来源标签。[资料来源: 搜索结果-条目3] 标题: {标题} 链接: {URL} 摘要: {提取的关键信息}就算后续做了摘要压缩我也会在摘要里保留每个关键结论对应的来源标签。这样一来模型在生成结果时如果引用数据我能追踪到具体来源用户也能看到参考链接。Agent 的可信度一下子就上来了不像某些黑盒输出用户根本不知道数据是哪来的。5. 上下文编排多轮多工具下的秩序维护5.1 消息结构的清晰分层Agent 每轮实际发送给模型的上下文绝不是简单的消息列表拼接。我把上下文内容分成几层第1层: 系统提示词固定角色、规则 第2层: 本会话目标用户最新需求长期目标 第3层: 动态上下文时间、用户状态、任务进度 第4层: 工作记忆当前子任务、中间结论 第5层: 检索信息外部知识片段按需加入 第6层: 最近的对话轮次用户问题、模型回答、工具结果这个顺序不是随便排的它遵循了“全局信息在前、局部信息在后”的原则。模型在读上下文时前面内容是理解的基础后面内容是处理当前轮的直接依据。我在调试中发现的规律是如果第5层检索信息和第6层近期对话顺序调换模型偶尔会把检索到的旧信息当成对话历史里的内容导致时间线混乱。分层清晰之后这类问题几乎消失。5.2 工具结果与模型推理的轮流插入多工具并行的场景下上下文会快速膨胀。我采取的策略是每个工具结果之后都接一轮模型摘要或判断而不是让多个工具结果连续堆砌。举例说明用户: 请对比A和B两款AI框架的优缺点 步骤1: 模型判断 - 需要分别搜索A和B 步骤2: 调用搜索A - 返回结果 步骤3: 模型摘要A - 提炼A的核心信息 步骤4: 调用搜索B - 返回结果 步骤5: 模型摘要B - 提炼B的核心信息 步骤6: 模型综合分析 - 输出对比结论如果步骤2和步骤4的搜索结果直接连着塞模型在做第6步时很可能分不清哪些数据属于 A、哪些属于 B。加了“模型摘要”这一步之后每个框架的信息已经结构化后续对比自然不容易混淆。5.3 并行任务时的上下文隔离有一次我让 Agent 同时做三件事查天气、写邮件、安排日程。结果发现它把查天气的结果当成了写邮件的内容输出了一封莫名其妙的邮件。原因很简单三个子任务的上下文混在了一起。从此之后我在并行任务设计时严格做了上下文隔离每个独立子任务维护独立的上下文片段共享的长期目标信息单独存放子任务完成后只将结论和关键产物汇入总上下文。这就像你同时开三个浏览器标签页每个标签页有自己的历史和状态互不干扰。Agent 的并行能力不是靠死记所有内容而是靠合理隔离和汇总。5.4 编排中使用的结构化输出协议为了让模型在每轮输出中能“帮我”完成上下文管理我给模型设定了一套结构化输出协议。在系统提示词中明确要求每一轮模型输出的末尾必须包含一个“上下文状态小结”[上下文状态] - 当前任务进度: 60% - 本轮使用工具: web_search - 关键结论: A框架性能更优 - 待办事项: 完成时间线对比 - 下一步动作: 调用 code_executor 绘制图表这个状态小结会在下一轮被重新注入到工作记忆中。相当于让模型自己给自己留笔记防止中间因为上下文压缩而失忆。实测下来这个做法让 Agent 在长任务中的稳定性提升了非常多。6. 常见问题排查上下文工程踩坑实录6.1 上下文溢出后模型“失忆”现象任务执行到一半模型忘记了最开始的用户目标开始自由发挥。原因历史内容过多早期关键信息被挤出有效窗口。排查思路查看每一轮实际发送的上下文 token 数找出溢出点。很多时候不是一下就溢出的而是多次累积后悄悄越过阈值。解决提前做摘要压缩而不是等到溢出再补救把用户目标放进每一轮上下文的固定位置。这个情况我遇到至少十几次。印象最深的一次是让 Agent 跑一个 12 步的数据分析流程到第 9 步时它突然开始分析一个完全不相关的指标我一看上下文记录初始任务目标已经被挤到非常靠后的位置了。后来我把“用户目标”强制提到第2层并且每轮都重新写入问题就再没出现过。6.2 工具结果混乱模型张冠李戴现象模型把 A 工具的结果说成 B 工具的结果或者引用错误来源。原因多个工具的结果没有做来源标识模型在长上下文中丢失了来源信息。排查思路逐轮检查工具结果的格式看看是否都有清晰的来源标签。解决工具结果统一带来源头摘要阶段强制保留来源标签。我特别想强调标签要写清楚但不要写得太复杂。以前我试过在每条工具结果前加超大段说明结果模型把说明当正文了反而忽略了真正的数据。现在统一用简短的[来源ID]开头干净利落。6.3 检索内容不相关Agent 被带偏现象明明知识库里有答案但 Agent 没找到反而用了一堆无关信息作答。原因可能是检索的召回率不够也可能是片段切分不合理上下文窗口太小导致片段被截断。排查思路打印出每一轮注入的检索片段人工检查是否相关。解决调整知识库的切分粒度引入重排模型控制注入片段数量。检索不相关的问题在前置的过滤机制上也要下功夫。我后来在知识库的每个片段前都人工添加了标签字段比如“技术”“营销”“财务”然后在检索时根据当前任务类型先做一次粗筛选大幅提升了准确率。6.4 token 消耗过快成本飙升现象任务没跑几步API 账单却涨得飞快。原因上下文没有压缩工具结果全量进入模型多次调用每次都带着完整历史。排查思路统计每轮发送的 token 数找出哪些轮次消耗异常。解决工具结果强制摘要、历史消息按需裁减、动态注入必要的动态信息。token 消耗这件事我在实际项目里总结了一个估算公式单轮成本约等于固定上下文系统历史摘要加本轮工具结果加模型输出。优化的重点永远是降低固定上下文的大小而不是纠结于本轮输出的几个 token。6.5 模型反复调用同一工具死循环现象Agent 陷入无限循环调用同一个工具好几遍结果还是同一个。原因模型没有记录“已经调用过什么工具、拿到了什么结果”所以重复执行。排查思路看上下文里是否有工具调用记录。解决在工作记忆中加入“工具调用历史”每次调用后更新记录如果重复调用模型会发现自己已经拿到了该结果。这个问题的根子在于上下文里缺少“状态意识”。我后来在编排层强制加了一个“步骤序号”字段Agent 的每一步都有编号模型在生成下一步时会先查看编号有效避免重复动作。7. 上下文工程的工具选型与落地经验7.1 框架层面怎么选目前主流的 Agent 框架都会内置一些上下文管理能力但普遍做得比较简单多数只是把历史消息传给模型如果超了就截断。选框架时我会重点看几点是否支持自定义消息结构能否在系统提示词之外动态插入内容是否有内置的摘要压缩策略工具结果是否可以在进入上下文前做钩子Hook处理是否支持记忆模块扩展。对于轻量级项目自己写上下文管理逻辑完全可控。项目规模大了之后比如有多个知识库、多类工具、多用户场景则建议基于主流框架做二次开发而不是从零造轮子。7.2 评测方法怎么判断上下文工程改好了上下文工程优化到底有没有效果不能靠感觉要开会话级的评测。我的做法是维护一组建好的评测用例每个用例都包含多步任务、工具调用、长上下文场景。每次改动上下文策略后都在这组用例上跑一遍对比成功率、关键信息召回率、错误率。评测指标方面建议关注任务完成率最终有没有产出用户想要的结果关键信息保留率早期信息在后期是否仍被引用工具调用正确率该调的时候调不该调的时候不乱调平均耗时与 token 成本优化后成本有没有下降。我一般在改完上下文工程配置后会连续跑一周的线上日志抽一部分会话做人工标注重点看模型是否记住了该记住的信息是否漏了该用的数据。7.3 上下文工程的迭代节奏最后想分享一个迭代节奏上的经验不要追求一次性把上下文工程做到完美先跑通再优化。第一版直接用最基础的截断策略能完成任务就算成功。第二版加上工具结果摘要和来源标签。第三版再做分层记忆和动态注入。每一步都有稳定的效果增量而且出问题时也容易定位是哪个环节引入的。我在实际工作中见过不少团队一上来就整巨复杂的记忆系统结果上下文结构臃肿模型反而表现更差。上下文工程的目标是让模型在每一步都轻松拿到正确信息而不是把系统做成信息堆积场。7.4 一个重要原则留白上下文工程非常讲究“留白”。不要想着把每个知识碎片都塞进去也不要为了用工具而用工具。上下文本身就是一笔预算花在刀刃上才有价值。我记得有次调一个客户项目对方要求把几十页产品手册全部塞进上下文让 Agent“无所不知”。结果 Agent 反而变得保守、回复冗长、抓不住重点。后来我只保留产品卖点、FAQ 和竞品对比三个核心片段Agent 的应答质量瞬间回到正常水准。上下文宁可少而精也不要多而杂。最后说点实在的上下文工程不是一条固定公式它更像是一门和模型窗口、任务类型、工具设计紧密耦合的工程手艺。同一个方案在对话型任务里很稳在深度研究型任务里可能撑不住。我自己也在持续迭代每次跑长任务或者碰到 Agent 行为异常都会先从上下文入手排查是不是该保留的丢了是不是该压缩的没压是不是检索进来的内容是噪音。如果你现在正被 Agent 的“不稳定”“傻里傻气”“上下文超限”折磨我建议你从今天开始把上下文当成一等公民来对待。先给每轮实际发送的内容打日志看看模型到底看到了什么再逐步引入摘要压缩、来源标签、状态小结。这几步做完你会明显感觉到 Agent “变聪明了”——其实不是模型变了是你把它的工作台整理干净了。