原文: English original · Anthropic/OpenAI 官方

面向 AI agents 的有效上下文工程

发布于 2025 年 9 月 29 日

上下文是 AI agents 的关键资源,但也是有限资源。在本文中,我们会探讨如何有效整理和管理驱动 agents 的上下文。

在 prompt engineering 成为应用 AI 关注焦点几年之后,一个新术语开始进入主流视野:上下文工程。用语言模型构建应用,正在从为 prompt 寻找合适措辞,转向回答一个更宽的问题:“什么样的上下文配置最可能让模型产生我们期望的行为?”

上下文指的是从大型语言模型(LLM)采样时包含的一组 tokens。眼前的工程问题,是在 LLM 固有约束下优化这些 tokens 的效用,从而稳定获得期望结果。要有效驾驭 LLM,往往需要以“上下文”为单位思考。换句话说,要考虑 LLM 在任一时刻可见的整体状态,以及这种状态可能引发哪些行为。

在本文中,我们将探讨正在形成的上下文工程技艺,并给出一个更精炼的心智模型,用于构建可引导且有效的 agents。

上下文工程 vs. prompt engineering

在 Anthropic,我们把上下文工程视为 prompt engineering 的自然演进。Prompt engineering 指的是编写和组织 LLM 指令以获得最佳结果的方法(概览和实用的 prompt engineering 策略,可参见我们的文档)。

上下文工程指的是在 LLM 推理期间整理和维护最优 tokens(信息)集合的一组策略,其中也包括 prompt 之外可能进入上下文的所有其他信息。

在早期围绕 LLM 做工程时,prompting 是 AI 工程工作的最大组成部分,因为除日常聊天交互外,大多数用例都需要针对 one-shot 分类或文本生成任务优化 prompt。顾名思义,prompt engineering 的主要关注点,是如何编写有效的 prompts,尤其是 system prompts。

然而,当我们转向构建能力更强、能够跨多轮推理和更长时间跨度运行的 agents 时,就需要管理整个上下文状态的策略,包括 system instructions、工具、Model Context Protocol(MCP)、外部数据、消息历史等。

在循环中运行的 agent 会生成越来越多可能与下一轮推理相关的数据,而这些信息必须被循环地精炼。上下文工程就是一门艺术与科学:从这个持续演化的潜在信息宇宙中,整理出将被放入有限上下文窗口的内容。

Prompt engineering vs. context engineering

与编写 prompt 这种离散任务相比,上下文工程是迭代式的:每当我们决定向模型传递什么内容时,整理阶段都会发生一次。

为什么上下文工程对构建强大 agents 很重要

尽管 LLM 速度很快,也能处理越来越大的数据量,但我们观察到,LLM 和人一样,到达某个点后会失去焦点或产生混乱。关于 needle-in-a-haystack 类型基准的研究揭示了 context rot 这一概念:随着上下文窗口中的 tokens 数量增加,模型从该上下文中准确回忆信息的能力会下降。

虽然一些模型的退化更平缓,但这一特征会出现在所有模型上。因此,上下文必须被视为一种有限资源,并且存在边际收益递减。人类有有限的工作记忆容量,LLM 同样有一个“注意力预算”,用于解析大体量上下文。每引入一个新 token,都会在某种程度上消耗这份预算,也就更需要仔细整理 LLM 可见的 tokens。

这种注意力稀缺来自 LLM 的架构约束。LLM 基于 transformer 架构,它让每个 token 都能在整个上下文中关注到其他每个 token。对于 n 个 tokens,这会产生 n^2 个两两关系。

随着上下文长度增加,模型捕捉这些两两关系的能力会被摊薄,从而在上下文大小和注意力聚焦之间形成天然张力。此外,模型的注意力模式来自训练数据分布,而在训练数据中,较短序列通常比长序列更常见。这意味着模型对跨整个上下文的依赖关系经验更少,专门处理这类依赖的参数也更少。

Position encoding interpolation 之类技术可以让模型通过适配原始训练时较小的上下文来处理更长序列,不过对 token 位置的理解会有所退化。这些因素造成的是性能梯度,而不是断崖式下降:模型在较长上下文下仍然很强,但与较短上下文中的表现相比,在信息检索和长程推理上可能精度更低。

这些现实意味着,周密的上下文工程对于构建强大 agents 至关重要。

有效上下文的构成

既然 LLM 受有限注意力预算约束,好的上下文工程就意味着找到尽可能小、信号尽可能高的一组 tokens,使其最大化某个期望结果出现的概率。把这个实践落地远比说起来难,但在下文中,我们会围绕上下文的不同组成部分,说明这一指导原则在实践中意味着什么。

System prompts 应该极其清晰,并使用简单、直接的语言,在适合 agent 的抽象高度上呈现想法。合适的抽象高度,是两种常见失败模式之间的 Goldilocks zone。在一个极端,我们会看到工程师在 prompt 中硬编码复杂、脆弱的逻辑,以诱发精确的 agentic 行为。这种做法会制造脆弱性,并随着时间推移增加维护复杂度。

在另一个极端,工程师有时会提供模糊、高层级的指导,既不能给 LLM 提供期望输出所需的具体信号,又会错误地假设双方拥有共享上下文。最佳抽象高度要取得平衡:既足够具体,能有效引导行为;又足够灵活,能给模型提供强有力的启发式规则作为行为依据。

Calibrating the system prompt in the process of context engineering.

在光谱的一端,是脆弱的 if-else 硬编码 prompts;在另一端,是过于笼统或错误假设共享上下文的 prompts。

我们建议把 prompts 组织成不同章节(例如 <background_information><instructions>## Tool guidance## Output description 等),并使用 XML 标签或 Markdown 标题等技术来划分这些章节。不过,随着模型能力增强,prompt 的具体格式可能会变得没那么重要。

无论你决定如何组织 system prompt,都应该努力使用最小的信息集合,完整勾勒出你期望的行为。

(注意,最小并不一定意味着简短;你仍然需要在前期给 agent 足够的信息,确保它遵循期望行为。)最佳做法是,先用可用的最佳模型测试一个最小 prompt,观察它在你的任务上的表现,然后根据初始测试中发现的失败模式,添加清晰指令和示例来提升表现。

工具让 agents 能够操作环境,并在工作过程中拉入新的额外上下文。因为工具定义了 agents 与其信息/行动空间之间的契约,所以工具必须促进效率。这既包括返回 token 高效的信息,也包括鼓励高效的 agent 行为。

《Writing tools for AI agents - with AI agents》中,我们讨论过如何构建 LLM 容易理解、且功能重叠最少的工具。类似设计良好的代码库中的函数,工具应该自包含、对错误鲁棒,并且对其预期用途极其清晰。输入参数同样应该描述充分、没有歧义,并发挥模型的固有优势。

我们看到的最常见失败模式之一,是臃肿的工具集:它们覆盖了过多功能,或者在该使用哪个工具的问题上制造模糊决策点。如果一位人类工程师都无法明确说出某种情况下应该使用哪个工具,就不能期待 AI agent 做得更好。正如后文会讨论的,为 agent 整理一组最小可行工具,也能让长交互中的上下文维护和修剪更可靠。

提供示例,也称为 few-shot prompting,是一个广为人知的最佳实践,我们仍然强烈建议采用。不过,团队经常会把一长串边缘案例塞进 prompt,试图阐明 LLM 在特定任务中应该遵循的每一条可能规则。我们不建议这样做。相反,我们建议努力整理一组多样、标准的示例,有效呈现 agent 的预期行为。

对于 LLM 来说,示例就是“抵得上千言万语的图片”。

我们对上下文不同组成部分(system prompts、工具、示例、消息历史等)的整体建议是:有意识地取舍,让上下文信息充分但紧凑。接下来,我们深入讨论如何在运行时动态检索上下文。

《Building effective AI agents》中,我们强调了基于 LLM 的 workflows 与 agents 的差异。自从写完那篇文章后,我们逐渐采用了一个关于 agents 的简单定义:LLM 在循环中自主使用工具。

在与客户共同工作时,我们看到这个领域正在向这一简单范式收敛。随着底层模型能力增强,agents 的自主水平也可以扩展:更聪明的模型让 agents 能独立穿越微妙的问题空间,并从错误中恢复。

我们现在看到,工程师思考如何为 agents 设计上下文的方式正在转变。今天,许多 AI-native 应用会使用某种基于 embedding 的推理前检索,在推理前为 agent 呈现重要上下文,供其进行推理。随着这个领域转向更 agentic 的方法,我们越来越多地看到团队用 “just in time” 上下文策略增强这些检索系统。

采用 “just in time” 方法构建的 agents,不会在前期预处理所有相关数据,而是维护轻量标识符(文件路径、存储的查询、网页链接等),并在运行时用工具动态把数据加载进上下文。Anthropic 的 agentic coding 方案 Claude Code 就使用这种方法,对大型数据库执行复杂数据分析。

模型可以编写有针对性的查询、存储结果,并利用 Bash 命令,如 headtail,分析大体量数据,而不需要把完整数据对象加载进上下文。这种方法呼应了人类认知:我们通常不会记住整个信息语料,而是引入文件系统、收件箱、书签等外部组织和索引系统,按需检索相关信息。

除了存储效率之外,这些引用的元数据也提供了一种高效精炼行为的机制,无论这些元数据是显式提供的,还是凭直觉就能看出的。

对于在文件系统中运行的 agent 来说,tests 文件夹中名为 test_utils.py 的文件,与位于 src/core_logic/ 中的同名文件暗示着不同用途。文件夹层级、命名约定和时间戳都会提供重要信号,帮助人类和 agents 理解如何以及何时使用信息。

让 agents 自主导航和检索数据,也支持渐进式披露。换句话说,它允许 agents 通过探索逐步发现相关上下文。每次交互都会产出可用于下一次决策的上下文:文件大小暗示复杂度,命名约定提示用途,时间戳可以作为相关性的替代指标。

agents 可以一层层搭建理解,只在工作记忆中保留必要内容,并利用笔记策略获得额外持久性。这种自我管理的上下文窗口让 agent 专注于相关子集,而不是淹没在详尽但可能无关的信息中。

当然,这里存在取舍:运行时探索比检索预计算数据更慢。不仅如此,还需要带有明确观点且经过深思熟虑的工程设计,确保 LLM 拥有合适的工具和启发式规则,能够有效导航其信息空间。如果没有适当指导,agent 可能会因误用工具、追逐死胡同或无法识别关键信息而浪费上下文。

在某些场景中,最有效的 agents 可能会采用混合策略:为了速度,先检索一部分数据;随后由 agent 自行判断是否展开进一步自主探索。关于“正确”自主程度的决策边界,取决于任务本身。

Claude Code 就是采用这种混合模型的 agent:CLAUDE.md 文件会被朴素地预先放入上下文,而 globgrep 等原语让它能够导航环境并 just-in-time 地检索文件,有效绕过陈旧索引和复杂语法树带来的问题。

混合策略可能更适合内容变化较少的场景,例如法律或金融工作。随着模型能力提高,agentic 设计会倾向于让智能模型以智能方式行动,并逐步减少人工整理。考虑到这个领域的进展速度很快,对于在 Claude 之上构建 agents 的团队来说,“做能奏效的最简单事情”很可能仍是我们的最佳建议。

面向长时间跨度任务的上下文工程

长时间跨度任务要求 agents 在一系列行动中维持连贯性、上下文和目标导向行为,而这些行动的 token 数会超过 LLM 的上下文窗口。对于持续数十分钟到数小时的连续工作任务,例如大型代码库迁移或综合研究项目,agents 需要专门技术来绕过上下文窗口大小限制。

等待更大的上下文窗口,似乎是显而易见的策略。但在可预见的未来,各种大小的上下文窗口都很可能受到上下文污染和信息相关性问题的影响,至少在追求最强 agent 性能的场景中会如此。

为了让 agents 能够在更长时间跨度内有效工作,我们开发了几项技术,直接应对这些上下文污染约束:compaction、结构化笔记和 multi-agent 架构。

Compaction

Compaction 是这样一种实践:取一段接近上下文窗口限制的对话,总结其内容,然后用这份摘要重新启动一个新的上下文窗口。Compaction 通常是上下文工程中用于提升长期连贯性的第一种抓手。其核心是以高保真方式提炼上下文窗口内容,使 agent 能以最小性能退化继续工作。

例如在 Claude Code 中,我们通过把消息历史传给模型,让模型总结并压缩最关键的细节来实现这一点。模型会保留架构决策、未解决 bug 和实现细节,同时丢弃冗余的工具输出或消息。随后,agent 可以带着这份压缩后的上下文,以及最近访问过的五个文件继续工作。用户获得了连续性,而不必担心上下文窗口限制。

Compaction 的技艺在于选择保留什么、丢弃什么,因为过于激进的 compaction 可能导致细微但关键的上下文丢失,而其重要性只会在之后才显现。对于实现 compaction 系统的工程师,我们建议在复杂 agent traces 上仔细调优你的 prompt。

从最大化召回率开始,确保你的 compaction prompt 能从 trace 中捕捉每一条相关信息;然后迭代提升精确率,剔除多余内容。

一个最容易先清掉的冗余内容例子,是清理工具调用和结果:一旦某个工具已经在消息历史深处被调用过,agent 为什么还需要再次看到原始结果?最安全、最轻量的 compaction 形式之一,就是工具结果清理;它最近作为 Claude Developer Platform 的一项功能发布。

结构化笔记

结构化笔记,或者说 agentic memory,是一种让 agent 定期写笔记,并把笔记持久化到上下文窗口之外的技术。这些笔记会在之后被重新拉回上下文窗口。

这种策略以最小开销提供持久记忆。就像 Claude Code 创建待办列表,或者你的自定义 agent 维护一个 NOTES.md 文件一样,这个简单模式让 agent 能够跨复杂任务跟踪进展,保留关键上下文和依赖关系。否则,这些信息可能会在几十次工具调用中丢失。

Claude playing Pokemon 展示了 memory 如何改变非编码领域中的 agent 能力。

这个 agent 会在数千个游戏步骤中保持精确统计,跟踪诸如“在过去 1,234 步里,我一直在 Route 1 训练我的 Pokemon,Pikachu 已经朝提升 10 级的目标完成了 8 级”这样的目标。即使没有任何关于 memory 结构的 prompt,它也会绘制已探索区域的地图,记住自己解锁了哪些关键成就,并维护战斗策略笔记,帮助它学习哪些攻击对不同对手最有效。

在上下文重置后,agent 会读取自己的笔记,并继续多小时训练序列或地下城探索。这种跨摘要步骤的连贯性,使长时间跨度策略成为可能,而如果只把全部信息保存在 LLM 的上下文窗口中,这是不可能做到的。

作为 Sonnet 4.5 发布的一部分,我们在 Claude Developer Platform 上公开 beta 发布了一个 memory 工具,让 agent 更容易通过基于文件的系统,在上下文窗口之外存储和查阅信息。这允许 agents 随时间积累知识库、跨 sessions 维护项目状态,并引用此前工作,而不必把所有内容都保留在上下文中。

subagent 架构

subagent 架构提供了另一种绕过上下文限制的方法。与其让一个 agent 试图在整个项目中维护状态,不如让专门的 subagents 用干净的上下文窗口处理聚焦任务。主 agent 负责通过高层计划进行协调,而 subagents 则执行深入技术工作,或使用工具寻找相关信息。

每个 subagent 都可能展开大量探索,使用数万甚至更多 tokens,但只返回一份压缩、提炼后的工作摘要,通常是 1,000 到 2,000 tokens。

这种方法实现了清晰的关注点分离:详细搜索上下文被隔离在 subagents 内部,而主 agent 专注于综合和分析结果。这一模式在《How we built our multi-agent research system》中已有讨论,它在复杂研究任务上相比 single-agent 系统显示出显著提升。

这些方法之间如何选择,取决于任务特征。例如:

  • Compaction 能为需要大量来回互动的任务维持对话流;
  • 结构化笔记擅长处理有清晰里程碑的迭代开发;
  • Multi-agent 架构适合复杂研究和分析,在这类任务中并行探索会带来回报。

即使模型继续改进,如何在长时间交互中维持连贯性,仍将是构建更有效 agents 的核心挑战。

结论

上下文工程代表了我们使用 LLM 构建系统方式的一次根本转变。随着模型变得更有能力,挑战不再只是打磨一个完美 prompt,而是在每一步都周密整理哪些信息进入模型有限的注意力预算。

无论你是在为长时间跨度任务实现 compaction,设计 token 高效的工具,还是让 agents 能 just-in-time 地探索环境,指导原则都保持不变:找到最小的一组高信号 tokens,使其最大化你期望结果出现的概率。

随着模型改进,我们概述的这些技术会继续演化。我们已经看到,更聪明的模型需要更少的规定式工程,让 agents 能以更高自主性运行。但即便能力不断扩展,把上下文视为珍贵且有限的资源,仍将是构建可靠、有效 agents 的核心。

今天就可以在 Claude Developer Platform 中开始使用上下文工程,并通过我们的 memory and context management cookbook 获取实用技巧和最佳实践。

致谢

作者为 Anthropic Applied AI 团队成员 Prithvi Rajasekaran、Ethan Dixon、Carly Ryan 和 Jeremy Hadfield,团队成员 Rafi Ayub、Hannah Moran、Cal Rueb 和 Connor Jennings 也有贡献。特别感谢 Molly Vorwerck、Stuart Ritchie 和 Maggie Vo 的支持。