Hermes Agent 的 Skill 系统是一个完整的知识注入机制,包含发现索引→触发加载→预处理→Prompt注入→LLM响应五个阶段。Skill 以 SKILL.md 文件形式存储,通过 YAML frontmatter 声明元数据,支持条件激活、平台过滤、安全检测等特性。

~/.hermes/skills/ ├── category-a/ │ └── skill-name/ │ ├── SKILL.md # 必需:主文件 │ ├── references/ # 可选:参考资料 │ ├── templates/ # 可选:模板文件 │ ├── scripts/ # 可选:脚本文件 │ └── assets/ # 可选:资源文件 ├── category-b/ │ └── another-skill/ │ └── SKILL.md └── ...
关键特性:
os.walk 递归扫描).git, .github, .hub, .archiveget_all_skills_dirs()
├── ~/.hermes/skills/ # 本地目录(始终在前)
└── skills.external_dirs # 外部目录(config.yaml配置)
↓
iter_skill_index_files() # 递归扫描所有 SKILL.md
↓
parse_frontmatter() # 解析 YAML 元数据
↓
过滤规则:
├── skill_matches_platform() # 平台兼容性检查
├── get_disabled_skill_names() # 禁用列表过滤
└── _skill_should_show() # 条件激活规则
↓
build_skills_system_prompt() # 生成分类索引 Prompt
两级缓存机制
| 层级 | 类型 | 容量 | Key |
|---|---|---|---|
| L1 | 进程内 LRU 缓存 | 8 entries | (skills_dir, external_dirs, tools, toolsets, platform, disabled) |
| L2 | 磁盘快照 | 持久化 | .skills_prompt_snapshot.json(mtime/size验证) |
生成的 System Prompt 格式
## Skills (mandatory)
Before replying, scan the skills below. If a skill matches or is even partially relevant
to your task, you MUST load it with skill_view(name) and follow its instructions.
category-a:
- skill-name: brief description
- another-skill: another description
Only proceed without loading a skill if genuinely none are relevant to the task.
System Prompt 引导:
"Before replying, scan the skills below... MUST load with skill_view(name)"
↓
LLM 判断任务与 skill 相关
↓
tool_call: skill_view(name="skill-name")
触发条件:
description 字段包含关键词用户输入: /skill-name some instruction
↓
scan_skill_commands() # 扫描所有 SKILL.md 生成命令映射
↓
匹配 /skill-name
↓
build_skill_invocation_message() # 构建触发消息
Skill 命令命名规则:
My Skill → /my-skillhermes --skills skill-name
build_preloaded_skills_prompt()
↓
注入到 session prompt 开头
skill_view(name)
├── 解析 qualified name # plugin:skill → 路由到 plugin 系统
├── 目录搜索(first match wins) # local → external
│ ├── 直接路径: search_dir/name/SKILL.md
│ ├── 分类路径: search_dir/category/name/SKILL.md
│ └── 名称匹配: 遍历所有 SKILL.md 比对目录名
├── 安全检查
│ ├── 路径穿越检测(防止 .. 攻击)
│ └── prompt injection 模式扫描
├── 平台/禁用检查
├── 前置条件检查
│ ├── 环境变量(prerequisites.env)
│ └── 凭证文件(prerequisites.credential_files)
├── preprocess_skill_content()
│ ├── 模板变量替换: ${HERMES_SKILL_DIR} → 绝对路径
│ └── inline shell 展开: !`cmd` → 执行结果
├── 收集 linked_files
│ ├── references/*.md
│ ├── templates/*.yaml
│ ├── scripts/*.py
│ └── assets/*
└── 返回 JSON:
{
"success": true,
"name": "skill-name",
"content": "",
"linked_files": {"references": [...], "templates": [...]},
"skill_dir": "/path/to/skill",
"setup_needed": false,
"readiness_status": "available"
}
模板变量替换:
${HERMES_SKILL_DIR} → skill 的绝对路径
${HERMES_SESSION_ID} → 当前会话 ID
Inline Shell 展开(需配置启用):
!`ls -la ${HERMES_SKILL_DIR}/scripts/`
→ 替换为命令执行结果
tool 返回 JSON
↓
作为 tool_result 注入 conversation history
↓
LLM 在下一轮看到完整 skill 内容
_build_skill_message()
├── [IMPORTANT: The user has invoked the "xxx" skill...]
├──
├── [Skill directory: /path/to/skill]
├── [Skill config: key = value] # 配置变量注入
├── [Skill setup note: ...] # 安装提示
├── [This skill has supporting files:] # 支持文件列表
│ ├── references/api.md → /path/to/references/api.md
│ └── scripts/run.py → /path/to/scripts/run.py
└── The user has provided the following instruction: ...
↓
作为 user message 注入 → LLM 响应
[IMPORTANT: The user launched this CLI session with "xxx" ...]
↓
追加到 system prompt 的 prompt_parts
LLM 接收包含 skill 内容的 message ├── 遵循 skill 中的 instructions ├── 可通过 skill_view(name, file_path) 加载 supporting files ├── 执行 skill 中的 scripts(通过 skill_dir 绝对路径) ├── 使用 skill 声明的配置变量 └── 任务完成后可选:skill_manage(action='patch') 更新 skill
---
name: skill-name
description: "简短描述(≤1024字符)"
version: 1.0.0
author: Author Name
license: MIT
platforms: [macos, linux] # 可选:平台限制
metadata:
hermes:
tags: [tag1, tag2]
related_skills: [skill-a, skill-b]
fallback_for_toolsets: [web] # 当 web toolset 可用时隐藏
fallback_for_tools: [web_fetch] # 当 web_fetch tool 可用时隐藏
requires_toolsets: [browser] # 当 browser toolset 不可用时隐藏
requires_tools: [browser_click] # 当 browser_click tool 不可用时隐藏
config: # 配置变量声明
- key: api_endpoint
description: API endpoint URL
default: "https://api.example.com"
prompt: Enter API endpoint
prerequisites:
env:
- name: API_KEY
description: API key for authentication
credential_files:
- path: ~/.config/skill/credentials.json
description: Credentials file
---
| 字段 | 含义 | 示例 |
|---|---|---|
| fallback_for_toolsets | 当指定 toolset 可用时隐藏此 skill | 有 web toolset 时不需要 web-fallback skill |
| fallback_for_tools | 当指定 tool 可用时隐藏此 skill | 有 web_fetch tool 时不需要备用方案 |
| requires_toolsets | 当指定 toolset 不可用时隐藏 | 没有 browser toolset 时浏览器 skill 不可用 |
| requires_tools | 当指定 tool 不可用时隐藏 | 没有 git tool 时 git 相关 skill 不可用 |
检测模式:
ignore previous instructionsdisregard your instructionsyou are nowsystem prompt:处理方式:
..)| 文件 | 职责 |
|---|---|
| hermes_constants.py | get_skills_dir() → ~/.hermes/skills/ 路径解析 |
| agent/skill_utils.py | 核心工具:frontmatter 解析、平台匹配、禁用列表、外部目录、条件提取、文件迭代 |
| agent/prompt_builder.py | build_skills_system_prompt() 生成分类索引,两级缓存,_skill_should_show() 条件过滤 |
| agent/skill_commands.py | Slash 命令扫描、消息构建、CLI 预加载 |
| agent/skill_preprocessing.py | 模板变量替换、inline shell 展开 |
| tools/skills_tool.py | Tool 注册(skills_list, skill_view)、skill 加载、安全检查、linked_files 发现 |
| model_tools.py | Tool 注册触发、toolset 过滤 |
| tools/registry.py | Tool 注册机制,registry.register() 统一注册 schema + handler |
| run_agent.py | Agent 循环中调用 build_skills_system_prompt(),注入 system prompt |
description 字段是 LLM 判断是否加载的主要依据,应包含关键词fallback_for_* 声明备选关系