创建技能

技能(Skill)是为 Hermes Agent 添加新功能的首选方式。它们比工具更容易创建,无需修改代理代码,并且可以与他人分享。

应该是技能还是工具?

以下情况应该创建技能

  • 该能力可以通过指令 + Shell 命令 + 现有工具来表达
  • 它包装了一个外部 CLI 或 API,代理可通过 terminalweb_extract 调用
  • 它不需要自定义 Python 集成或在代理中内置 API 密钥管理
  • 示例:arXiv 搜索、Git 工作流、Docker 管理、PDF 处理、通过 CLI 工具收发邮件

以下情况应该创建工具

  • 需要端到端的 API 密钥集成、认证流程或多组件配置
  • 需要每次精确执行的自定义处理逻辑
  • 处理二进制数据、流式传输或实时事件
  • 示例:浏览器自动化、TTS(文本转语音)、视觉分析

技能目录结构

内置技能按类别组织在 skills/ 目录下。官方可选技能使用相同的结构放在 optional-skills/ 中:

skills/
├── research/
│   └── arxiv/
│       ├── SKILL.md              # 必需:主要指令
│       └── scripts/              # 可选:辅助脚本
│           └── search_arxiv.py
├── productivity/
│   └── ocr-and-documents/
│       ├── SKILL.md
│       ├── scripts/
│       └── references/
└── ...

SKILL.md 格式

---
name: my-skill
description: 简要描述(显示在技能搜索结果中)
version: 1.0.0
author: 你的名字
license: MIT
platforms: [macos, linux]          # 可选——限制在特定操作系统平台
                                   #   有效值:macos, linux, windows
                                   #   省略则在所有平台上加载(默认)
metadata:
  hermes:
    tags: [类别, 子类别, 关键词]
    related_skills: [其他技能名称]
    requires_toolsets: [web]            # 可选——仅当这些工具集激活时显示
    requires_tools: [web_search]        # 可选——仅当这些工具可用时显示
    fallback_for_toolsets: [browser]    # 可选——当这些工具集激活时隐藏
    fallback_for_tools: [browser_navigate]  # 可选——当这些工具存在时隐藏
    config:                              # 可选——技能所需的 config.yaml 设置
      - key: my.setting
        description: "此设置控制的内容"
        default: "合理默认值"
        prompt: "设置时的显示提示"
required_environment_variables:          # 可选——技能所需的环境变量
  - name: MY_API_KEY
    prompt: "请输入你的 API 密钥"
    help: "获取地址:https://example.com"
    required_for: "API 访问"
---
 
# 技能标题
 
简要介绍。
 
## 何时使用
触发条件——代理何时应加载此技能?
 
## 快速参考
常用命令或 API 调用表。
 
## 操作步骤
代理执行的逐步说明。
 
## 注意事项
已知的失败模式及处理方法。
 
## 验证
代理如何确认操作成功。

平台特定技能

技能可以使用 platforms 字段限制在特定操作系统上运行:

platforms: [macos]            # 仅 macOS(例如 iMessage、Apple Reminders)
platforms: [macos, linux]     # macOS 和 Linux
platforms: [windows]          # 仅 Windows

设置后,该技能在不兼容的平台上会自动从系统提示、skills_list() 和斜杠命令中隐藏。如果省略或为空,技能在所有平台上加载(向后兼容)。

条件技能激活

技能可以声明对特定工具或工具集的依赖关系,以控制该技能是否在特定会话的系统提示中显示。

metadata:
  hermes:
    requires_toolsets: [web]           # 如果 web 工具集未激活则隐藏
    requires_tools: [web_search]       # 如果 web_search 工具不可用则隐藏
    fallback_for_toolsets: [browser]   # 如果 browser 工具集已激活则隐藏
    fallback_for_tools: [browser_navigate]  # 如果 browser_navigate 可用则隐藏
字段行为
requires_toolsets任一列出的工具集不可用时,技能隐藏
requires_tools任一列出的工具不可用时,技能隐藏
fallback_for_toolsets任一列出的工具集可用时,技能隐藏
fallback_for_tools任一列出的工具可用时,技能隐藏

fallback_for_* 的使用场景: 创建在主工具不可用时作为替代方案的技能。例如,一个 duckduckgo-search 技能设置 fallback_for_tools: [web_search],仅当需要 API 密钥的 web_search 工具未配置时显示。

requires_* 的使用场景: 创建仅在特定工具存在时才有意义的技能。例如,一个网页抓取工作流技能设置 requires_toolsets: [web],当 web 工具被禁用时不会占用提示空间。

环境变量要求

技能可以声明其所需的环境变量。当通过 skill_view 加载技能时,所需的变量会自动注册以传递到沙盒执行环境(terminal、execute_code)中。

required_environment_variables:
  - name: TENOR_API_KEY
    prompt: "Tenor API 密钥"               # 提示用户时显示的文字
    help: "获取密钥:https://tenor.com"     # 帮助文本或 URL
    required_for: "GIF 搜索功能"            # 需要此变量的功能

每个条目支持:

  • name(必需)——环境变量名称
  • prompt(可选)——向用户询问值时的提示文本
  • help(可选)——获取值时的帮助文本或 URL
  • required_for(可选)——描述需要此变量的功能

用户也可以在 config.yaml 中手动配置传递变量:

terminal:
  env_passthrough:
    - MY_CUSTOM_VAR
    - ANOTHER_VAR

参见 skills/apple/ 获取 macOS 专用技能的示例。

加载时的安全设置

当技能需要 API 密钥或令牌时,使用 required_environment_variables。缺失的值不会使技能从发现结果中隐藏。相反,Hermes 会在本地 CLI 中加载该技能时安全地提示用户输入。

required_environment_variables:
  - name: TENOR_API_KEY
    prompt: Tenor API 密钥
    help: 从 https://developers.google.com/tenor 获取密钥
    required_for: 完整功能

用户可以跳过设置并继续加载技能。Hermes 永远不会将原始密钥值暴露给模型。网关和消息通信会话会显示本地设置指南,而不是在带内收集密钥。

:::tip 沙箱透传 加载你的技能时,已设置的 required_environment_variables 会自动透传execute_codeterminal 沙箱——包括 Docker 和 Modal 等远程后端。你的技能脚本可以直接访问 $TENOR_API_KEY(或在 Python 中使用 os.environ["TENOR_API_KEY"]),用户无需额外配置。详情请参见环境变量透传。 :::

旧版 prerequisites.env_vars 仍作为向后兼容的别名受支持。

配置设置(config.yaml)

技能可以声明非密钥设置,存储在 config.yamlskills.config 命名空间下。与环境变量(密钥存储在 .env 中)不同,配置设置用于路径、偏好设置和其他非敏感值。

metadata:
  hermes:
    config:
      - key: myplugin.path
        description: 插件数据目录路径
        default: "~/myplugin-data"
        prompt: 插件数据目录路径
      - key: myplugin.domain
        description: 插件操作的领域
        default: ""
        prompt: 插件领域(例如 AI/ML 研究)

每个条目支持:

  • key(必需)——设置的点分路径(例如 myplugin.path
  • description(必需)——说明此设置控制的内容
  • default(可选)——用户未配置时的默认值
  • prompt(可选)——在 hermes config migrate 期间显示的提示文本;未提供时回退到 description

工作原理:

  1. 存储: 值写入 config.yaml 中的 skills.config.<key>

    skills:
      config:
        myplugin:
          path: ~/my-data
  2. 发现: hermes config migrate 扫描所有已启用的技能,查找未配置的设置并提示用户。设置也会出现在 hermes config show 的”技能设置”部分。

  3. 运行时注入: 当技能加载时,其配置值被解析并追加到技能消息中:

    [技能配置(来自 ~/.hermes/config.yaml):
      myplugin.path = /home/user/my-data
    ]
    

    代理可以直接看到配置值,无需自行读取 config.yaml

  4. 手动设置: 用户也可以直接设置值:

    hermes config set skills.config.myplugin.path ~/my-data

:::tip 何时使用哪种方式 API 密钥、令牌和其他密钥信息使用 required_environment_variables(存储在 ~/.hermes/.env,从不显示给模型)。路径、偏好设置和非敏感配置使用 config(存储在 config.yaml,在 config show 中可见)。 :::

凭据文件要求(OAuth 令牌等)

使用 OAuth 或基于文件的凭据的技能可以声明需要挂载到远程沙箱中的文件。这适用于以文件形式(而非环境变量)存储的凭据——通常是由设置脚本生成的 OAuth 令牌文件。

required_credential_files:
  - path: google_token.json
    description: Google OAuth2 令牌(由设置脚本创建)
  - path: google_client_secret.json
    description: Google OAuth2 客户端凭据

每个条目支持:

  • path(必需)——相对于 ~/.hermes/ 的文件路径
  • description(可选)——说明文件内容及创建方式

加载时,Hermes 会检查这些文件是否存在。缺失的文件会触发 setup_needed。存在的文件会自动:

  • 挂载到 Docker 容器中,作为只读绑定挂载
  • 同步到 Modal 沙箱(创建时 + 每个命令前,以支持会话中的 OAuth)
  • 本地后端上无需特殊处理即可使用

:::tip 何时使用哪种方式 简单的 API 密钥和令牌(存储在 ~/.hermes/.env 中的字符串)使用 required_environment_variables。OAuth 令牌文件、客户端密钥、服务账号 JSON、证书或任何磁盘上的凭据文件使用 required_credential_files。 :::

完整的示例请参见 skills/productivity/google-workspace/SKILL.md

技能编写指南

无外部依赖

优先使用 Python 标准库、curl 和现有的 Hermes 工具(web_extractterminalread_file)。如果需要依赖,请在技能中记录安装步骤。

渐进式信息展示

将最常用的工作流放在前面。边缘情况和高级用法放在末尾。这样可以减少常见任务的令牌消耗。

包含辅助脚本

对于 XML/JSON 解析或复杂逻辑,请在 scripts/ 中包含辅助脚本——不要期望 LLM 每次都内联编写解析器。

以文档形式传递媒体([[as_document]]

如果你的技能生成了高分辨率截图、图表或任何有损预览压缩会损害质量的图像——在响应中的某处(通常是最后一行)放置字面指令 [[as_document]]。网关会剥离该指令,并将该响应中提取的每个媒体路径作为可下载的文件附件传递,而不是内联图像气泡。完整语义请参见技能输出和媒体传递

从 SKILL.md 引用捆绑脚本

当技能加载时,激活消息会暴露技能的绝对目录为 [Skill directory: /abs/path],并且还会在 SKILL.md 正文中的任何位置替换两个模板令牌:

令牌替换为
${HERMES_SKILL_DIR}技能目录的绝对路径
${HERMES_SESSION_ID}当前活动的会话 ID(如果没有会话则保留原样)

因此 SKILL.md 可以直接告诉代理运行捆绑脚本:

要分析输入,请运行:
 
    node ${HERMES_SKILL_DIR}/scripts/analyse.js <input>

代理看到替换后的绝对路径,并调用 terminal 工具执行即可运行的命令——无需路径计算,无需额外的 skill_view 往返。在 config.yaml 中设置 skills.template_vars: false 可全局禁用替换。

内联 Shell 片段(可选加入)

技能还可以在 SKILL.md 正文中嵌入以内联 Shell 片段形式编写的 !`cmd`。启用后,每个片段的 stdout 会在代理读取消息之前内联到消息中,因此技能可以注入动态上下文:

当前日期:!`date -u +%Y-%m-%d`
Git 分支:!`git -C ${HERMES_SKILL_DIR} rev-parse --abbrev-ref HEAD`

此功能默认关闭——SKILL.md 中的任何片段都会在主机上运行且无需审批,因此请仅对你信任的技能来源启用:

# config.yaml
skills:
  inline_shell: true
  inline_shell_timeout: 10   # 每个片段的超时时间(秒)

片段以技能目录作为工作目录运行,输出限制为 4000 个字符。失败(超时、非零退出)显示为简短的 [inline-shell error: ...] 标记,而不会破坏整个技能。

测试

运行技能并验证代理是否正确遵循指令:

hermes chat --toolsets skills -q "使用 X 技能执行 Y 操作"

技能应该放在哪里?

内置技能(在 skills/ 中)随每个 Hermes 安装一同分发。它们应对大多数用户具有广泛实用性

  • 文档处理、网络研究、常见开发工作流、系统管理
  • 被广泛人群经常使用

如果你的技能是官方的且有用,但并非普遍需要(例如付费服务集成、重量级依赖),请将其放在 optional-skills/ 中——它会随仓库一同分发,可通过 hermes skills browse 发现(标记为”官方”),并以内置信任级别安装。

如果你的技能是专业用途、社区贡献或小众需求,更适合放在 Skills Hub 中——上传到注册中心并通过 hermes skills install 分享。

发布技能

发布到 Skills Hub

hermes skills publish skills/my-skill --to github --repo owner/repo

发布到自定义仓库

将你的仓库添加为 tap(源):

hermes skills tap add owner/repo

用户随后可以从你的仓库中搜索和安装技能。

安全扫描

所有从 Hub 安装的技能都会经过安全扫描,检查以下内容:

  • 数据泄露模式
  • 提示注入尝试
  • 破坏性命令
  • Shell 注入

信任级别:

  • builtin(内置)——随 Hermes 一起发布(始终信任)
  • official(官方)——来自仓库的 optional-skills/(内置信任,无第三方警告)
  • trusted(信任)——来自 openai/skills、anthropics/skills、huggingface/skills
  • community(社区)——非危险发现可通过 --force 覆盖;dangerous 判定仍被阻止

Hermes 现在可以通过多种外部发现模型消费第三方技能:

  • 直接 GitHub 标识符(例如 openai/skills/k8s
  • skills.sh 标识符(例如 skills-sh/vercel-labs/json-render/json-render-react
  • /.well-known/skills/index.json 提供的知名端点

如果你希望技能无需特定于 GitHub 的安装程序即可被发现,除了在仓库或市场中发布外,还可以考虑从知名端点提供服务。