§16近90个工具与按需暴露
Ninety-Odd Tools and Exposure on Demand
README写着「40+ tools」,6月我数源码数出64个,10月同样的数法数出88个。这个差不只是计数口径,它背后藏着一个更有意思的设计:工具越多,越不能一股脑全塞给模型。
先把数字数清楚
旧书里写Hermes有「40+工具」,那是官方README的对外口径。6月写上一版时我去翻源码,数了一遍registry的注册项,真正能被模型调用的工具是64个,把spotify那套走插件路径注册的也算上大概71个。10月这一版我换了个更稳的数法(建一个临时环境、导入工具模块之后读registry),先在v0.16.0上复现出71,再拿同样的数法去数v0.22.2,是88个。官方的工具参考文档写的是「约100个」,因为它把看板、元宝、桌面GUI这些只在特定场景出现的工具也算进去了。
数字对不上,是因为有两个概念被混在一起了,得先掰开。
| 推荐 | 不推荐 |
|---|---|
| 工具(tool):模型实际能call的那个函数。比如 | 工具集(toolset):把工具分组打包的别名。比如 |
| web_search、terminal、image_generate。v0.22.2 | web={web_search, web_extract}。这种约50个。 |
| 里有88个。 |
为什么要分这两层?因为「给模型暴露什么」和「按功能怎么组织」是两件事。工具是原子,工具集是套餐。
后面你会看到,这套分层正是「按需暴露」的地基。
五大类,工具的全景
把这些工具按职能归一下类,能看清Hermes到底能干什么。我读了toolsets.py和各个工具文件,归成五大类。
| 类别 | 代表工具 | 能力 |
|---|---|---|
| 执行 | terminal、execute_code、read_file、 | 跑命令、读写文件、改代码。computer_use在后台控制桌 |
| 类 | patch、computer_use | 面,不抢你的鼠标 |
| 信息 | web_search、web_extract、browser_* | 搜网页、抓内容、开浏览器。browser是大头,光子工具就12 |
| 类 | (12个)、x_search | 个 |
| 媒体 | image_generate、video_generate、 | 生图、生视频、看视频、语音合成。每个只暴露一个统一入口 |
| 类 | video_analyze、text_to_speech | |
| 记忆 | memory、skills_list、todo_list、 | 跨会话记忆、管Skill、待办、定时任务、翻历史 |
| 规划 | cronjob_manage、session_search | |
| 类 | ||
| 协调 | delegate_task、kanban_*(15个) | 派子agent、看板协调一群agent(多模型混合 |
| 类 | mixture_of_agents已经不是工具了,改成了一个可选的虚拟 | |
| 模型moa) |
这里有个细节值得拎出来。有几个旧书的说法已经过时了。旧书写协调类「最多3个并发子Agent、最多3层」,现在默认并发是10个(delegation.max_concurrent_children ),嵌套深度默认1层也就是扁平派活,要多层得自己调max_spawn_depth ,每个子Agent单独有250圈的上限。子Agent还能放到后台跑,跑的过程中你可以中途改它的方向或者叫停。旧书还列过一类「rl工具」,现在RL环境走单独的目录,根本不进agent的工具面。
写书引用旧版本的限制数,很容易翻车,这是我读源码时撞到的坑。
关键不在多,在「该出现时才出现」
64个工具,如果每次对话都把64个工具的定义全塞进system prompt,会发生什么?
context被工具定义撑爆。模型还没开始干活,光读工具说明书就占掉一大块上下文。更糟的是,工具一多,模型挑错工具的概率也跟着涨。
Hermes的解法是两层门控。第一层是toolset分组,第二层叫progressive tool disclosure。先说第一层。
很多工具不是无条件出现的,它们带一个check_fn 门控函数,只在满足运行时条件时才进模型可见的工具列表。我列几个实际的例子,你就懂这个设计有多克制。
check_fn门控的几个实例:computer_use只在装了桌面驱动时才出现;kanban那十几个看板工具只在被看板
调度器派生出来时才出现(§07里worker调用的kanban_show、kanban_complete就是它们);x_search要
有xAI的登录或key才出现。没装、没配、没触发,模型就压根看不见它们。6月那版我举过的send_message(只在网关跑起来时出现)后来被整个删掉了,Home Assistant和Spotify那几套也搬出了核心,改成从插件目录安装。
还有一处我觉得设计得很聪明的安全收窄。webhook场景下,比如有人提了个PR、发了条评论触发Hermes,内容可能来自不可信的第三方。这种场景Hermes只放出四个最安全的工具(搜索、抽取、看图、澄清),本地执行权限一个都不给。因为webhook里的文字可能藏着prompt injection,万一模型被骗去跑terminal就完了。这是把威胁模型直接写进了工具暴露规则里。
Progressive tool disclosure:跟OpenClaw学的一课
第二层门控是v0.16.0加的,叫progressive tool disclosure,工具按需暴露,到v0.22它从「可选」变成了常态。
开启之后,MCP工具和非核心的插件工具不再直接列进模型能看到的工具数组,而是被三个桥接工具替代:
tool_search、tool_describe、tool_call。模型需要时自己搜一下有什么工具、查一下怎么用、再调用。像图书馆从「把所有书摊在你面前」改成「给你一个检索台」。
模型想做某事
tool_search 搜可用工具tool_describe 查用法tool_call 调用
这里有两条让我觉得设计很有分寸的规则。一是核心工具永不延迟,源码原话是「Always load means always load. No exceptions.」最常用的那批工具该全程可见就全程可见,不绕弯子。二是这个机制什么时候启用。6月时有个阈值,可延迟的工具占context不到10%就空转;现在的默认值tool_search.enabled: auto实际上等于常开,只要有一个工具被设成延迟加载,它就启用,旁边那个5%指的是工具目录清单本身最多占多少预算。v0.22还把大约19个冷门的内置工具默认改成了延迟加载,包括computer_use、session_search、image_generate、定时任务、桌面GUI那一批,官方给的数字是桌面端发给模型的工具说明从13,367个token降到6,883个。
这件事我在§07的账单里亲眼看到了:hermes insights的工具排行里有tool_search、tool_describe、tool_call各一次。那是我说「每个工作日早上9点提醒我」的时候,定时任务工具默认没在它眼前,它先搜到、查了用法、再调用。现在tool_call一次还能批量调最多10个工具。
最有意思的是源码注释里写的一句话:这个工具目录是无状态的、每轮重建。为什么不缓存?因为他们明确吸取了OpenClaw的教训。
注意
OpenClaw曾经踩过一个坑:把工具目录做了session级缓存,结果缓存和实时的工具注册表漂移了,导致工具静默消失。用户以为某个工具还在,模型却看不见了,还不报错。Hermes的注释里直接点名引用了这个回归bug,宁可每轮重建也不缓存,就为了避开同一个坑。
我特别喜欢这种「我看着别人摔倒,所以我绕开这块石头」的工程注释。它不是抽象的最佳实践,是一手的、带血的经验。这套progressive disclosure本质上是Anthropic「工具按需加载」思路的开源实现,解决的就是MCP接多了之后上下文被工具定义撑爆的真实问题。
工具交付全面插件化:一文件一后端
聊完「怎么暴露工具」,再看「工具本身怎么交付」。6月那一版Hermes最大的架构变化,是把外部能力全做成了插件。
web、browser、image_gen、video_gen这四类,全部拆成了plugins目录下的一文件一后端。想加一个新的生图服务商?加个文件夹就行,不用去fork主工具。这就是源码里说的「四向架构对齐」,四类外部能力共用同一套插件骨架。
生图这块最能说明问题。你只看到image_generate 一个工具,但背后挂着一排provider目录,6月是5个,v0.22.2是8个:deepinfra、fal、krea、meta-ai、openai、openai-codex、openrouter、xai。具体走哪个,由配置和可用性自动路由。生视频同理,video_generate 一个入口,背后现在是deepinfra、fal、openrouter、xai四个后端,给纯文本就文生视频,给文本加图就图生视频;v0.17起image_generate也能图生图了。联网搜索那一类插件更多,Brave、DuckDuckGo、Exa、Firecrawl、Perplexity、SearXNG、Tavily、xAI等十来个后端。
6月我数的时候,光FAL这一条路由进来的生图模型就有12个(这个数是动态的,Portal文档现在写的是9个),阵容挺豪华:FLUX 2 Pro、Nano Banana Pro(也就是Gemini 3 Pro Image)、GPT Image 2、Z-Image、Qwen Image都在里面。源码还很细心地把尺寸规格分了三族,每个模型只收它支持的参数键,拒绝的键根本传不进去。
Krea 2和xAI:插件化带来的两个新成员
插件化最直接的好处,是新能力进得快。两个第一版完全没有的成员,都是靠这套骨架接进来的。
一个是Krea 2。它有独立的原生插件,也能从FAL那条路用到,两条路都通。Krea的API是异步的:你提交后它返一个任务ID,插件每2秒去轮询一次结果,对外伪装成同步调用。源码里还自带了定价和速度的元数据:Krea 2 Medium大概15到25秒出图,强项是插画、动漫、绘画这类表现性风格。这种把第三方异步API包装成同步工具的活,正是插件骨架该干的脏活。
另一个更夸张,是xAI。它不是一个普通的provider,而是横跨登录、搜索、生图、生视频、语音的一条龙。
| xAI接进来的能力 | 具体是什么 |
|---|---|
| SuperGrok OAuth登录 | 不用API key,订阅直接用 |
| x_search | 搜X上的帖子和线程 |
| Web Search provider | 和Brave、Tavily并列的一个搜索后端 |
| grok-imagine生图 | 挂在image_gen插件里 |
| Grok Imagine生视频 | 文生、图生、参考图引导都支持 |
| Custom Voices TTS | 语音合成加语音克隆 |
我觉得xAI这条线特别值得玩味。它是「一个开源agent怎么把一家闭源大厂的订阅能力吃干抹净」的标本:你订了SuperGrok,Hermes就帮你把这份订阅的搜索、生图、生视频、语音全用上,不用单独配一堆API key。
不过有个工程细节我得替Nous说句公道话,他们没偷懒。x_search的返回值里加了一个degraded 字段:当你加了账号或日期过滤却拿不到任何引用来源时,它会标degraded=true,等于在告诉你「这个答案是模型自己编的,不是从X索引来的」。把「有没有真来源」这件事做进了工具的返回值里,这种诚实挺难得。
这一节想说的
回到开头那个88对40的差。它其实是整节的隐喻:工具的增长是真实的,但增长本身会变成负担。
Hermes的回答是,不要把「能力多」直接等同于「全暴露给模型」。toolset分组、check_fn门控、progressive disclosure、插件化交付,这四件事串起来是一个统一的态度——能力可以无限长,但每一刻暴露给模型的,只是此时此地真正用得上的那一小撮。OpenClaw用工具太多掉准确率的坑,Hermes用这套机制绕开了。
下一节我们看连接外部世界的另一条主干道:MCP。Hermes在MCP上玩出了两个方向,比你想的要绕。