Manus-AI agent 的上下文工程
摘要: Manus团队提出上下文工程是AI agent的关键。核心优化包括:1)KV缓存命中率,保持提示前缀稳定,避免修改已缓存内容;2)遮蔽而非移除工具以维护缓存有效性;3)用文件系统管理长上下文,避免信息丢失;4)通过复述(如更新todo.md)维持任务焦点;5)保留错误内容以提升模型自我修正能力;6)减少对少样本示例的依赖,引入多样性防止模式僵化。
参考Manus发布的AI代理的上下文工程:构建Manus的经验教训,记录一下,如果有理解不对的地方欢迎指出,谢谢。
---------------------------------------------------------------------------------------------------------------------------------
1、提高KV缓存命中率方式:
他们认为KV-cache命中率 是生产阶段AI agent最重要的单一指标,它直接影响延迟和成本。因此围绕KV缓存进行设计。
典型agent运作方式:
input->模型根据上下文选择一个动作->在环境中执行动作->产生观察结果
->动作和观察结果添加到上下文->选择动作->执行动作->产生观察结果
......(持续迭代)
->任务完成
随着每一步的推进,上下文不断增长,而输出——通常是结构化的函数调用——保持相对简短。这使得代理(agents)相比聊天机器人的预填充和解码比例高度倾斜。例如在Manus中,平均输入与输出的token比例约为100:1。
具有相同前缀的上下文可以利用KV缓存,这大大减少了首个token的生成时间(TTFT)和推理成本——无论你是使用自托管模型还是调用推理API。例如:使用Claude Sonnet时,缓存的输入token成本为0.30美元/百万token,而未缓存的成本为3美元/百万token——相差10倍。

(1)保持提示前缀稳定(LLM自回归特性导致有改动会使该标记之后的缓存失效)
(2)上下文只追加,避免修改之前的操作或观察(要注意在序列化JSON对象时键顺序的稳定性,否则可能会悄无声息地破坏缓存。)
(3)在需要时明确标记缓存断点(有些模型或推理框架不支持自动增量前缀缓存,需要在上下文中手动插入缓存断点。分配断点时,要考虑缓存过期问题,要至少确保断点包含系统提示的结尾)
此外,如果正在使用像 vLLM 这样的框架自托管模型,请确保启用了前缀/提示缓存,并且你正在使用会话 ID 等技术在分布式工作节点之间一致地路由请求。
2、遮蔽、而非转移
实验表明了一个明确的规则:除非绝对必要,避免在迭代过程中动态添加或移除工具。原因:
(1)在大多数LLM中,工具定义在序列化后,位于上下文的前部,通常在系统提示之前或之后。因此任何更改都会使后续所有动作和观察的KV缓存失效。
(2)当先前的动作和观察仍然引用当前上下文中不再定义的工具时,模型会感到困惑。如果没有约束解码,这通常会导致模式违规或幻觉动作。
为了解决这个问题并仍然改进动作选择,Manus使用上下文感知的状态机来管理工具可用性。它不是移除工具,而是在解码过程中掩蔽token的logits,以基于当前上下文阻止(或强制)选择某些动作。

在实践中,大多数模型提供商和推理框架支持某种形式的响应预填充,这允许你在不修改工具定义的情况下约束动作空间。函数调用通常有三种模式(使用 NousResearch 的 Hermes 格式 作为示例):
(1)自动 – 模型可以选择是否调用函数。通过仅预填充回复前缀实现:<|im_start|>assistant
(2)必需 – 模型必须调用函数,但选择不受约束。通过预填充到工具调用令牌实现:<|im_start|>assistant<tool_call>
(3)指定 – 模型必须从特定子集中调用函数。通过预填充到函数名称的开头实现:<|im_start|>assistant<tool_call>{"name": "browser_ 通过这种方式,他们通过直接掩码token的logits来约束动作选择。例如,当用户提供新输入时,Manus必须立即回复而不是执行动作。他们还有意设计了具有一致前缀的动作名称——例如,所有与浏览器相关的工具都以browser_开头,命令行工具以shell_开头。以便能够轻松确保agent在给定状态下只从特定工具组中进行选择而无需使用有状态的logits处理器。
这些设计有助于即使在模型驱动的架构下也能确保Manus的循环保持稳定。
3、使用文件系统作为上下文
(1)痛点:
<1> 观察结果可能非常庞大,尤其是当agent与网页或PDF等非结构化数据交互时。很容易超出上下文限制。
<2> 模型性能往往会下降(超过一定的上下文长度后,即使支持该窗口大小)。
<3> 长输入成本高昂,即使使用前缀缓存。你仍然需要为传输和预填充每个token付费。
很多agent系统通过压缩解决这个问题,但是压缩会带来信息损耗,可能10步之后需要的某些重要信息因压缩丢失(因为无法可靠预测哪个观察结果在哪一步最重要)。因此任何不可逆的压缩都带有风险。
因此Manus中将文件系统视为终极上下文:大小不受限制,天然持久化,并且agent可以直接操作。模型学会按需写入和读取文件——不仅将文件系统用作存储,还用作结构化的外部记忆。

Manus将压缩策略始终设计为可恢复的。例如,只要保留URL,网页内容就可以从上下文中移除;如果沙盒中仍然保留文档路径,则可以省略文档内容。这使得Manus能够缩短上下文长度,而不会永久丢失信息。 与Transformer不同,状态空间模型(State Space Model,SSM)缺乏完整的注意力机制,并且在处理长距离的后向依赖关系时表现不佳。但如果它们能够掌握基于文件的记忆——将长期状态外部化而不是保存在上下文中——那么它们的速度和效率可能会开启一类新型智能体。基于SSM的智能体可能是神经图灵机真正的继任者。
4、通过复述操控注意力
Manus在处理复杂任务时,倾向于创建一个todo.md文件,并在任务执行过程中更新它,勾选已经完成的任务。这就是一种操控注意力的刻意机制。

Manus中的一个典型任务平均需要大约50次工具调用。由于Manus依赖LLM进行决策,在这么长的循环中,它很容易偏离主题或忘记早期目标,尤其是在长上下文或复杂任务中。
通过不断重写待办事项列表,Manus将其目标复述到上下文的末尾。这将全局计划推入模型的近期注意力范围内,避免了"丢失在中间"的问题,并减少了目标不一致。实际上,它使用自然语言来使自己的注意力偏向任务目标——而不需要特殊的架构变更。
5、保留错误内容
语言模型会产生幻觉,环境会返回错误,外部工具会出现异常行为,意外的边缘情况随时都会出现。因此保留失败信息,放到上下文中,让模型看到失败的行动,以及由此产生的观察结果或堆栈跟踪,它会隐式地更新其内部信念。这会改变其先验,降低重复相同错误的可能性,具备一定的错误恢复能力。

6、不要被少样本示例所困
少样本提示是提高LLM输出的常用技术。但在agent系统中,它可能会以微妙的方式适得其反。如果你的上下文充满了类似的过去行动-观察对,模型将倾向于遵循该模式,即使这不再是最优的。
这在涉及重复决策或行动的任务中可能很危险。例如,当使用Manus帮助审查20份简历时,agent通常会陷入一种节奏——仅仅因为这是它在上下文中看到的,就重复类似的行动。这导致偏离、过度泛化,或有时产生幻觉。

解决方法是增加多样性。Manus在行动和观察中引入少量的结构化变化——不同的序列化模板、替代性措辞、顺序或格式上的微小噪音。这种受控的随机性有助于打破模式并调整模型的注意力。 换句话说,不要让自己陷入少样本学习的窠臼。你的上下文越单一,你的智能体就变得越脆弱。
更多推荐


所有评论(0)