很多技术博客看完就忘,但 Manus 的这篇上下文工程日志,却让我有一种很久没遇到的熟悉感,就像十几年前我第一次读《编程珠玑》时那种“结构清晰又内功深厚”的惊叹:用极简的语言,把系统最核心、最隐秘的痛点一层层拆出来,再用“实践炼过、成本试过、坑都踩过”的方式,给出一套优雅得近乎朴素的工程解法。把你从“github 上一堆看起来能跑”的原型,带到“可以抗住百万次交互”的真实世界。
如果你正在构建 Agent 系统、研究 prompt 调度、RAG 链路、日志记录、踩过cache miss、上下文错乱、模型行为漂移等无数坑,那肯定非常能共鸣 Manus 的实用主义。
很多时候知道问题在哪,但还没把它总结成一条法则;明明做了优化,但没能力从认知上总结它为什么成立;但没人告诉你:其实这些事,别人已经系统总结过了,而且优雅 100 倍。我读 Manus blog 的时候,就有这种踏实感,原来我们绕过的弯,爬过的坡是可以被结构化定义下来的。
分享下我对 Manus 六大上下文工程法则的拆解,可以看作是“智能体上下文系统设计的六个底层约束”。
1️⃣法则一:围绕 KV-Cache 进行设计
让智能体变快,不一定靠生成快,记忆前缀不重算也能加速。我们经常把注意力放在 LLM 的生成效果上,优化 prompt 内容、格式、语言风格。对于聊天机器人,输入和输出的长度通常比较均衡。但对于AI智能体,情况则大相径庭,智能体场景中最昂贵的成本其实发生在前置阶段:当一个智能体执行一次“读取上下文 + 推理 + 输出调用”的循环时,它的输出可能只有几十个 token,而输入上下文可能高达几千甚至上万 token,在这种严重失衡的输入输出结构下,预填充阶段的计算成本才是拖慢系统、放大延迟的罪魁祸首。
如果你最近在做 multi-agent 系统,尤其是在“需要快速轮询”“低延迟交互”这些及时响应场景中,明显感到响应慢、链路卡顿、用户体验下降,那你极有可能踩在了这条隐藏的高成本区上,每个 Agent 都在重复预填整个上下文,导致系统性能雪崩。
Manus 的处理方式非常极致:把缓存命中率当作核心优化指标,哪怕为此牺牲 prompt 灵活性都在所不惜。
KV缓存是LLM的一项优化技术,它能缓存已经计算过的前缀(注意是前缀)的键值对,避免在后续请求中重复计算。为了最大化缓存命中率,Manus采取了以下实践:
保持提示词前缀稳定: 即使是单个token的改变也会使该位置之后的所有缓存失效。一个常见的错误是在系统提示的开头包含一个精确到秒的时间戳,这虽然能让模型知道当前时间,但却会彻底破坏缓存。
确保上下文是 append-only: 避免修改历史的动作或观察结果。同时,要保证序列化方式是确定的,例如,很多编程语言在序列化JSON对象时并不保证键(key)的顺序,这会悄无声息地破坏缓存。
显式标记缓存断点: 某些推理框架需要手动在上下文中插入缓存断点。在设置时,至少要确保系统提示的末尾是一个断点。
2️⃣法则二:掩码,而非移除
随着智能体能力的增强,其可用的工具会越来越多。很多人一开始觉得工具是智能体的核心,一个自然的想法是动态地管理这个工具集,比如使用类似RAG的技术按需加载工具定义。就是把工具按需加载、动态切换、上下文中途插入,这听起来很动态、很模块化,但在真正跑起来之后,Manus 发现这是一个陷阱:在迭代中途动态增删工具会带来两大问题:
缓存失效: 工具定义通常位于上下文的前部,每次工具定义变化,都会导致后续所有步骤的KV缓存失效。
模型困惑: 当历史记录中引用了当前上下文中已不存在的工具时,模型会感到困惑,容易导致格式错误或幻觉出不存在的动作。
你有没有遇到过越加工具模型越不稳定,生成经常“选错工具”“乱组参数”甚至出现没定义过的操作这样的幻觉,那你可能已经踩上这颗雷了。
Manus 的解法非常聪明也非常工程化:保持工具定义集稳定,转而使用“掩码”技术来约束模型的选择。通过在解码阶段利用logits处理器屏蔽(或强制选择)某些token,可以控制模型在当前状态下只能选择允许的工具,而无需修改上下文中的工具定义。
例如,当用户刚输入新指令时,Manus会通过预填充特定的回复前缀来强制模型立即回复用户,而不是先执行某个工具。此外,他们还巧妙地为工具名称设计了统一的前缀,如所有浏览器相关的工具都以browser_开头,所有命令行工具都以shell_开头,这使得在特定状态下仅允许某一类工具变得非常容易 ()。
这个设计的哲学很现代:不要试图让模型“理解你不想让它做什么”,你就直接不给它做的可能性。
3️⃣法则三:将文件系统作为上下文
上下文不是无限堆料,而是构建随取即用的语义型记忆索引。即使模型给你 128K、1M 100M的上下文窗口,它也依然不够。你不知道哪个网页会突然给你塞个两万 token 的 HTML,你也拦不住哪个 API 会返回一个五层嵌套的 JSON,你更不知道用户什么时候发来个几十页的 PDF。这带来了三个大的问题:
观察结果巨大: 当智能体与网页、PDF等非结构化数据交互时,一次观察就可能轻易撑爆上下文窗口。
性能下降: 即使没有超出窗口限制,模型在处理超长上下文时,性能也往往会下降。不止拉高计算延迟、引入注意力混乱,还让模型迷失自我。
成本高昂:即使有前缀缓存,开发者仍然需要为传输和预填充每一个token付费。
Manus 的做法有很强的借鉴意义,它做的不是扩容,而是外置。他们把文件系统当作一个无限持久化的“语义型存储空间”,它具有三大优势:大小无限、本质上持久、并且可由智能体直接操作。
模型在上下文里记录路径、摘要、索引,真正需要的时候再调用读文件这个工具。这种方法还支持可恢复的压缩策略:即使一个网页的详细内容因为上下文空间不足而被丢弃,它的URL或文件路径依然会保留在上下文中,智能体可以在需要时重新访问它。
这其实是 Agent 系统中一个很高级的认知结构:不是把所有信息喂给模型,而是训练模型具备“知道信息在哪”的能力。
4️⃣法则四:通过复述操控注意力
跟我们日常复盘碎碎念一样,Agent 执行过程中的目标也不是记住的,而是每一步都重新提醒一下自己。在我自己做 Agent 系统的时候,经常发现一个现象:模型走着走着就忘了它原本想做的事,偏离目标、越绕越远。我们管这个叫“迷失在中间”,但在工程语境里,这种“目标漂移”其实是上下文 attention weight 的失焦问题。
Manus 的解法很朴,每轮都更新一次目标和当前状态,然后把这个文件的内容贴到上下文最后。
看起来像是个复读机,但背后其实是一种“语义注意力偏置”:这个行为相当于智能体在不断地向自己复读它的总体目标和当前计划。由于LLM的注意力机制倾向于更关注上下文末尾的近期信息,这种复读有效地将全局计划推入模型的近期注意力范围,从而利用自然语言本身来偏置模型的注意力,使其始终聚焦于核心任务目标,而无需对模型架构进行任何特殊修改 。
我感觉这个方式特别美,因为它没有引入任何额外结构,但却做到了最接近人类不断自我提醒的认知行为。
5️⃣法则五:保留错误的内容
一句话:失败是智能体推理链上的必要节点,在大任务的执行过程中,失败是常态。几乎所有 Agent 系统都会有 retry 机制:出错就重来,格式错就重置。很多人为了“干净”,在智能体犯错时直接清缓存、重试调用,结果模型变成一个永远不长记性的工具轮回者。它永远不知道自己错在哪,也就永远学不会避开这个坑。它今天格式错一次,明天还错一样,明明是上一步才失败过的函数,它下轮又敢信心满满去调用。
Manus 的做法是反常规的,他们选择保留所有出错信息:失败调用、错误观察、甚至栈追踪,一条不删,照样放进上下文里。有了这些证据,模型就能在后续的推理中隐式地更新其内部的信念模型,从而调整其行为的先验概率,降低在相似情境下重复犯错的可能性。这种吃一堑长一智的做法,让模型记住自己干砸过,在未来的语义决策中,自动规避相似路径。
这种让模型知道这条路不通的方式,比任何显式标注更接近认知建模。所以,如果你发现 Agent 一直“重复同样的蠢事”,那就别再清上下文了,错是它的,但学会是你的责任。
6️⃣法则六:不要被少样本示例所困
你在构建提示词模板时,是不是喜欢封装成一串标准化样例?确实能跑得通。few-shot prompting 在很多任务中非常好用,但在多轮、动态任务中,如果你给的示例太相似、结构太固定,模型很容易陷入“模式依赖”,变成“照搬机器”。当你发现模型开始照猫画虎地生成、总在学你给的那个格式、甚至一字不差地模仿之前的样例的时候,就要开始思考如何构建样例,让模型的行为多样分布。
few-shot 用得太像 few-clone,会让模型陷入“格式安全区”,变成行动保守者,而不是策略探索者。
Manus 的做法是刻意制造结构化变体,在智能体的动作和观察中,有意识地引入少量但结构化的变体,给的示例语义一致但表达方式不同。通过打破一成不变的模式,有效地使模型的注意力多样化,避免其陷入单调的模仿循环,从而提高其鲁棒性和适应性。这个策略的高明之处在于你让模型理解还有别的方式也可以对。
最后
Manus 这篇小而硬的博客,像是你走了很远很远之后突然在半山腰看到的一块坐标石碑,告诉你你快进入上下文工程师的区域了。
做得越深,就越知道所谓“智能体跑不起来”,是根本没给模型构造一个可持续运行的信息生命系统,它记不清目标、摸不清状态、想不清下一步能干嘛,更不用说从失败中自我修正。
对我来说,这篇文章让我确认了我们走的那些弯路其实早有共性路径,也让我第一次能用一套更准确的语言来描述我眼里“一个靠谱的 Agent 系统到底需要什么样的上下文架构”。
只要你干过这些,你就会意识到:Prompt 是告诉模型你想要什么,Context是构建一个系统,让模型每一次都有机会自动靠近正确。
如果你正在做 Agent,或者计划进入这个方向,不妨用这六条 checklist 把你现在的系统过一遍:哪个上下文会频繁变动?哪个状态是隐式的?错误有没有暴露给模型?工具调用是否具备 mask 控制能力?你的记忆系统是全塞还是挂载的?