--- title: "优秀的垂类Agent构建实战:CPU缓存与Agent上下文管理" source_url: "https://mp.weixin.qq.com/s/4MJ9_wqTx7ttGilKCHkX9w" source: "wechat|AI技术立文" author: "AI技术立文" publish_date: "2026-06-12" ingested: "2026-06-12" type: article tags: [] source_type: wechat sha256: "bafc7641d7e11a59e665b401a0fc76dd994e2dbd25219d8c25d8d0d7f05535c3" --- 把 CPU 缓存的 L1/L2/L3 层级结构,**直接迁移到 Agent 上下文管理**。作者从"提示词臃肿"的失败模式出发,把 Agent 上下文构建成 L1(常驻)/ L2(按需规格文档)/ L3(原始 API 大全 + 检索技能)三层,配套"一个工具而不是三十个"的设计原则、读取区间的三重压缩、写入 diff 的分组采样 + 问题分类等具体工程模式。 ## 核心命题 **Agent 开发,假设你不拥有运行环境,也没有训练模型,那么你能设计的东西只有三样:系统提示、工具,以及各类产出物(skill 文件、精心整理的文档、参考资料)。这三样东西本质上是一回事:Agent 的上下文。** 模型固定之后,准确率就是上下文质量的函数。**99% 准确率的任务,其价值是 95% 任务的十倍**——这个关系不是线性的。 但用户问题呈长尾分布:80% 是高频主干任务,15% 是偶发重要任务,剩下 5%+ 是稀疏长尾。Agent 必须覆盖所有场景,但不可能把一切同时塞进上下文(context),那正是"提示词臃肿"的失败模式。 **真正要解决的问题:在整条任务分布曲线上,最小化每个任务平均消耗的上下文开销**。 ## CPU 缓存的类比 一个程序可能触碰几 GB 数据,但紧贴处理器的存储空间极小——CPU 将内存分成多个层级:L1 极快极小 / L2 L3 稍大稍慢 / 主存和磁盘。这套机制有效,因为**数据访问也呈长尾分布**:热数据放在快速层,只在需要时才向慢层取。 **Agent 应该采用同样的结构**——把上下文构建成 L1 / L2 / L3。 ### L1 — 常驻内容(80% 覆盖) - 极小、即时可用 - 放在系统提示里 - 未命中代价:一次廉价调用 ### L2 — 按需加载(15% 覆盖) - 精心整理的规格文档 - 一步发现即可加载 - 未命中代价:读 skill 文件 + 搜索 ### L3 — 兜底路径(5%+ 覆盖) - 原始 API 全集 - 覆盖长尾 - 3-6 次 grep 即可定位 **几乎所有优化都围绕"信息压缩"与"发现速度"之间的权衡**。把某项能力放进 L1,即时可用但无论是否需要都消耗 token;推到 L3,不用时零成本,一旦需要付出多次工具调用代价。 ## 一个工具,而不是三十个 在进入层级设计之前,先说底层基础。**所有电子表格能力都通过一个工具 execute_code**: ```javascript async function execute() { const data = await sheet.getCellRange("Sheet1!A1:D200"); // ...读取、计算、写入... } ``` Agent 写代码 → 代码调函数 → 函数操作电子表格。**没有 read_range / write_range / make_chart 工具**。只有一个工具,API 就在代码内部。 **原因**:每多一个工具,提示词就多一份 schema,模型面对的选择歧义就更大——在工具职责有重叠时,这个问题被进一步放大。**一个 execute_code 工具把所有决策折叠成一步**:让模型用编程语言的完整表达力组合各种能力,而非拼凑僵硬的工具调用。 **这与 [[entities/ai-agent-tool-count-trap|AI Agent 工具数量陷阱]] 数据完全吻合**:Anthropic 测试"5-10 个工具是上限";本文走得更远,**"1 个 execute_code 工具 = 0 个 prompt token 工具税"**。 **对层级设计的关键意义**:三个缓存层从**同一个入口触达**——模型始终在写代码,L1/L2/L3 只决定它知道哪些函数可调用,以及找到这些函数要付出多少代价。 ## L1 实战:读取区间的三重压缩 读取 200 行营收表,把六百个公式 + 四百个样式单元格压缩到原 dump 的一小部分 token: ### 压缩 1:公式别名化 500 个 `=A2*B2`、`=A3*B3`... 几乎相同 → 规范化为 R1C1 格式 → `=A2*B2` 和 `=A3*B3` 都变成 `=RC[-2]*RC[-1]`。统计模式出现次数,超过十次的模式折叠成短别名如 `F1`。**模型看到的是反复出现的 F1 加一行说明,而非 500 个公式**。 ### 压缩 2:自动补充行列语义 读取 `C5:E20` 时,那些裸数字代表什么?**向左扫描行标签、向上扫描标题行**(通过投票选出文本单元格最多的附近行作为标题),将它们一并附加。模型自动获得 `Region | Q1 | Q2` 和 `North America | ...` 这样的语义。 ### 压缩 3:样式压缩 格式也是信息——粗体红色 + 0.00% 数字格式传递某种信号。但逐个列出每个单元格样式会淹没数值本身。**按相同样式对单元格分组,每组折叠为连续区间,打印一行**。 **结果**:六百个公式变成一行说明,四百个样式单元格变成两行,模型从未要求的标题行附在末尾。 ## L1 实战:写入 diff 的双重压缩 一次 execute_code 调用可能改变数百个单元格。代码运行后,**返回结构化 diff**,列出每个变更单元格,同时压缩 + 分级。 ### 压缩机制 1:分组采样而非全量 dump 变更单元格按工作表和行分组,每行以带计数的列区间呈现(第 2 行(D):1 个单元格),只打印确定性采样的若干单元格,其余用"...以及另外 N 行"代替。**两百次写入变成寥寥几条,Agent 仍能掌握总量**。 ### 压缩机制 2:问题分类 - **无问题的变更**:归入此类 - **需要审查的单元格**:可疑内容(#REF! 这类无效公式、未标注的硬编码数字、嵌在公式里的硬编码数字、异常大的百分比)归入此类 - **必须修复**:最严重的问题单独标注并置顶 **反馈循环从"这是变更内容"变为"这是变更内容,以及其中需要关注的部分"**——相当于 Agent 自身编辑行为的内置 linter。 **L1 小结**:频率曲线陡峭部分的操作,需要经过**精心设计、token 高效、能汇报变更后果**的包装器,并固定在提示词中。建设成本较高,但每个任务都依赖它们——值得投入。 ## L2 实战:规格文档按需加载 不可能把所有东西都放进 L1。条件格式、数据透视表、图表、数据验证——每项都重要,每次会话用几次,但文档量足够大。**典型的 L2 场景**。 模型从代码内部调用: ```javascript console.log(general.getConditionalFormattingInfo()); console.log(general.getPivotTableInfo()); console.log(general.getChartInfo()); console.log(general.getDataValidationInfo()); console.log(general.getAPIInfo("addSpanAt")); // 按名称获取任意单个函数 ``` 这些**不是类型签名的 dump**,而是手写的文档,每份几百行,描述完成任务的规范方式——**包含原始 API 不会直接告诉你的知识**: ```javascript const pt = sheet.originalSheet.pivotTables.add("SalesPivot", "SalesData", 0, 0, ...); pt.suspendLayout(); pt.add("Region", "Region", rowField); pt.add("Quarter", "Quarter", columnField); pt.add("Amount", "Sum of Amount", valueField, 8); // 8 = sum pt.resumeLayout(); ``` 把只有踩坑之后才能学到的东西写进去:批量修改必须用 `suspendLayout()/resumeLayout()` 包裹,否则表格每次调用后重建;值字段聚合方式必须传入原始整数(sum 是 8),因为友好枚举运行时不存在。 **关键属性**:在任务需要它之前,这些文档的 token 成本为**零**。一次 `console.log` 就是全部发现代价。 ## L2 实战:延迟工具(Deferred Tools) L2 不只用于文档。把模式应用于**延迟工具**——`web_search`、`web_crawl`、`create_website` 等: ```javascript get_tool_info("web_search") → 返回 schema,标记为"已获取" execute_tool("web_search", …) → 如果未先获取,则拒绝执行 ``` **已获取工具的集合即一个会话级缓存**——模型加载一次 schema,从此保持可用。提示词保持精简,只在真正需要时付出一步未命中的代价。 **这与 Claude 的延迟工具思路相同,但不依赖特定厂商的工具加载特性**——可移植的设计。 ## L3 实战:原始全集 + 检索技能文件 长尾:从未被包装、也从未有过规格文档的偏门需求。**这类需求无法预见,定义上如此**。但 Agent 必须能处理它们: - "给每行加一个 sparkline"(真实但少被触碰的 API 面) - "把图表的副坐标轴设为对数刻度,并只给第三个系列重新着色"(深入三层的图表属性) - "插超链接到命名区间,并把这些图形组合起来"(绘图/图形/超链接的角落地带) **L3 = 完整的原始 API 全文 + 教 Agent 如何检索的技能文件**(约 100 行): ```bash grep -n '"charts.add"' api-reference.json -A 5 # 查找一个方法 grep -n '"pivots\.' api-reference.json | head # 列出一个命名空间 grep -n '"ChartConfig"' api-reference.json -A 10 # 解析一个类型 grep -n '"isEnum": true' api-reference.json -B2 -A10 # 枚举所有枚举值 ``` 通过 3-6 次 grep 定位到所需签名。**L3 的访问代价真实存在,但有上限**。 ## 提示词预算分配 | 层级 | 系统提示中占多少 | 内容 | |------|------------------|------| | **L1** | 几百行 | 核心读写操作、execute_code 契约、关键类型、执行和安全指南——每次调用常驻 | | **L2** | 约 50 行 | 不是规格文档本身,是"受认可"方法白名单 + 指向 `getXInfo(...)` 规格文档的说明 | | **L3** | 5 行 | 技能文件名称和描述 + 几行引用 | **原始参考文档 7 万行完全放在磁盘,从不进入提示词**。常驻的只有短小的技能文件和 API 层级那一节里指向它的一行。 **预算分配与频率曲线吻合**:大部分 token 花在 80% 情况上,少量用于指向 15% 路标,长尾几乎不占空间。 ## 迁移到任何领域 三个问题决定层级设计: 1. **什么要包装进 L1?** 频率曲线陡峭部分的主干操作。让它们 token 高效、能汇报变更后果——Agent 在每个任务上都依赖这些 2. **什么要推迟到 L2?** 重要但不常见的能力。写成精心整理的规格文档,一步发现即可加载。重点编码规范流程和约束 3. **L3 是什么?** 完整的原始底层基础 + 教 Agent 如何检索的技能文件。不必设计易用,只要内容完整、可以触达、有限步骤内能找到即可 三个层级到位 → **常见场景响应高效、偶发场景能力完整、罕见场景不会止步**,同时上下文控制在紧凑范围内,模型准确率稳定。 ## 层级会移动但不会消失 **L1 的边界随模型能力而变化**。早期模型需要小而单一的工具,今天的模型能一次处理更大的 L2 规格文档。**随着模型能力提升,昨天的 L3 成了今天的 L2,昨天的 L2 折叠进 L1**。Agent 的能力边界向外扩展,各层级相应下移。 **但层级结构本身不会消失**——因为相对于所有可以放入的内容,上下文始终稀缺,多余内容始终损耗准确率。没有任何模型强大到让"在正确时机把正确内容放在它面前"失去意义。 **更大的上下文窗口容易让人倾向于放入更多内容**。但更有效的做法是 **CPU 数十年前已验证的方案:摘要放在缓存,细节按需取用,原始底层兜底**。把 Agent 的上下文管理做成内存层级,准确率自然随之改善。 ## 与 [[entities/ai-agent-tool-count-trap|Anthropic 工具数量陷阱]] 的对比 | 维度 | Anthropic 答案 | 本文答案 | |------|----------------|----------| | **工具上限** | 5-10 个边界清楚的工具 | **1 个 execute_code 工具** | | **作用域** | 整个 Agent 工具集 | 把"API 集合"折叠进 execute_code 内部 | | **token 税** | 134K / 99 工具 | **接近 0**——只付 execute_code schema 的 token | | **决策压力** | 模型选哪个工具 | 模型写什么代码 | | **表达力** | 受限于工具 API 的固定形态 | 编程语言的完整表达力 | **1 个 execute_code 工具 = 0 工具税 + 编程语言表达力 + L1/L2/L3 通过代码自然分层**。