从提示工程到上下文工程:编写、筛选、压缩、隔离
面向AI智能体的上下文工程课程:为何提示工程不够用,上下文窗口如何填充,四种策略,工具用的RAG技术,Claude Code。
凡是构建过智能体的人大概都见过同样的情况:在最初的几步中,它的表现相当不错——会选择合适的工具,逻辑清晰,并且专注于完成任务。但到了第15步或第20步左右,它的表现就开始走下坡路。它会忘记任务要求,使用与任务无关的工具,或者开始产生质量低下的结果。
人们通常首先会怀疑模型本身,但更多时候问题出在呈现给模型的内容上。决定向模型展示什么、以何种形式以及何时展示,这被称为上下文工程,对于智能体构建者而言,这正逐渐成为最宝贵的技能之一。
以下内容将介绍什么是上下文工程以及为什么智能体需要它、几乎所有技术都遵循的四种策略、上下文出错的四种方式、针对系统提示和工具定义的具体建议、将这些策略整合起来的分阶段工作流程,以及 Claude Code、Manus、ChatGPT Agent 和谷歌的 Agent Development Kit 分别是如何处理这一问题的。
从提示工程到上下文窗口中的上下文工程
提示工程是为语言模型编写优质指令的技巧:清晰地表述内容、提供示例、指定角色。对于仅有问答的简单对话,这通常就已经足够了。
智能体改变了局面。它不会一次性给出答案,而是会逐步浏览、调用 API、编写代码并执行指令,有时甚至需要数十步,整个过程无需人工干预。每一步都会产生输出,所有这些输出都会被纳入模型的上下文之中,而该上下文的容量是固定的。
因此,上下文工程就是围绕模型来设计整个信息系统。这包括系统提示词、工具定义、之前工具调用的结果、对话历史等内容,在每一个步骤中都需要考虑。Anthropic 的工程团队将上下文定义为从模型中采样时所包含的令牌集合,而上下文工程则是指优化这些令牌在实现预期结果方面的有效性。简而言之,智能体应在恰当的时间以恰当的格式获取正确的信息。
Anthropic也将此视为提示工程之后的自然发展阶段。所有与提示工程相关的原则依然适用(清晰的指令、良好的示例、结构化的格式),此外还增加了新的层次:工具、外部数据、消息历史、内存以及动态状态。提示工程便成了其中的一个子集。
时机至关重要。Gartner预计,到2026年底,40%的企业应用将配备特定任务的AI智能体,而2025年的这一比例还不到5%。这些智能体用动态系统取代了静态提示和固定的检索流程,在该系统中,每一次工具调用、检索到的文档以及做出的决策都会被整合到一个窗口中,其中包含用户并未直接要求的内容。那些学会管理这一系统的团队往往能打造出持续可靠的智能体,因为他们不再将问题归咎于模型本身,而是意识到问题源于输入数据。
作为工作记忆的上下文窗口
LangChain给出了一个生动的类比:将大语言模型视作一种新型操作系统——模型相当于负责思考的CPU,而上下文窗口则相当于RAM,即工作内存,用来存储模型当前能够看到的所有信息。正如电脑的运行速度会在RAM占满时变慢,智能体的推理能力也会在其上下文窗口变得拥挤时下降。
这种现象有一个专门的名称,即“上下文衰退”。Chroma测试了18种前沿模型,包括GPT-4.1、Claude 4、Gemini 2.5和Qwen3,发现随着输入长度的增加,所有模型的性能都会下降,即便远未达到厂商宣称的极限。那些上下文窗口容量为20万token的模型,在输入5万token时就已经会出现明显的性能下降。这种下降并非突然出现,而是一个渐进的过程。Anthropic自身的技术文档也得出了相同结论,将性能下降视为一种渐变现象。
原因在于变换器的工作机制。每个标记都会关注其他所有标记,从而产生 n² 个成对关系。随着窗口大小的增加,模型处理所有这些关系的能力被分散,就好比要求某人记住数量不断增多的物品。最终有些信息会被忽略。
另一个被广泛研究的现象是“中间内容丢失”。刘领导的研究小组发现,注意力分布呈 U 形。上下文开头和结尾的内容容易被回忆起来,而中间的内容则容易被遗漏,当相关段落从开头移到中间时,准确率会下降三十多个百分点。想象一下,某个智能体的初始指令被五万多个工具输出内容所覆盖,那些指令实际上已经消失了。
从业者们总结出了一些经验法则。Claude Code的用户反馈称,当处理时间达到窗口容量的40%到60%左右时,输出质量就开始下降,远早于任何硬性限制出现的时间。
哪些因素会占用空间
有七种类型的信息会在智能体的上下文中争夺空间:
- 系统提示词,即智能体的身份标识:包括行为规则、控制流程以及针对不同任务类型的指导说明。对于智能体而言,它远不止一句“乐于助人的助手”的描述,还能决定整个系统的运作方式。
- 工具定义。智能体可能调用的每个工具都需要相应的架构描述,说明其功能、所需参数以及使用时机。
- 工具输出结果。每次调用都会产生相应的输出内容。获取的网页内容可能包含五千到一万个标记,文件读取后的内容也是如此。
四种核心策略,以RAG和Claude Code为例
在时间有限且会逐渐减少的上下文窗口中,关键问题在于哪些信息可以纳入、哪些必须排除以及哪些会被压缩。LangChain这一广为引用的框架将所有上下文工程技术分为四类:写入、筛选、压缩和隔离。一旦熟悉了这些分类,几乎任何遇到的技术都能归入其中之一。
写入
智能体会遗忘信息。当完整上下文被压缩后,相关信息就会丢失,如果智能体没有在其他地方保存这些信息,它们就彻底消失了。写入机制旨在为智能体提供在上下文窗口之外保存信息的方法,它主要有三种常见形式。
草稿本是一种笔记工具,智能体可在任务执行过程中使用它来记录临时发现、决策以及日后可能需要的信息。Anthropic开发了一种“思考”工具,为Claude提供了一个专门用于分析问题的空间,在tau-bench基准测试中,它在某些任务上的性能提升了多达54%。
规则文件则起到持久化程序记忆的作用。Claude Code的用户应该熟悉CLAUDE.md这类文件。这些文件会在每次会话开始时加载,作为固定准则,涵盖项目的架构、规范、测试方法以及需要注意的事项,从而确保基本内容不会被遗忘。
记忆提取功能允许智能体将事实、偏好和学到的模式存储在基于文件的系统中,并在后续会话中随时调取,而无需重新处理这些信息。
选择
只有当恰当的笔记在恰当的时刻出现时,它们才有用。选择意味着为智能体提供当前步骤所需的资源,而非它可能用到的所有东西。拥有数十种工具、庞大知识库以及多轮历史记录的智能体无法一次性加载所有内容,因此必须有人来决定哪些信息是相关的,而关键问题在于由谁来做出这个决定。
在传统的RAG系统中,是由系统来做出决定的。问题出现后,系统会检索文档并将其放入提示词中,模型则没有发言权。而在智能体驱动的RAG系统中,智能体自己决定要搜索什么、使用哪些工具、如何优化查询,以及何时停止搜索。检索过程因此变成了一种迭代过程,这很合适,因为在长期任务中相关性的判断会不断变化,只有智能体才知道自己下一步需要什么。
LangChain和Pinecone都将可调用的记忆分为三种类型。情景记忆本质上是以往处理类似情况时的少量示例;语义记忆则是智能体所学或被告知的事实存储;程序记忆则是诸如上述规则文件之类的固定行为指令。一个设计良好的智能体会根据具体步骤从这三种记忆中获取信息。
工具会带来最严重的选择难题。拥有四十多种工具时,可能在开始任何工作之前就有上万个标记的定义内容存在于上下文中。正如下文的失败案例所示,工具过多不仅会浪费空间,还会让模型陷入混乱。
解决办法是将RAG技术应用于工具描述本身,通过语义搜索筛选出当前步骤可能用到的少数工具。一篇名为RAG-MCP的论文对此进行了测试,发现工具选择准确率从约14%提升到了43%,提升了两倍多,而提示词数量则减少了大约一半。
Anthropic给出的通用建议是采用混合方式:为提升速度,预先加载少量必要的材料,比如CLAUDE.md文件,其余内容则由智能体在需要时再获取。实际上,这意味着智能体会保存文件路径、查询语句和链接等轻量级参考信息,只有在某一步骤需要时才会打开大量内容。通过预先加载基础信息并按需获取其余内容,既能保持系统高效,又不会让智能体陷入信息缺失的困境。
压缩
即便有良好的筛选机制,窗口仍会不断被填满。想象一下,某个智能体进行了二十次工具调用,产生了八万个标记量的输出内容、历史记录以及推理轨迹,其中大部分它已经处理过了。这些旧数据依然占用空间,分散注意力,还会增加成本和延迟。这又是上下文腐化问题,而压缩技术通过保留重要信息的同时削减标记量来解决这一问题,可以在三个环节实现。
在信息进入上下文之前。 分块功能可将大型文档拆分成更小的连贯部分,重新排序则确保只有最优的部分进入窗口。工具输出也可在加入主上下文之前即时进行总结。
在智能体运行期间。总结对话是一种常用技巧:通过每次交流后更新摘要,可以简洁地记录迄今为止的所有内容。另一种流行的混合方式是逐字保留最近的十条消息,因为可能仍需要精确细节,而将更早的消息进行总结。另一种选择则是使用硬编码规则直接删除旧消息,一旦达到大小阈值就将其移除。Claude Code具备自动压缩功能,当窗口容量达到95%时会总结整个对话历程,以此作为安全保障。理想情况下,压缩应在事前完成,而非在紧急情况下才进行。
在智能体使用完某样东西之后。最简单的解决办法是清除工具的运行结果。如果某个工具执行了十五步操作,而智能体已经根据其输出采取了行动,那么这些原始文本就可以被删除。很久之前获取的完整网页可以用一行摘要替代,或者直接移除。
隔离
隔离正是让多智能体系统能够正常运行的关键。假设有一个智能体在单次长对话中负责研究、规划、编码、测试和调试工作。它的上下文会逐渐填满,但更严重的问题是信息污染——在实现阶段开始时,研究阶段进行的文件搜索结果仍然存在,而这些旧资料此时就成了干扰因素,会在模型需要编写干净代码时分散其注意力。
解决方法是为工作的不同部分分配独立的上下文窗口。
显而易见的方法是使用子代理。父代理会将特定的任务——比如查找所有与身份验证相关的文件——交给在独立窗口中运行的子代理处理。任务完成后,子代理仅返回简化的摘要,而繁琐的搜索过程则留在子代理内部,不会影响父代理。
另一种方法是状态模式隔离,如LangGraph中所实现的那样。代理的状态被设计为不同字段存储不同类型的上下文,模型只能看到与当前步骤相关的字段。工具的运行结果可以存放在模型无法直接看到的后台字段中,直到有特殊操作将其呈现出来。这样无需启动额外的代理即可实现精细控制。
简而言之,这些策略包括写入、选择、压缩和隔离,后续的所有方法都是应用了其中一种或多种策略。
代理为何会失败
故障模式能告诉我们应当避免什么。2025年中期,Drew Breunig撰写了一组具有影响力的两篇系列文章,指出了在情境日益复杂时智能体出现故障的四种不同方式。
上下文污染。某种幻觉或错误进入上下文后会被反复引用。可能是某个工具返回了错误数据,或是智能体在五步之前做出了错误的推断。这个错误会一直存在于上下文中,智能体会在此基础上继续处理,而由于智能体会不断迭代自己的输出,每一个错误步骤都会进一步加剧问题。解决方法是进行剪枝:在新的信息出现时主动删除过时或矛盾的信息,在工具输出(尤其是来自外部来源的)进入上下文之前对其进行验证,而在智能体从错误中恢复后,要压缩那些失败的尝试,这样在只有解决方案重要的时候,就不会再保留那些毫无意义的十步调试过程。如果任由这些被放弃的尝试存在,它们会不断诱使模型回到那些已经失败的方法上。
上下文干扰问题。当上下文长度过长时,模型会过度依赖最近的信息,而忽视训练中学到的内容。它不再尝试创造新内容,反而反复使用近期见过的模式,重复过去的行动,无法形成新的计划。解决方法仍是那条通用建议:即便上下文范围很广,也要积极进行总结和删减。
上下文混淆问题。模型会捕获到多余的内容,从而降低响应质量。典型的例子就是工具混淆现象。有一项基准测试在GeoEngine基准上使用了量化后的Llama 3.1 8B模型。当有全部46种可用工具时,尽管上下文长度仍在模型承受范围内,模型仍无法正常工作;而当仅使用19种工具时,模型则能正常运行。这些工具虽然都在处理范围之内,但数量过多,导致模型无法清晰地进行推理。解决此问题的方法是动态工具管理——根据智能体所处的阶段筛选合适的工具,并通过RAG-MCP风格的检索器为每一步挑选出相关的工具。
上下文冲突。在任务执行过程中收集到的新信息与现有上下文中的内容相矛盾。系统提示可能与检索到的文档内容不一致。智能体无法调和这些矛盾,因而行为会出现不一致性——有时遵循某一来源,有时遵循另一来源,有时还会做出与两者均不符的举动。解决方法是明确设定权威层级:系统提示优先于检索到的事实,检索到的事实优先于对话历史。在引入新信息之前,需先将其与现有内容进行比对验证,并使用XML标签或清晰的标题等结构化方式,以便模型明确每条信息的来源及其可信度。
好消息是,为问题命名通常能揭示相应的解决策略。针对“污染”问题可用压缩和剪枝来解决,针对“分心”问题可用压缩来处理,针对“混乱”问题可用选择机制,而针对“冲突”问题则可通过结构化的写作与选择来解决。归根结底,所有方法都离不开“编写、选择、压缩、隔离”这四个步骤。
给智能体的系统提示
向智能体发送提示与向聊天机器人发送提示有显著区别。聊天机器人的提示主要用于设定语气:要友好、简短。而智能体的提示则用于定义其架构,详细说明控制流程,即如何处理不同类型的任务、哪些工具适用于何种情况、出错后应采取什么措施以及适用哪些安全限制。它更像是为自主员工制定的职位描述。
Anthropic提到要在恰当的尺度上制定规则,存在一个“适中的区间”。规定得过于严格会显得僵化。试想这样一条规则:每当用户提到账单、要求退款且金额超过一百美元时,就必须调用工具X。但这种规则会在所有未被预见的边缘情况下失效。规定得过于模糊同样糟糕。“要提供帮助并使用合适的工具”这样的指示对智能体毫无帮助,因为它不知道哪些工具适用于何种情况,也无法在没有明确信号的情况下做出决策。理想的状况是规则具体到足以引导自主行为,同时又足够灵活,让模型能够在新情境中运用判断力。应依靠强大的启发式方法,而非僵化的规则。
一些实用的习惯有助于做到这一点:
- 为提示语设定结构,使用XML标签或Markdown标题来区分背景信息、操作指令和工具使用指南。
- 从最简版本开始,通过失败案例不断迭代。让代理在真实任务上运行,观察它在哪里出错,然后针对这些具体问题添加相应的指令,而非试图提前预测所有边缘情况。
- “最简”并不等同于“简短”。复杂工作流程的提示语可能长达数千个标记,但这没关系,只要每个标记都有其存在的必要。
- 使用少样本示例。展示各种典型且正确的工具选择、合理推理以及规范的多步骤执行案例,比用文字描述所有规则更为有效。
工具定义
每个可调用的工具都需要一份说明其用途、参数及使用场景的架构文档。一个好的定义应当是自包含的、能容错且指令清晰的,而其代价则是额外的上下文空间。
在实际应用中,各种工具越来越多地通过MCP(模型上下文协议)进行连接,这是一种让智能体能够访问外部工具和数据的标准化方式。有一个用于GitHub的MCP服务器,一个用于数据库,还有一个用于文件系统,所有这些工具都通过统一的接口提供功能。问题在于,由于添加工具如此容易,人们往往会过度使用。当有四五个服务器相连时,定义内容可能在执行第一步之前就占据数千个标记。
默认的建议是只保留最基本的必要工具集。如果智能体确实需要大量工具,有两种方法可以实现扩展。
第一个例子来自 Manus,这是个智能体平台。他们建议不要在对话进行过程中添加或删除工具,背后有个许多开发者并不了解的原因:KV缓存。当文本片段被传递给大语言模型时,模型需要为每个片段计算键值表示,这一过程成本很高,因此服务提供商会将这些数据缓存起来。如果多次调用之间的上下文开头部分相同,服务提供商会直接复用已缓存的计算结果,仅处理新增的文本片段,这样既更快也更省钱。
如果在多次调用之间重新排列或修改上下文的前半部分,缓存就会失效,所有数据都需要重新计算。使用 Claude Sonnet 时,已缓存的输入文本片段每百万个仅需0.3美元,而未缓存的则需3美元,两者相差十倍。对于每个任务要执行三四十次调用的智能体来说,这种差异会很快显现出来。
因此,Manus更倾向于使用工具掩蔽而非工具移除。所有定义都保留在缓存的前缀中,但某些工具会被标记为当前阶段不可用。这些定义虽保留以维持缓存稳定性,但智能体知晓不应使用它们;而统一的命名前缀则有助于其对工具类别进行分类推理。
第二种方法是之前提到的基于RAG的选择方式:仅检索与当前步骤相关的工具,正如RAG-MCP论文所示,这种方法能使准确率提升三倍以上,同时将token使用量减少一半。这两种方法互为补充——掩蔽适用于规模适中的工具集,而检索则适用于规模极大的工具集。
这两者背后都遵循着一个核心原则:静态内容位于上下文的顶部,即系统提示、工具定义以及各轮对话之间不会发生变化的内容;而动态内容(历史记录、当前步骤、智能体状态)则位于底部。
整合所有要素的分阶段工作流程
无论是对现成的编程助手还是自建的智能体,这些原则都适用。唯一的区别在于你是自行设计工作流程,还是构建智能体来执行该流程。
HumanLayer的首席执行官Dex Horthy在AI Engineer Code Summit上做了一场演讲,介绍了一种能够清晰展现上述所有内容的 方法。据称,他的团队曾利用该方法在短短7小时内为一个大型的Rust代码库添加了约三万五千行代码。他将这种方法称为“频繁有意压缩”。这项工作被刻意分为多个阶段,每个阶段都会生成一个紧凑的成果,比如结构化的Markdown摘要,而每个新阶段都会在仅包含该成果的独立窗口中开始。这样做的目的是有意将窗口内的内容控制在大约40%到60%之间。
第一阶段:研究。在编写任何代码之前,该代理会先探索代码库:读取文件、追踪数据流,并梳理与任务相关的架构。子代理负责执行原始的搜索和分析工作,因此所有的 grep 查询结果和文件内容都仅存在于它们的界面中,不会影响到主界面的内容。这就是隔离机制。该阶段的输出是一个研究文件,即一份包含文件路径、函数签名、现有模式以及潜在问题的简洁 Markdown 文档。由于这些研究结果会被保存在界面之外,这也属于写作过程。之后上下文会重置。原始的研究内容可能占用了界面的60%到80%,而最终生成的研究文件则将其占用比例降至15%到20%左右。这就是压缩机制。
第二阶段:规划。会打开一个全新的窗口,其中仅包含研究文件和问题描述,智能体便在这个干净的界面基础上起草详细的实施计划。这也是进行人工审核的最佳时机——在此发现的逻辑错误很容易修正,因此任何开发自主智能体的人都应该在此环节设置人工介入检查点。
第三阶段:实施。另一个新的窗口仅显示计划内容,智能体便按照计划逐步执行。对于需要多轮压缩的任务,progress.md文件会记录已完成和剩余的工作内容,这又涉及一次文本写入操作。
大多数实际生产系统都采用类似的设计方式。
真实产品如何处理上下文
Claude Code。 Anthropic开发的命令行编程助手是文档记录最为完善的案例之一。它采用混合检索机制:在每次会话开始时预先加载CLAUDE.md文件以提供基础上下文,而glob和grep等工具则用于对代码库进行即时查询。该系统不会预先索引所有内容,而是按需探索。当资源利用率达到95%时便会触发自动压缩功能,同时保留架构决策信息以及最近访问过的五份文件。它能够为复杂的子任务创建具有独立工作空间的子助手,还有记忆工具可在不同会话之间持续保存信息。其设计理念是采用最简单且有效的方案,相信模型能够自行判断所需信息,并为其提供相应的工具来获取这些信息。
Manus。 这是一种对基础设施要求更高的方案,对于需要服务数十万用户、且效率至关重要的通用智能体而言十分合适。它的核心特点是基于KV缓存排序机制,通过保持各轮对话中的前缀稳定性来实现最大程度的缓存复用,同时采用屏蔽工具而非直接移除的方式。观察结果压缩流程会在数据进入智能体上下文之前对其进行处理。持久化的待办列表用于记录状态,而文件系统则充当被移除上下文的溢出存储空间。
ChatGPT Agent。 这是OpenAI在Operator基础上开发的智能体,其架构与两者均有不同。它基于“计算机使用智能体”模型,采用以图形界面为主的处理方式。而非通过文本指令调用工具,它是通过可视化浏览器来操作,截图会以快照形式纳入模型分析的上下文,同时还会结合之前生成的截图及操作记录。这就带来了不同的挑战——由于视觉元素的处理成本较高,该智能体必须谨慎决定保留多少截图。OpenAI利用强化学习来寻找高效的工具使用策略,在数千台虚拟机上进行训练,而非硬编码规定何时使用何种工具。Deep Research与Operator能够共享状态,从而实现浏览、文本分析及代码执行之间的流畅切换。 与以代码为中心、依赖文本工具且窗口较大的 Claude Code 相比,这款工具更注重可视化且功能更为通用。两者都需要进行上下文构建,但面临的问题及解决方案各不相同。
谷歌的智能体开发工具包。 ADK 采取了最为原则性的架构理念,为智能体上下文制定了三项设计原则:将存储与展示分离,因为持久化的状态与特定 API 调用中显示的内容并不相同;使用明确的转换机制,即通过有名称、有序的处理器以可测试、可组合的步骤来重塑上下文,而非随意进行字符串拼接;默认限制上下文范围,确保每次模型调用仅能看到最少必需的信息,除非明确包含,否则不会有任何内容进入上下文。这样一来,上下文构建就被视为一条具有明确阶段的流程,而非不断追加提示语的方式。
通用的上下文处理流程
纵观这些平台,每个智能体轮次都会出现相同的流程:
- 收集候选信息:用户输入、历史记录、工具输出、检索到的文档以及智能体状态。
- 在剩余的令牌预算范围内选择与当前步骤相关的信息。
- 通过总结、截断或重新组织选定的信息来压缩内容以适应限制。
- 为KV缓存的重用对所有信息进行排序,将静态内容放在前面,动态内容放在后面。
- 整合最终上下文并发起调用。
该领域发展迅速,仍有许多需要学习的内容,因此提升能力的最佳方式就是通过实验:构建一些系统,观察其出现的问题并加以调整。
相关阅读
- LLM应用中的上下文工程:结构化输出、工具使用与智能体限制:如何有针对性地构建模型输入:上下文选择、提示词模板、JSON架构、受限解码、工具调用、智能体循环以及有限自主性。
- 生产环境RAG的分块策略:固定大小法、语义分块法与父子节点分块法:全面介绍RAG分块技术,涵盖从固定大小分割、递归分割到父子节点结构、命题划分、延迟分块、RAPTOR算法、表格处理、代码处理以及性能基准测试等内容。