Geek,人工智能、软件工程、架构设计、金融财经、历史人文,佛学爱好者,有一个可爱的女儿

面向 AI Agent 的上下文工程

译自: https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents

在应用人工智能领域,提示工程一直是关注的焦点,而如今,一个新的术语—— 上下文工程—— 开始崭露头角。语言模型的构建不再仅仅是为提示找到合适的词语和短语,而是更多地关注于回答一个更广泛的问题:“什么样的上下文配置最有可能产生我们模型期望的行为?”

上下文 指的是从大型语言模型 (LLM) 中采样时所包含的 Token 集合。当前的 工程 问题在于,如何在 LLM 固有的约束条件下优化这些 Token 的效用,从而持续实现预期结果。有效管理 LLM 通常需要 从上下文的角度思考 ——换句话说,需要考虑 LLM 在任何给定时间点的整体状态以及该状态可能产生的潜在行为。

在这篇文章中,我们将探讨新兴的上下文工程艺术,并提供一个改进的思维模型来构建可控、有效的代理。

上下文工程与提示词工程

在 Anthropic,我们认为上下文工程是提示工程的自然延伸。提示工程指的是编写和组织 LLM 指令以实现最佳结果的方法(有关概述和有用的提示工程策略,请参阅 我们的文档 )。 上下文工程 指的是在 LLM 推理过程中,用于管理和维护最佳 Tokens(信息)集的一系列策略,包括提示之外可能出现的所有其他信息。

一个循环运行的智能体会生成越来越多的数据,这些数据 可能 与下一轮推理相关,而这些信息必须不断进行提炼。上下文工程的 艺术和科学 在于,如何从不断演进的浩瀚信息海洋中,筛选出哪些信息能够进入有限的上下文窗口。

上下文工程与提示词工程的关系

与编写提示的离散任务不同,上下文工程是迭代的,每次我们决定将什么传递给模型时,都会进行内容整理阶段。

为什么上下文工程对构建功能强大的智能体至关重要?

尽管 LLM 速度很快,而且能够处理越来越大的数据量,但我们观察到,它们和人类一样,在某个阶段也会失去焦点或感到困惑。对“大海捞针”式基准测试的研究揭示了 “上下文腐烂” 的概念:随着上下文窗口中词元数量的增加,模型准确回忆上下文信息的能力会下降。

虽然有些模型的性能退化程度比其他模型更缓和,但所有模型都存在这一特性。因此,上下文必须被视为一种边际收益递减的有限资源。与 工作记忆容量有限的 人类类似,LLM 也存在“注意力预算”,用于解析大量上下文信息。每引入一个新的词元,都会消耗一部分注意力预算,这就增加了 LLM 需要精心筛选可用词元的必要性。

这种注意力稀缺性源于 LLM 的架构限制。LLM 基于 Transformer 架构 ,该架构允许每个词元 关注整个上下文中的所有其他词元 。这导致 n 个词元之间存在 n²个成对关系。

随着上下文长度的增加,模型捕捉这些成对关系的能力会逐渐捉襟见肘,从而在上下文大小和注意力集中度之间产生一种天然的矛盾。此外,模型的注意力模式是从训练数据分布中发展而来的,而训练数据分布中短序列通常比长序列更为常见。这意味着模型在处理上下文范围内的依赖关系方面经验较少,并且缺乏专门的参数。

位置编码插值 等技术允许模型通过将其适应最初训练的较小上下文来处理更长的序列,尽管这会降低模型对词元位置的理解能力。这些因素造成了性能的梯度变化,而非断崖式下降:模型在较长的上下文中仍然保持着很高的能力,但与在较短上下文中的表现相比,其信息检索和长程推理的精度可能会降低。

这些现实意味着,周密的上下文工程对于构建有能力的智能体至关重要。

有效上下文的剖析

鉴于 LLM 的注意力预算有限,良好的上下文工程意味着找到尽可能小的高信号词元集合,以最大化预期结果的概率。实现这一目标说起来容易做起来难,但在接下来的章节中,我们将概述这一指导原则在上下文的不同组成部分中的实际意义。

系统提示词应极其清晰,使用简洁明了的语言,并以适合智能体理解的方式呈现概念。这种“合适的理解程度”介于两种常见故障模式之间,堪称“黄金地带”。一种极端情况是,工程师在提示中硬编码复杂且脆弱的逻辑,以精确地引导智能体的行为。这种方法会造成系统脆弱性,并随着时间的推移增加维护的复杂性。另一种极端情况是,工程师有时提供模糊不清、过于笼统的指导,无法为 LLM 提供期望输出的具体信号,或者错误地假设了共享上下文。最佳的理解程度应达到平衡:既要足够具体以有效引导行为,又要足够灵活以提供强大的启发式方法来指导模型的行为。

上下文工程过程中的系统提示词校准

一方面,我们看到脆弱的 if-else 硬编码提示;另一方面,我们看到过于笼统或错误地假设共享上下文的提示。

我们建议将 prompts 组织成不同的部分(例如 <background_information><instructions>## Tool guidance## Output description 等),并使用 XML 标记或 Markdown 标题等技术来区分这些部分,尽管随着模型功能的增强,prompts 的确切格式可能变得不那么重要了。

无论您如何构建系统提示词,都应该力求使用最少的信息完整地描述预期行为。(请注意,最少并不一定意味着简短;您仍然需要预先向模型提供足够的信息,以确保其遵循预期行为。)最好先使用最佳模型测试一个最少的提示,看看它在您的任务上的表现如何,然后根据初始测试中发现的故障模式,添加清晰的说明和示例来改进性能。

工具使智能体能够与其环境交互,并在工作过程中获取新的上下文信息。由于工具定义了智能体与其信息/行动空间之间的契约,因此工具必须能够提高效率,这体现在两个方面:一是返回高效的信息,二是鼓励智能体采取高效的行为。

《为人工智能代理编写工具——与人工智能代理一起》 一文中,我们讨论了如何构建易于语言学习者理解且功能重叠最小的工具。与精心设计的代码库类似,工具也应具备自包含性、容错性强,并且其预期用途清晰明确。同样,输入参数也应具有描述性、无歧义,并能充分发挥模型的固有优势。

我们最常见的故障模式之一是工具集过于臃肿,涵盖的功能过多,或者导致在选择工具时出现模糊不清的决策点。如果人类工程师都无法明确判断在特定情况下应该使用哪个工具,就不能指望人工智能代理做得更好。正如我们稍后将讨论的,为 agent 精心挑选一套最小可行工具集,也有助于在长期交互过程中更可靠地维护和精简上下文信息。

提供示例,也称为 few-shot prompting,是一种众所周知的最佳实践,我们一直强烈建议这样做。然而,团队常常会在提示中塞入一大堆极端情况,试图阐明 LLM 在特定任务中应遵循的所有规则。我们不建议这样做。相反,我们建议努力精心挑选一组多样化的、规范的示例,以有效地展现智能体的预期行为。对于 LLM 而言,示例胜过千言万语。

我们针对上下文各个组成部分(系统提示、工具、示例、消息历史记录等)的总体指导原则是:要深思熟虑,保持上下文信息丰富且简洁明了。现在,让我们深入探讨如何在运行时动态检索上下文。

上下文检索和自主搜索

《构建高效的 AI 代理》 一文中,我们重点阐述了基于 LLM 的工作流与代理之间的区别。自那篇文章发表以来,我们逐渐倾向于采用一个 简单的代理定义 :LLM 能够在一个循环中自主地使用各种工具。

通过与客户的合作,我们发现该领域正逐渐向这一简单的范式靠拢。随着底层模型能力的提升,智能体的自主程度也随之扩展:更智能的模型使智能体能够独立应对复杂多变的问题空间,并从错误中恢复。

我们现在看到工程师在为智能体设计上下文方面的想法正在发生转变。如今,许多原生人工智能应用都采用某种基于嵌入的预推理时间检索机制,以便为智能体提供重要的上下文信息,供其进行推理。随着该领域向更具智能体特性的方法过渡,我们越来越多地看到团队使用“即时”上下文策略来增强这些检索系统。

与预先处理所有相关数据不同,采用“即时”方法构建的智能体维护轻量级标识符(文件路径、存储的查询、网页链接等),并利用这些引用在运行时通过工具动态地将数据加载到上下文中。Anthropic 的智能体编码解决方案 Claude Code 就采用了这种方法,对大型数据库进行复杂的数据分析。该模型可以编写目标查询、存储结果,并利用 Bash 命令(例如 head 和 tail)来分析海量数据,而无需将完整的数据对象加载到上下文中。这种方法类似于人类的认知:我们通常不会记忆整个信息库,而是会引入外部组织和索引系统(例如文件系统、收件箱和书签)来按需检索相关信息。

除了存储效率之外,这些引用的元数据还提供了一种机制,可以有效地优化行为,无论这些行为是显式提供的还是直观的。对于在文件系统中运行的智能体而言, tests 文件夹中的 test_utils.py 文件与 src/core_logic/ 文件夹中的同名文件所代表的用途截然不同。文件夹层级结构、命名约定和时间戳都提供了重要的信号,帮助人类和智能体理解如何以及何时利用信息。

让智能体自主地导航和检索数据,还能实现渐进式信息披露——换句话说,智能体可以通过探索逐步发现相关的上下文。每次交互都会产生上下文信息,为下一步决策提供依据:文件大小暗示复杂性;命名规则暗示用途;时间戳可以作为相关性的参考。智能体可以逐层构建理解,仅在工作内存中保留必要信息,并利用笔记策略来增强信息的持久性。这种自我管理的上下文窗口使智能体能够专注于相关的信息子集,而不是被冗长但可能无关的信息淹没。

当然,这其中存在权衡:运行时探索比检索预先计算的数据要慢。不仅如此,还需要精心设计和周密规划,以确保 LLM 拥有合适的工具和启发式方法,从而有效地驾驭其信息环境。如果没有适当的指导,智能体可能会因为误用工具、陷入死胡同或未能识别关键信息而浪费上下文信息。

在某些情况下,最有效的智能体可能会采用混合策略:预先检索一些数据以提高速度,然后根据自身判断进行进一步的自主探索。自主程度的 “合适” 界限取决于具体任务。Claude Code 就是一个采用这种混合模型的智能体:CLAUDE.md 文件会被预先简单地放入上下文中,而像 globgrep 这样的基本工具则允许它导航环境并即时检索文件,从而有效地绕过了过时的索引和复杂的语法树等问题。

混合策略可能更适合内容动态性较低的场景,例如法律或金融领域。随着模型能力的提升,智能体设计将朝着让智能模型自主行动的方向发展,并逐步减少人工干预。鉴于该领域发展日新月异,“做最简单有效的方法”可能仍将是我们对基于 Claude 构建智能体的团队的最佳建议。

针对长期任务的上下文工程

长周期任务要求智能体在一系列动作中保持连贯性、上下文关联性和目标导向行为,即使动作数量超过了 LLM 的上下文窗口。对于持续数十分钟到数小时的连续工作任务,例如大型代码库迁移或综合研究项目,智能体需要专门的技术来克服上下文窗口大小的限制。

等待更大的上下文窗口似乎是一种显而易见的策略。但可以预见的是,在可预见的未来,各种大小的上下文窗口都可能受到上下文污染和信息相关性问题的影响——至少在需要智能体发挥最佳性能的情况下是如此。为了使智能体能够在更长的时间范围内高效工作,我们开发了一些直接解决这些上下文污染限制的技术:压缩、结构化笔记和多智能体架构。

压缩

压缩是指将接近上下文窗口上限的对话进行内容概括,然后用概括后的内容重新创建一个新的上下文窗口。压缩通常是上下文工程中提升长期连贯性的首要手段。其核心在于以高保真度的方式提炼上下文窗口的内容,从而使智能体能够在性能损失最小的情况下继续运行。

例如,在 Claude Code 中,我们通过将消息历史记录传递给模型来实现这一点,以汇总和压缩最关键的细节。该模型保留了架构决策、未解决的错误和实现细节,同时丢弃了冗余的工具输出或消息。然后,agent 可以使用这个压缩后的上下文以及最近访问的五个文件继续执行任务。用户可以获得连续的操作体验,而无需担心上下文窗口的限制。

压缩的艺术在于选择保留哪些信息,舍弃哪些信息,因为过度压缩会导致丢失一些微妙但至关重要的上下文信息,而这些信息的重要性往往在后续处理中才会显现。对于实现压缩系统的工程师,我们建议在处理复杂的代理轨迹时,仔细调整提示信息。首先,最大化召回率,确保压缩提示信息能够捕捉到轨迹中的所有相关信息,然后通过迭代优化,去除冗余内容,从而提高精确度。

清除工具调用和结果就是一个很容易实现的冗余内容示例——一旦某个工具在消息历史记录中被调用过,agent 为什么还需要再次查看原始结果呢?清除工具结果是最安全、最轻量级的压缩方式之一,最近已作为一项 功能在 Claude 开发者平台上 推出。

结构化笔记

结构化笔记,或称智能体记忆,是一种让智能体定期记录笔记并将其存储在上下文窗口之外的记忆中的技术。这些笔记会在稍后被调回上下文窗口。

这种策略以最小的开销提供持久内存。就像 Claude Code 创建待办事项列表,或者您的自定义代理维护 NOTES.md 文件一样,这种简单的模式使代理能够跟踪复杂任务的进度,并保留关键的上下文和依赖关系,否则这些信息会在数十次工具调用中丢失。

Claude playing Pokémon 展示了记忆如何在非编程领域提升智能体的能力。该智能体能够精确记录数千步游戏进程,追踪诸如“在过去的 1234 步里,我一直在 1 号道路训练我的Pokémon,Pikachu 已经升了 8 级,目标是升到 10 级”之类的目标。无需任何关于记忆结构的提示,它就能绘制已探索区域的地图,记住已解锁的关键成就,并保存战斗策略的笔记,从而学习哪些攻击对付不同的对手最为有效。

上下文重置后,智能体会读取自身的笔记,并继续进行数小时的训练序列或地牢探索。这种贯穿各个概要步骤的连贯性使得智能体能够执行长远策略,而如果仅将所有信息保存在 LLM 的上下文窗口中,则无法实现这一点。

作为 Sonnet 4.5 发布 的一部分,我们在 Claude 开发者平台上推出了 一款内存工具 的公开测试版。该工具通过基于文件的系统,使用户能够更轻松地在上下文窗口之外存储和查阅信息。这使得智能体能够随着时间的推移构建知识库,跨会话维护项目状态,并在无需将所有内容都保留在上下文中的情况下引用之前的工作。

子代理架构

子代理架构提供了另一种绕过上下文限制的方法。与其让一个代理尝试维护整个项目的状态,不如让专门的子代理在清晰的上下文窗口中处理特定的任务。主代理负责协调高层计划,而子代理则执行深入的技术工作或使用工具查找相关信息。每个子代理可能进行广泛的探索,使用数万个或更多令牌,但最终只返回其工作的精简摘要(通常包含 1000 到 2000 个令牌)。

这种方法实现了职责分离——详细的搜索上下文被隔离在子智能体内部,而主智能体则专注于结果的综合和分析。我们在 《我们如何构建多智能体研究系统》一文 中讨论了这种模式,它在处理复杂的研究任务时,相比单智能体系统展现出了显著的性能提升。

选择哪种方法取决于任务的特点。例如:

  • 压缩功能可以保持需要大量来回沟通的任务的对话流畅性;
  • 结构化笔记对于设定明确里程碑的迭代开发非常有效;
  • 多智能体架构能够处理复杂的研究和分析,并行探索能够带来丰厚的回报。

即使模型不断改进,在长时间的交互中保持一致性的挑战仍然是构建更有效智能体的核心。

结论

上下文工程代表了我们使用 LLM 构建方式的根本性转变。随着模型能力的提升,挑战不仅在于如何精心设计完美的提示,更在于如何巧妙地安排信息,确保每一步都能进入模型有限的注意力预算。无论是为长期任务实现信息压缩、设计高效的令牌工具,还是让智能体能够即时探索环境,其指导原则始终如一:找到一组能够最大程度提高预期结果概率的最小高信号令牌集合。

我们概述的技术将随着模型的改进而不断发展。我们已经看到,更智能的模型需要更少的规范性工程设计,从而使智能体能够更自主地运行。但即便智能体的能力不断提升,将上下文视为宝贵且有限的资源,对于构建可靠、高效的智能体而言仍然至关重要。

立即开始在 Claude 开发者平台中使用上下文工程,并通过我们的 内存和上下文管理 手册获取有用的技巧和最佳实践。

致谢

本文由 Anthropic 应用人工智能团队成员 Prithvi Rajasekaran、Ethan Dixon、Carly Ryan 和 Jeremy Hadfield 撰写,团队成员 Rafi Ayub、Hannah Moran、Cal Rueb 和 Connor Jennings 也做出了贡献。特别感谢 Molly Vorwerck、Stuart Ritchie 和 Maggie Vo 的支持。