← 返回 AI Agent 课程

【中文精读】Context Engineering for AI Agents: Lessons from Building Manus

原文:https://manus.im/blog/Context-Engineering-for-AI-Agents-Lessons-from-Building-Manus · 作者:Yichao 'Peak' Ji(Manus 联合创始人兼首席科学家) · 本文为中文精读版(忠实转述+关键段落翻译),非逐句全译 · 生成于 2026-07-03 · 精读整理:
导读:为什么要读这篇?
这是把「上下文工程(context engineering)」一词真正打响的工业界实战文之一。2025 年中发表时,「prompt engineering 已死、context engineering 当立」的说法刚开始流行,而这篇文章是少数用真实生产 agent 的血泪经验撑起这个概念的文字——Manus 是当时用户量最大的通用 agent 产品之一,作者团队为此重构了四次 agent 框架。它在 agent 开发知识体系中的位置,恰好与 Anthropic 官方的《Effective context engineering for AI agents》互补:Anthropic 那篇偏原则与心智模型(注意力预算、上下文是稀缺资源),这篇偏工程细节与踩坑清单(KV-cache 命中率、logits 遮蔽、文件系统外置记忆、todo.md 复述)。文中六条经验几乎每一条都能直接落到你自己的 agent 代码里,而且给出了「为什么这样做」的第一性解释。读完这篇,你对「一个生产级 agent 的上下文到底长什么样、钱花在哪、坑埋在哪」会有具象的认识。

引言:押注上下文,而不是押注模型

文章从 Manus 项目起点的一个关键抉择讲起:到底是用开源基础模型训练一个端到端的 agent 模型,还是基于前沿模型的上下文内学习(in-context learning)来构建 agent?

作者 Yichao 'Peak' Ji 用自己的经历回答了这个问题。他在 NLP 领域的第一个十年赶上了 BERT 时代——那时模型必须先微调(fine-tune)、再评估,才能迁移到新任务,一次迭代动辄数周。更痛的教训来自他上一次创业:团队从零训练的模型,在 GPT-3 和 Flan-T5 出现后一夜之间失去价值。这让 Manus 团队坚定地选择了上下文工程这条路:改进可以在数小时而非数周内交付,并且让产品与底层模型保持「正交」——模型进步时产品跟着受益,而不是被某个自研模型锁死。作者的比喻是:

"If model progress is the rising tide, we want Manus to be the boat, not the pillar stuck to the seabed."
如果模型进步是不断上涨的潮水,我们希望 Manus 是船,而不是钉死在海床上的柱子。

但上下文工程远非「写写提示词」那么轻松。Manus 的 agent 框架前后重构了四次,每次都是因为发现了更好的上下文塑造方式。作者把这种手工架构搜索、提示词调试加经验性猜测的过程,自嘲地称为「随机研究生下降(Stochastic Graduate Descent)」——谐仿机器学习里的随机梯度下降(Stochastic Gradient Descent, SGD),意思是:没有优雅的优化算法,全靠一届届「研究生」式的土法炼钢反复试错。不优雅,但有效。下面六节就是这场试错沉淀出的「局部最优解」。

一、围绕 KV-cache 做设计(Design Around the KV-Cache)

作者开门见山地给出全文分量最重的一个判断:

"The KV-cache hit rate is the single most important metric for a production-stage AI agent."
KV-cache 命中率是生产阶段 AI agent 唯一最重要的指标。

先解释术语:键值缓存(KV-cache)是 Transformer 推理时的核心优化——模型对已经处理过的前缀 token 计算出的注意力键值(Key/Value)可以缓存复用,只要新请求的前缀与缓存内容逐 token 完全一致,这部分就不必重算。命中缓存的输入 token,延迟和价格都大幅下降。

为什么这对 agent 特别关键?因为 agent 的工作方式天然造成极度倾斜的输入输出比:每一轮迭代,agent 把上一步的动作(action)观测(observation)追加进上下文,再让模型基于全部历史选出下一个动作。上下文随步数不断膨胀,而输出通常只是一个短短的结构化函数调用。在 Manus,平均输入输出 token 比约为 100:1——也就是说,成本几乎全部由「重复喂进去的长前缀」决定。

钱的差距非常具体:以当时的 Claude Sonnet 为例,命中缓存的输入 token 约 0.30 美元/百万 token(USD/MTok),未命中的是 3 美元/MTok——整整 10 倍差距。同一个 agent,缓存策略做得好与坏,账单可以差一个数量级。

由此,作者给出三条提升命中率的实践:

1. 保持提示词前缀稳定

LLM 是自回归的,哪怕一个 token 的差异,都会让该 token 之后的全部缓存失效。一个极常见的错误是在系统提示开头放精确到秒的时间戳——看起来无害(还能让模型知道现在几点),实际上每次请求前缀都变,缓存命中率直接归零。

2. 上下文只追加、不修改(append-only)

绝不回头改写之前的动作或观测,并且保证序列化是确定性的。这里有个隐蔽的坑:很多语言和库在序列化 JSON 时不保证键的顺序稳定,同一个对象两次序列化出的字符串可能不同——原文说这会「悄无声息地弄坏缓存(silently break the cache)」。

3. 需要时显式标注缓存断点

有些模型提供商或推理框架不支持自动增量前缀缓存,需要手动在上下文中插入缓存断点(cache breakpoint)。标断点时要把缓存过期时间考虑进去,并且至少确保断点覆盖到系统提示的末尾——系统提示是最稳定、最值得缓存的部分。

如果是自托管模型(比如用 vLLM),还要记得开启前缀缓存(prefix/prompt caching),并用会话 ID(session ID)把同一对话的请求一致地路由到同一个推理 worker,否则分布式部署下缓存形同虚设。

二、遮蔽,而不是移除(Mask, Don't Remove)

随着 agent 能力增长,动作空间(工具集)会自然爆炸——尤其是 MCP(Model Context Protocol)这类协议流行后,用户可以随手往 agent 里插几十上百个工具。工具一多,模型就更容易选错动作、走低效路径。作者的原话很扎心:「你那武装到牙齿的 agent 反而变笨了(your heavily armed agent gets dumber)」。

直觉的解法是「按需加载」:用类 RAG 的方式,任务进行到哪一步就动态挂载哪些工具定义。Manus 试过,结论是:除非万不得已,避免在迭代中途动态增删工具定义。两个原因:

Manus 的替代方案:工具定义一直全量留在上下文里,用一个上下文感知的状态机(state machine)来管理「此刻哪些工具可用」——不是把不可用的工具删掉,而是在解码阶段对 token 的 logits 做遮蔽(logits masking),阻止(或强制)选择某些动作。模型「看得见」所有工具,但「说不出」被遮蔽的那些。

具体实现依托大多数推理框架都支持的响应预填充(response prefill),即由框架替模型先写好回复的开头,约束它接下来能生成什么。以 Hermes 函数调用格式为例,有三种模式:

模式语义预填内容
Auto模型可以调用函数,也可以不调<|im_start|>assistant
Required必须调用某个函数,但不限定是哪个<|im_start|>assistant<tool_call>
Specified必须从指定子集中选一个函数预填到函数名开头,如 <tool_call>{"name": "browser_

注意第三种的巧妙之处:它依赖 Manus 刻意的工具命名设计——所有浏览器工具都以 browser_ 开头,所有命令行工具都以 shell_ 开头。于是「限定模型只能用浏览器工具」这件事,只需要把函数名预填到 "browser_ 为止,不需要实现有状态的 logits 处理器(stateful logits processor)。再举一个状态机的例子:当用户发来新消息时,状态机可以强制 Manus 立即用文本回复用户,而不是执行任何动作。这些设计让 Manus 的 agent 循环在纯模型驱动的架构下依然稳定。

三、把文件系统当作上下文(Use the File System as Context)

现代前沿模型的上下文窗口普遍到了 128K token 甚至更长,但在真实 agent 场景里,这常常不够,有时甚至是负担。三个痛点:

常规应对是截断或摘要压缩,但这里有个 agent 特有的根本矛盾:agent 必须基于全部先前状态预测下一步,而你无法预知哪条观测会在十步之后突然变得关键。从这个逻辑出发,「任何不可逆的压缩都带着风险(any irreversible compression carries risk)」——你今天摘要掉的那句话,可能就是明天缺的那块拼图。

Manus 的解法是把文件系统当作终极上下文:它「大小无限、天然持久、并且 agent 自己可以直接操作(unlimited in size, persistent by nature, and directly operable by the agent itself)」。模型学会按需读写文件——文件系统不只是存储,而是外部化的结构化记忆

关键约束是:压缩策略必须始终是可恢复的(restorable)。文中给了两个具体做法:

这样 Manus 就能在不永久丢失信息的前提下,大幅收缩上下文长度。压缩掉的是「字节」,保留的是「还原线索」。

这一节结尾有段有趣的展望:作者联想到状态空间模型(State Space Model, SSM)——这类模型没有 Transformer 的全注意力机制,长程依赖是弱项,但推理又快又省。如果 SSM 能学会基于文件的记忆,把长期状态外置到上下文之外而不是硬记在窗口里,那它们的速度和效率优势可能会催生出新一类 agent。原文说:「Agentic SSMs could be the real successors to Neural Turing Machines(具备 agent 能力的 SSM 可能才是神经图灵机的真正继承者)」。

四、通过复述操纵注意力(Manipulate Attention Through Recitation)

用过 Manus 的人会注意到一个细节:处理复杂任务时,它喜欢先创建一个 todo.md 文件,然后随任务推进逐步更新它、勾掉完成项。作者揭底:这不是卖萌的小习惯,而是一套刻意设计的注意力操纵机制

背景数字:Manus 上一个典型任务平均需要约 50 次工具调用。这么长的循环里,依赖 LLM 决策的 agent 很容易跑题、或者忘掉最初的目标——尤其是全局计划往往写在上下文的最前面,离「当前正在生成的位置」隔着几万 token,正好落在模型注意力最弱的「中段迷失(lost-in-the-middle)」区域。

而「不断重写 todo 清单」这个动作,本质上是把全局计划复述(recite)到上下文的末尾——也就是模型近期注意力最强的区域。目标被一遍遍推到眼前,「目标错位(goal misalignment)」和跑题自然减少。妙处在于:这完全用自然语言实现了对模型注意力焦点的引导,不需要改任何模型架构、不需要特殊 token,一个 agent 自己维护的 markdown 文件就够了。

五、把错的东西留在上下文里(Keep the Wrong Stuff In)

Agent 会犯错。这不是 bug,而是现实:模型会产生幻觉、环境会报错、外部工具会抽风、边缘情况随时冒出来。在多步任务里,「失败不是例外,失败是循环的一部分(failure is not the exception; it's part of the loop)」。

面对错误,工程师的本能冲动是「藏起来」:清理失败轨迹、重试动作、重置模型状态,寄希望于神奇的「温度(temperature)」带来不同结果。看起来更安全、更可控,但代价是:抹掉失败,就抹掉了证据。没有证据,模型无从适应。

作者给出的经验反直觉但简单有效:把走错的路留在上下文里。当模型看到一次失败的动作、以及随之而来的错误观测或堆栈跟踪(stack trace),它会隐式地更新内部信念——把先验概率从这类动作上挪开,降低重复同一个错误的几率。不需要显式教它「别这么干」,失败痕迹本身就是最好的负样本。

作者甚至把这一点抬到了对 agent 本质的判断:

"Error recovery is one of the clearest indicators of true agentic behavior."
错误恢复能力,是「真正 agent 行为」最清晰的指标之一。

但他也指出,这一点在学术研究和公开基准测试里被系统性低估了——大多数基准测的是「理想条件下的任务成功率」,而不是「搞砸之后能不能爬起来」。

六、别被 few-shot 套住(Don't Get Few-Shotted)

少样本提示(few-shot prompting)是提升 LLM 输出质量的标准技巧,但在 agent 系统里,它会以一种微妙的方式反噬。语言模型是出色的模仿者:上下文里充满相似的「动作-观测」对时,模型会倾向于机械跟随这个模式——哪怕它已经不再是当前最优解

文中的例子很具体:用 Manus 批量审阅 20 份简历时,agent 常常陷入一种「节奏」——仅仅因为上下文里前面都是同样的动作序列,就对每一份简历重复一模一样的操作,导致漂移(drift)、过度泛化,甚至幻觉。第 1 份简历和第 15 份简历可能需要完全不同的处理深度,但模式惯性会把它们碾平。

解法是引入结构化的变化(structured variation):在动作和观测的呈现上刻意加入少量多样性——不同的序列化模板(serialization templates)、替换性的措辞(alternate phrasing)、顺序或格式上的轻微噪声。这种「受控的随机性」能打破模式惯性、重新调整模型的注意力。一句话总结:

"The more uniform your context, the more brittle your agent becomes."
你的上下文越千篇一律,你的 agent 就越脆弱。

(原文此节配有示意图,大意是:上下文里堆满高度相似的动作-观测对时,模型输出分布会收窄到「继续重复」上;注入格式变化后分布重新展开。文中其余配图也多为此类机制示意,结论均已融入上文文字。)

结语:一次一个上下文

作者在结尾保持了工程师的克制:上下文工程仍是一门新兴学科,但对 agent 系统而言已是必需品。模型会越来越强、越来越快、越来越便宜,但再强的原始能力也替代不了对记忆、环境与反馈的需求——你如何塑造上下文,最终定义了 agent 的行为:跑多快、恢复得多好、能扩展到多远。

这六条经验来自四次框架重写、无数条死胡同,以及数百万用户的真实使用检验。它们不是普适真理,但「如果能帮你少走一次痛苦的迭代,这篇文章就完成了使命」。全文最后一句已成为这个领域被引用最多的口号之一:

"The agentic future will be built one context at a time."
Agent 的未来,将是一个上下文、一个上下文地构建出来的。
对开发者的启示