@BrainsAndTennis: https://x.com/BrainsAndTennis/status/2065190286519906657

X AI KOLs Timeline 工具

摘要

一条技术性 Twitter 线程,分享构建高性能垂直 AI Agent 的原则,以 Shortcut 电子表格 Agent 为例。核心见解:将上下文视为分层缓存(L1/L2/L3),以在分布中最小化每个任务的成本。

https://t.co/MVcIdCly31
查看原文
查看缓存全文

缓存时间: 2026/06/12 04:52

构建一个好的垂直智能体

如何构建一个在特定领域内真正有表现的智能体——一个客户愿意选择它,因为它更出色?

过去一年,基础知识已经标准化:智能体就是一个围绕模型的 while 循环,调用工具直到任务完成。给它一个文件系统,给它一个 shell,让它通过这个做大部分事情。你一个下午就能写出来,大多数人也都写过。每个人都能构建一个智能体——这真的没那么难,而且,就像我会详细说明的,它也没那么深奥。让一个好智能体区别于玩具的,不是聪明才智;而是对你领域的真正理解,以及在少数关键地方耐心做一些乏味而细致的工作的意愿。

我花了将近一年时间构建 Shortcut 智能体,它被广泛认为是目前最准确的电子表格智能体——它部署在四家最大多策略对冲基金中的三家内部,在那里犯错代价高昂,且没有人按曲线评分。我们没有微软或 Anthropic 那样的分发渠道。我们有的是智能体更常正确,而在这个领域,这是客户选择我们的唯一最有说服力的理由。所以智能体性能是我整天思考的问题。

而我不断遇到的一个差距是:关于构建智能体的文章很多,但关于构建好智能体的却很少。看看这个领域在最基本的问题上差异有多大——比如工具数量:Codex 和 Claude Code 各提供约 30 个工具;Pi 提供 7 个。当流行的智能体在最基本的设计问题上相差 4 倍时,这说明了:没有公认的原则。所以我分享我的原则,来自一年的构建经验,为任何自己编写智能体的人揭开这个过程的神秘面纱。

原则如下:一个好的智能体是其任务分布的忠实压缩。剩下的只是这到底意味着什么,以及它迫使你构建什么。

上下文作为分层缓存

假设你不拥有环境,也没有训练模型。那么有三件事你可以自行设计——系统提示、工具和制品(技能、策划文档、参考资料)——而且它们都是同一件事:智能体的上下文。

那么游戏的规则很简单。模型固定后,准确性是上下文质量的函数:臃肿的上下文会埋没信号,缺失的上下文会导致猜测,两者都会牺牲准确性。而准确性正是你所销售的——这种关系不是线性的,一个得分 99% 的任务比得分 95% 的任务价值高出十倍。

但你的用户不会给你带来统一的问题分布。他们带来的是长尾分布:

智能体必须处理所有这些问题。但它不能一次性将所有这些内容都放在上下文中——那是臃肿提示的失败模式。所以真正的目标比“让一切可用”更精确:最小化每个任务所花费的上下文,按任务分布平均。

这完全就是 CPU 面临的问题。一个程序可能触及千兆字节的数据,但处理器旁边的存储却很小——所以计算机将内存分层放置:一个小的、即时的缓存(L1),下面更大更慢的层(L2、L3),然后是主内存和磁盘。这之所以有效,是因为访问也是长尾的:将热点集保留在快速层中,只有在处理稀有时才深入到慢速层。“缓存未命中”是指你需要的内容不在快速层中,你需要付出代价从较慢的层获取它——正是你在常见路径上避免的成本。

智能体应该具有相同的结构。将你的上下文构建为 L1 / L2 / L3。

几乎每一个优化都在信息的压缩和发现的速度之间进行权衡。把某物放在 L1 中是即时的,但每个任务都会消耗提示令牌,不管它是否被使用。把它推到 L3,它在被需要之前都不消耗令牌——但那时需要多次工具调用来找到它。你的工作是将每个能力放置在能最小化整个分布总成本的层级上。这就是全部技巧。让我用我最熟悉的领域来具体说明。

旁白:一个工具,而不是三十个

在层级之前,先谈基础。我接下来要描述的每一个电子表格能力——每一次读取、每一次写入、每一次策划查找——都是在单个工具下执行的代码。

智能体编写代码;代码调用我们的函数;函数操作表格。没有 read_range 工具,没有 write_range 工具,没有 make_chart 工具。只有一个工具,API 存在于代码内部。

为什么?因为随着你添加工具,模型准确性会下降。这在我们自己的实验中一直是一致的。每添加一个工具,就相当于向提示中添加更多的模式,更多的混淆表面,更容易选错,尤其是当工具职责重叠时。一个单一的 execute_code 工具将所有决策归结为一个——编写代码——并让模型用编程语言或 DSL 的全部表达能力来组合能力,而不是将僵硬的工具调用拼接起来(更多内容将在未来的文章中讨论)。

这对层级很重要,因为这意味着所有三个缓存层都可以从同一个地方访问:模型总是在编写代码,而 L1/L2/L3 只是它知道可以调用哪些函数,以及找到它们需要多少工作量。

L1——核心业务:读写单元格

这是 80%。如果读写单元格范围做不好,其他一切都无关紧要。所以这就是我们投入了荒谬、不成比例精力的地方。看看一个简单的 getCellRange 实际上做了什么。

读取范围是一种压缩行为

读取一个 200 行的收入表:

三件事正在发生。

首先,公式别名化。一个 500 行的列,内容是 =A2*B2, =A3*B3, …,是 500 个几乎相同的公式。我们将每个公式标准化为 R1C1 形式——所以 =A2*B2 和 =A3*B3 都变成 =RC[-2]*RC[-1]——统计模式,任何出现超过十次的模式都会折叠成一个简短的别名,比如 F1。模型看到的是重复的 F1 加上一行图例,而不是 500 个公式。大幅节省令牌,零信息损失。

第二,免费的行和列上下文。当你读取 C5:E20 时,这些裸数字代表什么?我们向左扫描行标签,向上扫描标题行(通过投票选择最近哪一行包含最多的文本单元格)并附加它们,所以模型免费获得 Region | Q1 | Q2 和 North America | …,永远不需要猜测数字网格代表什么。

第三,样式压缩。格式也是信息——一个粗体红色、数字格式为 0.00% 的单元格在告诉你一些事情——但列出每个单元格的完整样式会淹没值。所以我们按相同样式对单元格分组,将每个组折叠为其连通的区域,每组分两行打印:区域、单元格数量以及紧凑的描述。

六百个公式变成了一行图例。四百个带样式的单元格变成了两行。而模型从未明确请求的标题行就在底部。整个表格,无损,以原始转储所需令牌的一小部分呈现。每一个这些都是压缩与发现的权衡,在常见情况下优势明显。

写入单元格:告诉模型它实际改变了什么,以及什么看起来有问题

写入比看起来更难,因为单个 execute_code 调用可以改变数百个单元格,而智能体需要知道发生了什么,而无需重新读取整个表格。所以在代码运行后,我们传回一个每个发生变化的单元格的结构化 diff——而且,同样重要的是,我们压缩并分类处理它。

代码:

返回的 diff:

两种压缩在这里起作用。

首先,diff 被分组和采样,而不是全量转储。更改的单元格按工作表和行分组,每一行显示为列范围和计数(第 2 行 (D): 1 个单元格),并且只打印每行和每节单元格的确定性样本,其余部分用 “… 以及另外 N 个” 的计数。两百次写入变成了一小部分,智能体仍然知道总数。

其次,diff 被分类。干净的写入归入“无问题更改”。任何看起来可疑的内容——无效公式如 #REF!、未标记的硬编码数字、硬编码数字嵌入公式中、异常大的百分比——都被拉入“需要检查的单元格”部分,最严重的违规者被标记为 必须修复。第 57 行中的那个 #REF! 在两行绿色 diff 的墙中很容易被忽略;在这里它以标签的形式浮现在顶部。反馈循环不是“这是改变的内容”,而是“这是改变的内容,以及你可能弄错的部分”——智能体自身编辑的内置 linter。

L1 一句话:曲线陡峭部分的操作获得功能工程、令牌压缩和后果报告包装,这些包装永远存在于提示中。构建它们代价高昂,但你仍然要构建,因为智能体在每个任务上都承担了这个成本。

L2——按需策划的英文文档

你不能把所有东西都放在 L1 中。条件格式、数据透视表、图表、数据验证、复制/移动语义——每一个都很重要,每一个在会话中出现几次,并且每一个都有足够多的表面,如果将其记录在系统提示中,会使得不使用它的每个任务都臃肿。经典的 L2。

所以我们编写了策划的能力规范,用英文,按需获取,就像技能 md 一样。智能体在其代码内部调用:

这些不是类型签名的转储。它们是手写的散文——每个几百行——描述完成任务的规范方法,包括原始 API 永远不会告诉你的知识。以数据透视表规范为例。它不仅仅列出方法;它教授整个配方,按正确顺序:

并且它内置了那些你只有反复失败才能学到的东西:你必须围绕一批更改调用 suspendLayout()/resumeLayout(),否则表会在每次调用时重建;值字段的聚合必须以原始整数传递(求和为 8),因为在运行时友好的枚举不存在。这些都不是古怪的坑——而是正确进行数据透视表的实际形状,由已经付出代价的人一次性写下来。

关键属性:直到任务需要它,这个成本为零。一个从未涉及数据透视表的任务永远不会为数据透视表文档付出代价。一个 console.log 就是整个发现成本——单个缓存未命中,快速服务。

同样的想法,用于可执行工具

L2 不仅仅是文档。我们将相同的模式应用于延迟工具——web_search、web_crawl、create_website 等。它们的模式不在提示中。取而代之的是一个元工具墙:

获取的工具集实际上是一个会话范围的缓存。模型加载一次模式,从那时起它就常驻。相同的压缩与发现权衡,相同的解决方案:保持提示小巧,在真正需要能力时支付一步未命中的成本。这与 Claude 上的延迟工具是相同的思想,但我们不局限于某个供应商的工具加载功能。

L3——原始巨著,以及映射它的技能

然后是长尾:那个我们从未包装过、也从未写过规范的晦涩东西。你无法预见到它——显然。但智能体仍然必须能够到达那里,否则它会撞墙并失败任务。具体来说,这就是这类请求最终到达的地方:

  • “为每一行添加一个迷你图来总结其趋势”——迷你图是一个真实但很少触动的 API 表面。
  • “将图表的次要坐标轴设置为对数刻度,并仅为第三个系列重新着色”——一个图表属性,三层深,没有任何策划规范费心涵盖。
  • “从此单元格插入一个超链接到那个命名范围,并对这些形状进行分组”——绘图/形状/超链接的角落,之前没人问到。

所以 L3 是完整的原始 API——整个 Office.js 表面(Excel 插件)或整个 SpreadJS 表面(Shortcut 网页),转储到磁盘。它是一个机器生成的参考,70,000 行长。它包含一切。但它也完全无法用作提示上下文——你永远不会粘贴进去。

诀窍:你给它一个技能——一个简短的地图,教它如何用 bash 挖掘那部巨著:

技能大约 100 行。它说:这里是结构,这里是每个方法和类型条目的形状,这里是针对每种问题的 grep 配方。有了它,智能体从“成千上万行我无法阅读”变成“3-6 次 grep 就能精确地调出我需要的签名。”这就是 L3 的访问成本——真实但有限,并且只有深入到这一层的罕见任务才需要付出。

而系统提示使这个逃生舱口明确,所以模型知道路径存在以及何时使用它:

API 层级——有 2 个级别的 API 能力。包装的 API:便捷函数;一些直接列出,其他通过 getAPIInfo(…) 访问。永远不要猜测——完整阅读文档。原始 API:当包装的 API 不能满足你的需求时使用……如果包装的 API 做不到,就使用原始 API——不要妥协。

最后那个从句就是 L3 的全部意义。智能体永远不应该被困住。它可以在 L1 中错过,降到 L2,如果即使策划的规范也没有答案,就深入原始巨著,并且仍然能在合理的调用次数内得到答案。

提示预算实际如何分配

值得看看令牌的去向,因为层级直接体现在系统提示的形状中。

提示的大部分是 L1——大约几百行。核心的读写操作、execute_code 契约、关键类型以及智能体在几乎所有任务上使用的少数方法,加上执行和安全指南。这是每次调用都常驻的部分,所以也是我们最努力保持紧凑的部分。

L2 是之上的薄薄一层——大约 50 行。它不是规范本身;它是一个策划的允许列表,包含“受祝福的”方法以及告诉智能体 getXInfo(…) 规范存在以及何时使用它们的指针。规范的实际内容留在提示之外,直到 console.log 将其拉入。

L3 基本上是 5 行,即 skill.md 的名称和描述,以及其他分散在各处的引用。原始参考——70,000 行——完全存在于磁盘上,从未触及提示。所有常驻的就是那个简短的技能文件以及 API 层级部分指向它的一行。

所以预算反映了频率曲线:大部分提示花在 80% 的案例上,一小部分用于指引 15%,而长尾部分几乎不花什么——这正好是缓存层级框架所预测的分配。

配方,移植到你的领域

电子表格只是我的例子。这个结构可以移植到任何领域。系统提示和策划规范中的压缩实际上是对你的用户分布以及他们执行的任务的编码——而在你的领域,你比任何人都更了解这种分布。所以你的任务是三个问题:

  1. 你把什么包裹进 L1?频率曲线陡峭部分的核心业务操作。让它们极度令牌高效且快速,并使它们报告后果。在这里投入不成比例的努力——智能体在每个任务上都承担这个成本。

  2. 你把什么推迟到 L2?重要但偶尔出现的能力。将它们写成策划的、英文的、包含陷阱的规范,一步发现即可达到。编码规范配方和约束,而不仅仅是签名。

  3. 你的逃生舱口(L3)是什么?原始的、完整的基底——加上一个教智能体挖掘它的技能。它不需要很人性化。它必须是可以到达的、完整的,并且可以在有限步数内找到。智能体必须能够——并且最终会——找到正确信息。

把这三个位置放对了,你就构建了一个在常见情况下快速、在偶尔情况下有能力,并且在罕见情况下从不真正被困住的智能体——同时保持上下文足够小巧,使模型保持敏锐。

层级不会消失——它会移动

一个最后的观察。什么算 L1 不是固定的;它会随着模型强度漂移。

早期、较弱的模型需要微小、单一用途的工具,

相似文章

关于 AI 智能体的真实内情

Reddit r/AI_Agents

一位资深从业者分享了将 25 个以上 AI 智能体部署到生产环境的经验教训,指出记忆、编排和可审计性远比模型选择重要。文章详细介绍了上下文丢失、静默成本循环等常见故障模式,并推荐了包含 Claude Sonnet 4、Pydantic AI 以及 Octopodas 等专用记忆层的技术栈。