ContextChef (4):Offloader/VFS——不破坏信息,只搬移信息
8 Mar 2026
1 min read
English version: ContextChef (4): Offloader/VFS — Relocate Information, Don’t Destroy It
工具返回了 15000 字的 webpack 构建日志。你把它原样塞进历史,下一轮 token 暴增,模型的注意力被这堵”噪声墙”分散,真正有用的最后几行错误信息反而被淹没。
直觉上的处理方式是截断——超过阈值就只保留最后 N 行。这没问题,但截断意味着信息丢失,而你在截断的时候并不知道第 3000 行里有没有某个关键的警告,会在十步之后变得重要。
设计角度:搬移,不是删除
Manus 在 Context Engineering for AI Agents 里提出的原则是:压缩策略必须是可恢复的(restorable)。他们把文件系统当做 Agent 的终极上下文存储,内容可以从上下文里移走,但只要文件路径还在,模型随时可以重新读取。
Anthropic 在 Claude Code 里用了同样的思路,称之为 just-in-time context:Agent 维护轻量的标识符,在真正需要完整数据时才加载进上下文,而不是预先塞入所有内容。
Offloader 的设计角度和这两者一致:不破坏信息,只搬移信息。大输出超限时,完整内容写入本地 VFS,上下文里保留截断摘要加 context://vfs/<hash> URI。信息没有消失,只是换了存放位置,入口还在上下文里。
这个角度的优势在于:对模型诚实。模型看到 URI,知道有完整内容可以按需读取,不会因为只看到截断内容就误以为工具的输出本身就这么少。这比静默截断的信息损失风险低得多——你不是在替模型决定”这些内容不重要”,你是在说”完整内容在这里,需要的时候来取”。
URI 是关键设计,不是实现细节
context://vfs/<hash> 这个 URI 不只是一个文件路径。它是一个协议约定:任何以 context://vfs/ 开头的字符串,模型都知道可以用 read_vfs 工具读取完整内容。
这个设计的好处是一致性:不管被卸载的是终端日志、文件内容、还是 API 响应,读取方式都一样,模型不需要区分来源。开发者侧也一样——只需要注册一个 read_vfs 工具,所有大输出的读取路径都走这里,不需要为每种内容类型分别处理。
tailLines 参数体现了对不同内容类型的适配意识:终端日志保留末尾 20 行(错误通常在末尾),静态文档设为 0(任意位置都可能有用,全部卸载,让模型按需读取)。默认值是针对最常见的场景——工具输出——调好的,不需要每次都显式指定。
const safeLog = chef.offload(rawTerminalOutput); // 日志:保留末尾 20 行
const safeDoc = chef.offload(largeDoc, { tailLines: 0 }); // 文档:全量卸载与 Janitor 的配合:无损先行
Offloader 和 Janitor 的分工很自然:Offloader 做无损搬移,Janitor 做有损摘要。当 token 预算超限时,应该先尝试无损的——把大型工具结果卸载到 VFS,看能否在不摘要的情况下把 token 数降下来;如果卸载还不够,再走摘要压缩。
这个顺序的价值是:摘要是有损操作,你永远不知道它丢了哪些”当时看起来不重要、后来却关键”的细节。能无损解决的,就不走有损路径。Janitor 的 onBudgetExceeded 钩子让这个两阶段策略可以显式实现,而不需要在外部手动协调两个模块。
下一篇:Core Memory——为什么”让 LLM 决定记什么”是一个危险的设计。