乐于分享
好东西不私藏

AI 为什么会用 ping?一张图看懂 Hermes 的 Tools

AI 为什么会用 ping?一张图看懂 Hermes 的 Tools

我们平时和 AI 聊天,它只能“说”。

但 Agent 不一样。它能读文件、开浏览器、查记忆,还能在终端里运行命令。

问题来了:

Hermes 的工具列表里明明只有 terminal,为什么 AI 却能运行 ping

答案其实很简单:

terminal 是工具,ping 是这个工具收到的一段命令。

就像“电话”是一种工具,而你通过电话说什么,是另一回事。

先认识三个角色

为了把这件事讲清楚,我们只需要认识三个角色。

1. 模型:负责做决定

用户问:

“服务器在线吗?”

模型会判断:要回答这个问题,最好先检查网络。

它看到自己拥有一个名为 terminal 的工具,于是生成一次工具调用:

{  "name": "terminal",  "arguments": {    "command": "ping -c 3 10.x.x.x",    "timeout": 15  }}

这里的 ping 是模型填写的参数,不是另一个工具。

2. Hermes:负责校验和转发

Hermes 收到模型返回的工具调用后,会做几件事:

  • 检查工具名是不是真的存在;
  • 检查参数格式是否正确;
  • 做安全和授权判断;
  • 找到 terminal 对应的执行函数;
  • 把执行结果再交给模型。

Hermes 不需要事先知道世界上所有 Shell 命令。

3. Shell:负责真正执行

terminal 最终会把命令交给 Shell,效果类似:

bash -c 'ping -c 3 10.x.x.x'

Shell 再从系统的 PATH 中找到 ping 程序并运行。

因此,gitcurldockerls 也遵循同样的逻辑:它们不是独立的 Hermes Tools,而是 terminal.command 中的系统命令。

Tool 到底是什么?

可以把 Tool 理解为 AI 能调用的“标准接口”。

一个 Tool 通常包含三部分:

部分
作用
名称
告诉模型这个工具叫什么
描述
告诉模型什么时候应该使用
参数
告诉模型应该填写哪些内容

以 terminal 为例,它的定义大致是:

{  "name": "terminal",  "parameters": {    "command": "string",    "timeout": "integer"  }}

模型看到这份定义,就知道:如果要执行命令,可以调用 terminal,并把命令放进 command

Toolset 又是什么?

Tools 多了以后,不能每个入口都一股脑全部开放。

Hermes 用 Toolset 对工具分组:

file       → 读文件、写文件、搜索文件terminal   → 执行命令、管理进程browser    → 打开网页、点击、输入、滚动memory     → 读取和保存长期记忆skills     → 查看和管理操作知识

Toolset 就像“工具箱分类”,Tool 才是里面那把具体的工具。

为什么不同入口看到的 Tools 不一样?

Hermes 可以从很多入口接收消息,例如:

  • CLI;
  • Telegram;
  • Discord;
  • Slack;
  • API Server;
  • Home Assistant。

每个入口都可以配置自己的 Toolsets。

例如,Discord 入口可能需要 Discord 专属工具;CLI 更偏向文件和开发;Home Assistant 则可能需要智能家居能力。

所以,即使它们使用同一个模型,最终收到的工具列表也可能不同。

可以用一个公式概括:

最终 Tools= 当前入口启用的 Toolsets+ MCP 和插件工具− 全局禁用项− 当前环境不可用的工具

为什么“已经启用”的工具仍可能消失?

因为“允许使用”和“现在能用”不是一回事。

例如:

  • 配置允许 Web Search,但没有搜索 API Key;
  • 配置允许浏览器工具,但浏览器服务没有启动;
  • 配置允许图片生成,但没有可用的图片提供商;
  • 配置允许某个 MCP,但 MCP 服务连接失败。

Hermes 会通过 check_fn 做运行时检查。

检查不通过的工具不会发给模型,避免模型调用一个注定失败的接口。

MCP 在这里扮演什么角色?

内置 Tools 来自 Hermes 自己的代码,MCP Tools 则来自外部 MCP Server。

可以把 MCP 理解为“外接工具扩展坞”:

Hermes  ├── 内置 Tools  ├── 插件 Tools  └── MCP Server 提供的 Tools

MCP 工具通常会带服务器前缀,例如:

mcp__remote_coder__run

这样可以避免不同服务器之间发生重名。

Skill 和 Tool 有什么区别?

这也是最容易混淆的地方。

一句话区分:

Skill 告诉模型“应该怎么做”,Tool 让模型“真的可以做”。

例如,一个服务器巡检 Skill 可能规定:

  • 先核对资产清单;
  • 只能进行只读检查;
  • 应使用指定的审计脚本;
  • 修改配置前必须获得批准。

但 Skill 本身不会执行 ping

模型读完 Skill 后,仍然需要调用 terminal,再由 terminal 执行具体命令。

这些 Tools 会不会每次都发给模型?

在常见的 OpenAI-compatible Chat Completions 模式下,请求大致包含:

{  "model": "example-model",  "messages": ["系统提示", "历史消息", "当前问题"],  "tools": ["完整工具定义"]}

因此,通常不只是 messages 会随请求发送,当前 Agent 的完整 Tools Schema 也会放进请求体。

需要注意两点:

  1. Session 导出文件不会被整体上传;用户 ID、聊天 ID、成本统计等本地字段不属于模型请求。
  2. 服务端即使支持 Prompt Cache,网络请求仍可能携带稳定的 System Prompt 和 Tools Schema,只是服务端可以复用部分计算。

一条完整链路

现在把整个过程连起来:

用户从某个入口发消息  ↓Hermes 根据入口选择 Toolsets  ↓加载内置、插件和 MCP Tools  ↓过滤当前环境不可用的工具  ↓把最终 Tools 发给模型  ↓模型选择 terminal,并生成 ping 参数  ↓Hermes 调用 terminal handler  ↓Shell 执行 ping  ↓执行结果返回模型  ↓模型组织最终回答

最后记住这五句话

如果你只想记住重点,记住下面五句就够了:

  1. Tool 是模型可以调用的结构化接口。
  2. Toolset 是一组 Tools 的选择和配置单位。
  3. 不同入口可以获得不同的 Toolsets。
  4. Skill 提供操作知识,Tool 提供执行能力。
  5. terminal 是 Tool,ping 只是模型写进参数的系统命令。

理解这几个边界之后,再看 Agent 的工具调用记录,就不会把 Tool、Skill 和 Shell命令混在一起了。