上下文工程实战:构建 Manus AI Agent 的五项关键原则

15 min

上下文工程实战:构建 Manus AI Agent 的五项关键原则

IMPORTANT

在构建生产级 AI Agent 的过程中,上下文工程(Context Engineering)是一项至关重要的核心技术。它直接决定了 Agent 的性能、稳定性和成本效益。本文旨在分享我们在构建 Manus AI Agent 项目中,通过多次迭代和重构所沉淀下来的五项关键设计原则。

项目伊始,我们面临一个根本性的架构选择:是训练一个端到端的 Agent 模型,还是基于前沿大语言模型(LLM)的上下文学习(In-Context Learning)能力进行构建。考虑到微调模型漫长的反馈周期与快速迭代的产品需求相悖,我们选择了后者。这一决策使我们的产品能够与底层模型的演进保持正交,从而持续受益于模型能力的提升。我们认为,如果模型进步是上涨的潮水,Manus 就应当是水涨船高的舟,而非困于原地的礁石。

然而,纯粹依赖上下文学习的路径充满挑战。我们发现,构建高效、可靠的 Agent 在很大程度上是一门实验科学,其核心在于如何精心设计和塑造模型的上下文。以下是我们总结的五项核心原则,希望能为相关领域的研究与开发者提供参考。


原则一:围绕 KV-Cache 优化设计,提升效率与成本效益

对于生产环境的 AI Agent 而言,KV-Cache 命中率是衡量其性能和成本的关键指标之一。Agent 的运行模式是一个迭代循环(Action-Observation Loop),在此过程中上下文长度持续增长,而输出(通常是结构化的函数调用)相对较短,导致输入与输出的 Token 比例极高(在 Manus 中约为 100

)。

KV-Cache 机制允许模型复用上下文前缀的计算结果,从而显著降低“首字符时间(TTFT)”和推理成本。例如,使用某些 API 时,缓存命中的 Token 成本可能比未命中低一个数量级。因此,最大化 KV-Cache 命中率是设计的首要目标。

关键实践:

  1. 保持 Prompt 前缀的稳定性:由于 LLM 的自回归特性,前缀中任何一个 Token 的变动都会导致后续所有缓存失效。应避免在系统提示等稳定部分加入时间戳等动态元素。
  2. 确保上下文的只增性(Append-only):避免修改或重排历史的 Action 和 Observation。确保序列化逻辑(如 JSON)是确定性的,以防因顺序变化导致缓存失效。
  3. 显式标记缓存断点:部分推理框架需要手动指定缓存断点。在设计时应确保断点位置能最大化复用范围,通常至少应包含完整的系统提示。

流程对比:

// 错误示范:前缀不稳定导致缓存完全失效 (Cache Miss)
[Context @ Step n]        -->     [Context @ Step n+1]
+-----------------+               +-----------------+
| Instruction (v1)|               | Instruction (v2)|  <-- 前缀变更
| Action 1        |               | Action 1        |
| Observation 1   |               | Observation 1   |
+-----------------+               +-----------------+
// 结果:从 Instruction (v2) 开始,所有内容需重新计算。

// 正确示范:稳定的前缀最大化缓存命中 (Cache Hit)
[Context @ Step n]        -->     [Context @ Step n+1]
+-----------------+               +-----------------+
| Instruction     |               | Instruction     |  <-- 缓存命中
| Action 1        |               | Action 1        |  <-- 缓存命中
| Observation 1   |               | Observation 1   |  <-- 缓存命中
+-----------------+               +-----------------+
| Action 2 (New)  |               | Action 2 (New)  |  <-- 此处开始计算
| Observation 2   |               | Observation 2   |
+-----------------+               +-----------------+

原则二:通过工具屏蔽而非移除,保障上下文稳定性

随着 Agent 功能扩展,其可用工具(Tools)的数量会急剧增加,导致模型的决策空间爆炸,从而影响选择的准确性和效率。一个直观的解决方案是动态增删工具集,但我们的实验表明,在迭代过程中动态修改工具定义列表是应当避免的。

主要原因:

  1. 破坏 KV-Cache:工具定义通常位于上下文前段,任何改动都会使后续所有缓存失效。
  2. 导致模型混淆:如果历史步骤引用了当前已被移除的工具,模型可能会因无法找到定义而产生 schema 违规或幻觉行为。

我们在 Manus 中采用的策略是屏蔽(Masking)而非移除(Removing)。通过利用推理框架支持的响应预填充(Response Prefill)或 Logits Processing 功能,我们可以在解码阶段动态地屏蔽掉当前状态下不可用的工具选项,从而在不破坏上下文稳定性的前提下,约束模型的行为空间。

流程对比:

// 错误示范:动态移除工具
[Context @ Step n+1]
+-----------------+
| Instruction     |
| Tool B          | <-- Tool A 被移除, Tool C 新增, 破坏前缀
| Tool C          |
| ...             |
+-----------------+
// 结果: KV-Cache 失效,且模型可能对历史行为产生困惑。

// 正确示范:保留完整工具集,按需屏蔽
[Context @ Step n+1]
+-----------------+
| Instruction     |
| Tool A (Masked) | <-- 上下文稳定,仅在解码时屏蔽
| Tool B (Active) |
| Tool C (Active) |
| ...             |
+-----------------+
// 结果: 缓存命中,模型决策空间受控,行为一致性高。

原则三:利用文件系统作为外部上下文,突破长度限制

尽管现代 LLM 的上下文窗口已达 128K 甚至更高,但在真实的 Agent 场景中,这依然面临三大挑战:

  1. 巨大的观测(Observation):与网页、PDF 等非结构化数据交互时,观测内容极易超出上下文限制。
  2. 长上下文性能衰减:模型在处理超长上下文时,可能会出现注意力分散或“中间遗忘(Lost-in-the-middle)”的问题。
  3. 高昂的成本:即使有前缀缓存,长输入依然会产生显著的传输和预填充成本。

上下文截断或有损压缩策略存在丢失关键信息的风险。因此,我们提出将文件系统(File System)视为 Agent 的终极上下文。文件系统具有容量无限、持久化且可被 Agent 直接操作的特性,使其成为理想的结构化外部记忆体。

Agent 学会按需读写文件,将大的观测结果(如网页内容)存入文件,在上下文中只保留其引用(如文件路径或 URL)。这种压缩策略是完全可恢复的,既能保持上下文的精简,又不会永久丢失信息。

流程对比:

// 传统方法:所有信息堆叠在上下文中
[CONTEXT]
+----------------------------+
| Instruction                |
| Action 1 (Read Webpage)    |
| Observation 1 (Full HTML)  | <-- 占据大量空间
+----------------------------+
// 结果: 上下文迅速膨胀,成本高,性能受影响。

// Manus 方法:使用文件系统作为外部上下文
[CONTEXT]                           [FILE SYSTEM]
+----------------------------+
| Instruction                |
| Action 1 (Save to file_X)  | ----> +-------------+
| Observation 1 (Path: /x)   |         | Document X  |
+----------------------------+         | (Full HTML) |
// 结果: 上下文保持简洁,信息可按需、无损地恢复。

原则四:通过目标复述引导注意力,缓解“中间遗忘”问题

在执行需要数十步工具调用的复杂任务时,Agent 很容易偏离最初目标。这是 Transformer 架构固有的“中间遗忘”问题的体现。

为解决此问题,Manus 设计了一种通过复述(Recitation)引导注意力的机制。具体而言,Agent 会在任务执行过程中,周期性地更新一个包含核心目标的 todo.md 文件,并将其置于上下文的末尾。

这种设计将全局计划不断推向模型的“近期记忆”中,强制模型在每一步决策前重新关注核心目标。这是一种利用自然语言偏置模型注意力的有效手段,无需对模型架构进行任何修改。

流程对比:

// 普通流程:目标位于上下文前端,易被忽略
[Context @ Step n+1]
+-----------------+
| Objectives      | <-- 注意力权重较低
| ... (long history)
| Action n        |
| Observation n   |
+-----------------+

// 复述流程:在上下文末尾重申目标
[Context @ Step n+1]
+-------------------------+
| Objectives (initial)    |
| ... (long history)      |
| Action n                |
| Observation n           |
| Objectives (rewritten)  | <-- 重新置于注意力焦点
+-------------------------+

原则五:保留失败记录,实现真正的上下文学习

AI Agent 在执行任务时不可避免地会遇到失败:环境返回错误、外部工具行为异常或模型自身产生幻觉。一个常见的错误做法是隐藏或清除这些失败记录,然后重试。这种看似“干净”的做法实际上剥夺了模型从错误中学习的机会。抹除失败的证据,就等于抹除了模型适应和改进的机会。

我们的经验表明,提升 Agent 行为鲁棒性的最有效方法之一,就是将完整的试错过程保留在上下文中。

实践方法: 当一个动作(Action)执行失败后,不应将其从历史记录中删除。相反,应将该动作、其失败的观测结果(Observation,如错误信息)以及后续的修正尝试一并完整地记录在上下文中。

流程对比:

// 错误示范:抹除失败记录
// Contextual History: [..., Action 1, Observation 1]
// Attempt 2A -> Fails. The system discards this attempt and resets.
// Attempt 2B -> Succeeds.
// Final Context: [..., Action 1, Observation 1, Action 2B, Observation 2B]
// 结果: 模型无法得知 2A 为何失败,失去了学习机会。

// 正确示范:将失败作为学习信号纳入上下文
[Context @ Step n+1]
+------------------+
| ...              |
| Action 1         |
| Observation 1    |
| Action 2A        | <-- 失败的尝试
| Observation 2A   |
| (Error: Failed)  | <-- 明确的失败反馈
| Action 2B        | <-- 基于失败反馈进行的修正尝试
| Observation 2B   |
| (Success)        |
+------------------+
// 结果: 模型获得了完整的试错轨迹,使其在后续决策中能够规避类似错误。

当模型在上下文中看到 Action 2A 导致了负面结果 Observation 2A,它在生成 Action 2B 时,就已经获得了宝贵的先验知识。这正是**在上下文中学习(In-Context Learning)**最直接的体现——模型在自身的工作流中,通过观察连续的、包含因果关系的事件来进行实时策略调整。

结论与展望

上述五项原则——围绕 KV-Cache 设计、通过屏蔽管理工具、利用文件系统扩展上下文、以复述引导注意力、并保留失败记录——共同构成了一套旨在构建高效、稳定且能自我改进的 AI Agent 的上下文工程方法论。其核心思想在于,将开发者从“指令下达者”转变为“上下文雕塑家”,通过精心构造信息流来引导模型的行为。

这些实践不仅是工程上的优化,更是对如何有效利用大语言模型内在学习能力的深入探索。我们相信,随着对上下文工程理解的加深,未来将涌现出能力更强、行为更可预测的 AI Agent。同时,我们也期待模型架构的演进,例如具备高效外部记忆访问能力的状态空间模型(SSM),可能会为 Agent 的设计带来新的范式,使其更接近于理论中的“神经图灵机”。

我们分享的经验源于 Manus 项目的特定场景,虽是局部最优解,但希望其中蕴含的通用思想能为业界同仁提供有益的启发。


原文: https://manus.im/blog/Context-Engineering-for-AI-Agents-Lessons-from-Building-Manus