Context Engineering:不是 Prompt 写得漂亮,而是信息怎么进窗口
“Context Engineering”这个词在过去一年里被提及的频率越来越高。
Andrej Karpathy 在 2025 年说过一句话,大意是:Prompt Engineering 这个词已经低估了真实的工程问题——真正的挑战不是怎么写出漂亮的 prompt,而是怎么在 context 窗口有限的情况下,在正确的时刻,把正确的信息放进去。他把这称为 Context Engineering。
这个表述切中了一个具体的痛点。
问题不在 Prompt,在信息架构
Prompt Engineering 强调的是”怎么说”——措辞、结构、few-shot 示例的顺序。Context Engineering 关注的是”放什么进去”——信息的选择、来源、时机、量级。
两者不是互斥的,但侧重完全不同。Prompt Engineering 解决的是表达问题,Context Engineering 解决的是信息供给问题。
一个 Agent 在执行任务时,context 窗口里的内容大致可以拆成五层:
1 | |
大多数团队在 demo 阶段只认真对待最后一层——当前输入。前四层要么是随手拼凑的,要么是随着需求不断堆叠的。到了生产,问题才开始暴露:模型行为不一致、成本失控、上下文溢出。
这些问题的根本原因不是模型不够好,而是 context 里进了不该进的东西、或者该进的东西没进来。
五个具体的工程问题
1. 系统指令的膨胀与腐化
系统提示(System Prompt)是 context 里最容易失控的部分。
起初只有几行角色定义。产品迭代几轮之后,加了一段特殊场景的处理逻辑;出了一个线上 bug,加了一段防御性说明;某个用户反馈了奇怪的行为,又加了几条约束。最终系统提示变成了一个几千 token 的文档,里面有大量已经不再适用的内容,但没有人敢删——不知道删了会不会出问题。
这是技术债,只是债主是 token budget。
解法不是”把系统提示写短一点”,而是建立系统提示的版本化管理和内容审计机制。每一段内容要有存在的理由,理由消失时要有对应的清理流程。动态内容(当前时间、用户信息、会话状态)不应该混进系统提示——它们每次都变,会破坏 prompt caching 的效果,也让系统提示的逻辑更难维护。
2. 工具定义的信噪比
工具定义会消耗大量 token,而且是每次调用都要带上的固定成本。
一个常见的失误是把所有工具在所有场景下都暴露给模型。一个通用 Agent 挂了 30 个工具,每个工具的 description 写了 300 字,工具定义就占了 9,000 token。但在处理某个具体任务时,其中 25 个工具完全用不到。
更合理的做法是按上下文动态加载工具。任务分类确定之后,只向模型暴露这类任务实际需要的工具子集。这需要在 Harness 层做工具的动态筛选,而不是把完整的工具列表硬编码进每个请求。
工具 description 的质量也是实际工程问题:不是写得越详细越好,而是要让模型以最低的 token 成本准确理解这个工具的用途和限制。冗余的描述是噪声,噪声会干扰模型的工具选择判断。
3. 记忆检索的注入时机
外部记忆(向量数据库、知识库、历史任务记录)是通过检索动态注入 context 的。
常见的实现是在每轮对话开始时统一检索一批相关内容,然后全部放进 context。这个做法简单,但有两个问题:
一是检索和使用之间有时间差。检索是在对话开始时做的,但真正需要记忆的时刻可能在第三步工具调用之后。早早注入的记忆内容会占用 context 空间,但在真正需要的时刻,它们已经被后来的内容”稀释”了。
二是一次性检索的精度不够。任务执行到中途,Agent 遇到了一个需要特定历史知识的决策点——这个时刻才是检索的最佳时机,这时的查询语义比任务开始时更精确,召回质量也更高。
更好的模式是按需检索:Agent 在推理过程中主动调用记忆工具,在需要特定信息的时刻发起检索。这要求记忆系统以工具的形式暴露,而不是在请求构建阶段静默注入。代价是增加了工具调用次数,但检索精度和 context 利用率都会显著提升。
4. 对话历史的压缩与剪枝
对话历史是 context 里增长最快的部分,也是最容易被忽视的成本来源。
一个执行了 20 步的 Agent 任务,历史记录里包含了每一次工具调用的完整输入输出。其中大量是执行细节:某个 API 返回了 500 行 JSON,Agent 只用了其中 3 个字段;某个中间步骤做了两次重试,重试记录对后续推理没有任何价值。
这些内容全部留在 context 里,是在消耗窗口空间,而不是在帮助模型推理。
历史压缩需要在 Harness 层主动实现,而不是等到上下文溢出才处理。几个具体策略:
工具输出裁剪:工具返回后立即做结构化提取,只保留 Agent 后续推理需要的字段,不把原始输出完整写入历史。
阶段性摘要:当任务执行超过某个步骤数阈值时,用一个轻量级的摘要步骤把早期历史压缩成结构化的状态描述,替换掉原始记录。
区分执行日志和推理材料:完整的执行记录写入可观测性系统,context 里只保留推理所需的摘要。这两件事不应该用同一份数据来做。
5. 信息的时效性管理
放进 context 的信息不全是等效的——有些是即时有效的,有些已经过期。
一个最常见的案例:Agent 从记忆里检索到”这个用户偏好简洁的回复”,但这是半年前针对另一个场景的偏好,当前任务是技术文档撰写,用户实际上需要详细说明。过期的记忆注入了 context,Agent 把它当作事实使用,结果不符合当前需求。
解法是给 context 里的所有外部信息打上元数据标签:来源、时间、适用范围、置信度。当 Agent 使用检索到的信息时,这些元数据应该一同可见,由 Agent 自行判断适用性,而不是盲目采信。
这要求在信息写入记忆系统时就做好结构化标注——是前期成本,换来的是后期 context 质量的可控性。
Context 质量是可以测量的
Context Engineering 的一个问题是:它的效果不像代码 bug 那样直接可见。
但 context 质量是可以被间接测量的。
Token 效率:完成同一类任务,消耗的 token 数量趋势是否稳定?如果某类任务的 per-task token 消耗在没有明显功能变化的情况下持续上升,通常意味着 context 里进了越来越多的噪声。
工具调用准确率:模型选错工具、调用不存在的工具、需要多次纠错才能完成任务——这些行为往往是工具定义写得模糊或者 context 信息相互矛盾的信号。
任务完成的步骤数:同一类任务,执行步骤数是否稳定?步骤数异常增多,可能是 context 里缺少了关键信息,导致模型在原地踏步。
把这三个指标加入 Agent 系统的可观测性监控,就能在 context 质量退化时得到早期预警。
与其他工程能力的关系
Context Engineering 不是独立存在的能力,它是 Agent 基础设施里多个模块共同作用的结果。
成本工程里讨论的 prompt caching 有效性、对话历史压缩——这些本质上是 context 管理策略;Agentic Memory 里讨论的检索时机和写-读不对称问题,是 context 信息供给的质量问题;Harness 工程里的上下文管理层,是 context 组装逻辑的执行位置。
Context Engineering 是这几个方向的交叉点。如果把 Agent 系统比作一台机器,context 就是驱动它运转的信息燃料。燃料的质量和供给方式,决定了机器能跑多远、跑多稳。
真正困难的部分不是把信息放进 context,而是决定什么不放进去。
任何信息都可以被加进 context,成本是窗口空间和模型的注意力。加得越多,噪声越多,推理质量的方差越大。Context Engineering 的核心判断力,是在”可能有用”和”确实需要”之间划出清晰的边界——在正确的时刻,放正确数量的正确信息。
这个判断力很难被自动化,但可以被系统化。