跳到主要内容

你为单个智能体添加的工具,现在每个智能体都能用了

· 阅读需 11 分钟
Tian Pan
Software Engineer

六个月前,客户支持团队的人为他们的智能体连接了一个 send_email 工具。它奏效了。平台团队在共享工具注册表中注意到了它,在 PR 上点了个大拇指表情,然后就继续忙别的了。本周,一名安全工程师进行审计时发现,send_email 竟然出现在会议摘要智能体、数据质量机器人、一个没人正式负责的分析助手,以及一个自一月份以来就没动过的半成品原型中。这些智能体中没有一个需要发送电子邮件。而且,从来没有人审查过是否 应该 允许它们这么做。会议摘要智能体的 PRD 只有两句话长,其中根本没有出现 “外部通信” 这个词。

这是我审计过的每个共享工具注册表的默认状态。注册工具的行为——将 JSON 模式和处理器推送到中央目录中——被视为一种开发人员的便利,就像向共享库中添加实用程序函数一样。但一旦注册表被引入到每个智能体的提示词中,注册工具就不再仅仅是库变更。它是同时向公司内的每个智能体进行的部署,且完全没有审查每个智能体是否应该接收它。

观念上的错误在于将注册表视为一个 目录 ——即智能体浏览的被动对象——而它实际上起的是 能力授予 的作用。工具进入注册表且注册表加载到智能体上下文的那一刻,该智能体就被授予了该能力。无论智能体在这一轮对话中是否使用它都是次要的。授权已经发生了。

全局目录的默认状态是 “对所有人开放”

大多数团队都是在不经意间建立起共享注册表的。第一个智能体构建完成后,它有三个工具。第二个团队构建智能体时,他们复制了第一个智能体的控制逻辑,因为连接过程很繁琐,而第一个已经能用了。现在,他们之间共享了一个 tools.json 文件,因为保持两份副本同步非常麻烦。当第三个智能体出现时,内部的 npm 或 PyPI 镜像上已经有了 tools-registry 包,导入它就会得到这一整堆工具。

没有人决定每个智能体都应该拥有每个工具。这个决定从未被做出。代码库的结构使其成为了阻力最小的路径,而由于缺乏针对每个智能体的准入列表(allow-list),注册表默认成为了准入列表。这与为了让某个查询正常工作而授予具有 SELECT * 权限的数据库角色,却因为没人想去创建一个权限更紧凑的角色而一直沿用至今的动态是一样的。

问题在于共享注册表的失效模式是 只加不减。当有明确的局部需求时,工具会被添加。工具几乎从未被移除——因为移除需要证明没有任何东西依赖于它们,而且没有人统筹管理整个注册表。因此,目录单调地增长,每个新智能体都继承了之前所有智能体需求的累积债。

为什么 “权限” 意味着 “针对每个智能体”,而非 “针对每台服务器”

MCP 生态系统在教会团队思考认证(authentication)方面做得很好——智能体在调用工具之前是否证明了其身份?——但在教会他们在正确的粒度上思考授权(authorization)方面则差得多。在大多数 MCP 设置中,授权的默认单位是 服务器:一个工具服务器发布一组工具,一个智能体要么拥有授权访问该服务器的令牌,要么没有。

这种粒度在两个方向上都是错误的。首先,它太粗糙了:智能体要么获得整个服务器的工具集,要么一个也得不到,即使它只需要一个工具。其次,它又太窄了:同一个智能体通常会连接到多个服务器,而权限问题——这个智能体是否应该拥有此能力——横跨了所有这些服务器。一个与你的日历服务器和邮件服务器通信的会议摘要智能体在这两个服务器上都不需要写入权限,但服务器范围的令牌是二进制化的,无法表达 “读取日历事件、读取邮件主题、不发送任何内容” 这种细分权限。

授权的单位必须是 (智能体, 工具) 对,而不是服务器。只有在这个级别上,“这种能力是否应该存在” 的问题才能得到真正的回答,因为只有在这个级别上,人才可以说 “会议摘要智能体的工作是总结会议,所以它不需要发送电子邮件,就这么简单”。服务器级别的授权抹杀了这种区别,并迫使其退回到最初导致问题的二进制化逻辑中。

真相大白的审计

发现这个问题的审计通常是这样的。某个人——一名安全工程师、一名新的平台主管,或是一个空闲时间太多的好奇实习生——写了一个脚本,将智能体注册表与工具注册表进行关联,并生成了一个矩阵:哪些智能体在其行动面中拥有哪些工具。这个矩阵的稠密程度超出了所有人的预料。

会议摘要智能体拥有 send_emailcreate_calendar_eventdelete_documentupdate_user_roleexecute_sql。数据质量机器人拥有 send_slack_messagewire_transferrestart_production_serviceescalate_to_oncall。每个智能体都拥有平台团队交付过的每一个工具,因为在入口处没有人设置过滤器。发现的结果并不是智能体被要求做有害的事情——在大多数情况下,LLM 不会在会议摘要期间选择转账。发现的结果是 没有任何机制阻止它这样做,唯一的安全网是模型的良好判断,而这称不上是安全网。

最近关于工具调用最小特权的文献量化了这种审计的感受。2025 年底的 MiniScope 论文发现,在他们的研究中,大多数智能体访问的工具数量是其实际调用工具数量的 3 到 10 倍,而且对于存在时间较长的智能体来说,这一差距更大——因为工具在不断累积,而失效的能力从未被移除。Vercel 工程团队报告称,削减智能体 80% 的工具提高了任务完成度,这从另一个角度说明,那 80% 只是 “顺便捎上” 的工具是有害的,甚至在涉及安全问题之前就是如此。

你从未调用的工具所带来的成本

审计还揭示了一项大多数团队未曾计算的成本:在每一个回合中,无论工具是否被使用,操作面中的每个工具定义都会消耗上下文 Token。据测算,在用户输入任何内容之前,标准的 MCP 配置在工具定义上就可能消耗掉智能体高达 72% 的上下文窗口。伯克利函数调用基准测试 (Berkeley Function Calling Leaderboard) 发现,随着可用工具数量从 4 个增加到 51 个,工具选择的准确率从 43% 骤降至 14% 以下。智能体变得更慢、更笨、更贵 —— 这是你为每次请求支付的三重税 —— 仅仅是因为半年前有人为一个已不存在的工作流添加了一个工具。

因此,即使撇开安全因素不谈,支持针对每个智能体设置允许列表的工程论据也非常充分。更小、更集中的工具范围能产生更好的智能体。而共享注册中心除了其他弊端外,在质量上也是一种退化。

针对每个智能体的允许列表究竟是什么样的

修复方案在概念上很简单,但在操作上却很繁琐,这就是为什么大多数团队还没有这样做。每个智能体都有一个清单 (Manifest) —— 一个小的、纳入版本控制的文件 —— 明确列出允许它看到的工具。注册中心不再定义智能体可以使用什么,清单才具有定义权。注册中心仅仅定义了清单中可以包含的内容。

一个清单看起来像这样:

agent: meeting-notes-summarizer
tools:
- calendar.read_events
- documents.read
- documents.write_to_owner_folder

这三行代码必须由能够回答“这个智能体为了完成工作是否需要这项能力?”的人进行审查。这种审查与你为添加数据库角色或 IAM 策略所做的审查是一样的。产出物很小,Diff 差异清晰可见。“我在注册中心添加了一个工具”的爆炸半径从“所有智能体”缩小到了“我刚刚更新的那个清单”。

添加清单层还创造了一个可以挂载其他策略的地方。你可以声明每个智能体在每个工具上的速率限制。你可以声明数据范围(“该智能体可以读取此文件夹,但不能读取其他文件夹”)。你可以声明允许智能体代表哪些用户身份进行操作。当注册中心是事实上的允许列表时,这些都无法实现,因为注册中心不知道是哪个智能体在请求 —— 它只是向所有人提供相同的目录。

工具集组合作为基本单元

更深层次的转变在于,设计的单元不再是“工具”,而是“智能体的工具集”。孤立的工具没问题,重要的是组合。会议摘要总结器应该拥有一套小型的、内部逻辑自洽的工具集 —— 读取日历、读取文档、将摘要写入受限位置。这套工具集应该作为一个整体进行设计和审查,就像你设计 API 接口或微服务的权限边界一样。

工具集组合明确了注册中心的角色:注册中心是能力的库,而不是默认的操作面。组合工具集是一种刻意的行为,就像组合 SQL 角色或组合 IAM 策略一样。事实上,我们花了二十年时间才把这些其他的组合搞对,然后却给了智能体相当于“GRANT ALL”的权限,这应该让我们感到警惕,而不是心安理得。

这也重新定义了“添加工具”的含义。向注册中心添加工具只是将其添加到库中 —— 没问题,风险低,智能体行为不会改变。而将工具添加到特定智能体的清单中才是真正的部署。这是授予能力的变更。它应该要求进行严格的审查,就像在注册中心出现之前,向单个智能体的硬编码列表中添加工具所需的审查一样。共享注册中心并没有消除这种审查,它只是把审查移到了一个更难被发现的地方。

值得坚持的原则

除非有人设计了明确的边界,否则每个共享资源都会趋向于“所有人都能使用”。一个没有行级安全保护的共享数据库,最终会导致每个服务都能读取每一行。一个没有前缀策略的共享 S3 存储桶,最终会导致每个人都能读取每个人的数据。一个没有针对每个智能体设置清单的共享工具注册中心,最终会导致每个智能体都拥有所有能力。这些状态从未经过深思熟虑,它们只是因为缺乏决策而继承下来的现状。

值得带入智能体平台的原则是:能力授予需要显式的授权,而不是默认许可。注册中心应该只对库进行增补;清单才是授予智能体能力的地方;清单才是需要被审查的对象。请以授予智能体数据库角色同等的审慎态度,来对待向特定智能体清单中添加工具的行为。如果你不放心通过在共享配置中添加一行代码就给后端每个服务授予 send_email 权限,那么也不要放心地对公司里的每个智能体做同样的事情。

审计结果总是一样的。随处可见的冗余工具。悄悄获得无人授权之权力的智能体。未提及智能体所掌握能力的 PRD。最小特权原则在安全领域已经作为基石存在了四十年,而我们正看着一代又一代的智能体平台在艰难地重新发现它 —— 每次发现都伴随着一个权限过大的会议摘要总结器。

References:Let's stay in touch and Follow me for more thoughts and updates