游乐游手机版
首页/AI教程/文章详情

Hermes Agent Skill机制深度解析

时间:2026-07-16 21:21
HermesAgent的Skill机制是一套知识注入流程,包含发现索引、触发加载、预处理、Prompt注入和LLM响应五个阶段。以SKILL md文件为核心,通过YAMLfrontmatter声明元数据,支持条件激活、平台过滤、安全检测等特性。触发方式包括LLM自主调用、Slash命令和CLI预加载,预处理涉及模板变量替换与Shell展开。
# Hermes Agent 的 Skill 机制,到底是怎么一回事? 就像我们之前聊过的,Hermes Agent 的 Skill 系统本质上是一套完整的知识注入机制,它不是简单的文件读取,而是经历了一个从“找到它”到“用上它”的完整流程。具体来说,这个流程包含**五个阶段:发现索引、触发加载、预处理、Prompt注入,最后才是LLM响应**。核心的载体是 `SKILL.md` 文件,通过YAML frontmatter声明元数据,支持条件激活、平台过滤、安全检测等一系列特性。 深入理解Hermes Agent Skill 机制 ## 1. Skill 目录结构 先来看看它的目录组织方式,其实挺直观的: ``` ~/.hermes/skills/ ├── category-a/ │ └── skill-name/ │ ├── SKILL.md # 必需:主文件 │ ├── references/ # 可选:参考资料 │ ├── templates/ # 可选:模板文件 │ ├── scripts/ # 可选:脚本文件 │ └── assets/ # 可选:资源文件 ├── category-b/ │ └── another-skill/ │ └── SKILL.md └── ... ``` **几个关键点值得注意**: - 支持任意深度的子目录嵌套,系统通过 `os.walk` 递归扫描,所以分类层级方面完全不用太担心 - 子目录只用于分类组织,不影响索引结果 - 有四个目录会被自动排除:`.git`、`.github`、`.hub`、`.archive` ## 2. 完整生命周期(5阶段) ### Phase 1: 发现与索引(启动时) 当Agent启动时,它会按以下路径扫描所有Skill: ``` get_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. ``` ### Phase 2: 触发(3种方式) 这是整个机制中最关键的一环——Skill到底是怎么被激活的?有三种途径: #### 方式 A: LLM 自主调用(主要路径) 这是最核心的触发方式,也是设计上期望的主要路径: ``` System Prompt 引导: "Before replying, scan the skills below... MUST load with skill_view(name)" ↓ LLM 判断任务与 skill 相关 ↓ tool_call: skill_view(name="skill-name") ``` 触发条件其实挺宽松的: - Skill 名称或描述与用户请求匹配 - Skill 的 `description` 字段包含关键词 - LLM 自主判断“部分相关”就应加载——这意味着描述写得好的Skill更容易被命中 #### 方式 B: Slash 命令(用户显式调用) 当用户想直接指定某个Skill时,可以这样操作: ``` 用户输入: /skill-name some instruction ↓ scan_skill_commands() # 扫描所有 SKILL.md 生成命令映射 ↓ 匹配 /skill-name ↓ build_skill_invocation_message() # 构建触发消息 ``` **Skill 命令命名规则**:名称会经过规范化处理——小写,空格/下划线转连字符,去除非法字符。例如 `My Skill` 就变成了 `/my-skill`。 #### 方式 C: CLI 预加载(Session 启动时) 还有一种方式是在启动时直接指定: ``` hermes --skills skill-name ``` ``` build_preloaded_skills_prompt() ↓ 注入到 session prompt 开头 ``` ### Phase 3: 加载与预处理 当Skill被触发后,就该进入实质性的加载阶段了。`skill_view()` 的执行流程相当严谨: ``` 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": "a vailable" } ``` 预处理机制有两个亮点值得关注: **模板变量替换**: ``` ${HERMES_SKILL_DIR} → skill 的绝对路径 ${HERMES_SESSION_ID} → 当前会话 ID ``` **Inline Shell 展开**(需配置启用): ``` !`ls -la ${HERMES_SKILL_DIR}/scripts/` → 替换为命令执行结果 ``` ### Phase 4: Prompt 注入 加载完成后,Skill内容需要以合适的方式注入到对话上下文中。根据触发方式不同,注入方式也有所区别: #### 方式 A: LLM tool call 返回 ``` tool 返回 JSON ↓ 作为 tool_result 注入 conversation history ↓ LLM 在下一轮看到完整 skill 内容 ``` #### 方式 B: Slash 命令消息构建 ``` _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 响应 ``` #### 方式 C: CLI 预加载 ``` [IMPORTANT: The user launched this CLI session with "xxx" ...] ↓ 追加到 system prompt 的 prompt_parts ``` ### Phase 5: LLM 响应与执行 最后,LLM开始基于Skill内容进行响应: ``` LLM 接收包含 skill 内容的 message ├── 遵循 skill 中的 instructions ├── 可通过 skill_view(name, file_path) 加载 supporting files ├── 执行 skill 中的 scripts(通过 skill_dir 绝对路径) ├── 使用 skill 声明的配置变量 └── 任务完成后可选:skill_manage(action='patch') 更新 skill ``` ## 3. Skill 元数据(YAML Frontmatter) 每个 `SKILL.md` 文件的开头,都会有一段YAML frontmatter来声明元数据。这里面的字段配置直接决定了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 --- ``` ## 4. 条件激活规则 这个机制是Skill灵活性的核心所在。通过几个字段,可以精确控制Skill在什么条件下出现,什么条件下隐藏: | 字段 | 含义 | 示例 | |------|------|------| | 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 不可用 | ## 5. 安全机制 安全这根弦得时刻绷紧,尤其是在处理外部注入的内容时。 ### Prompt Injection 检测 系统会扫描以下常见攻击模式: - `ignore previous instructions` - `disregard your instructions` - `you are now` - `system prompt:` - `` **处理方式**上,系统区分了两种场景: - Context 文件注入:**拒绝加载**并警告 - Skill 内容注入:**记录警告但仍加载**(因为Skill被视为可信来源) ### 路径安全 - 防止路径穿越攻击(`..`) - 验证解析路径仍在 skill 目录内 - 禁止访问 skill 目录外的文件 ## 6. 关键文件职责 整个Skill机制的实现分散在多个文件中,各司其职: | 文件 | 职责 | |------|------| | 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 | ## 7. 优化与最佳实践 ### Skill 设计原则 1. **描述清晰**:`description` 字段是LLM判断是否加载的主要依据,应包含关键词 2. **触发词明确**:在 description 中列出典型触发场景 3. **条件激活合理使用**:避免与内置 tool 冲突,使用 `fallback_for_*` 声明备选关系 4. **支持文件组织**:将参考资料、模板、脚本放在对应子目录中 5. **配置变量声明**:需要用户配置的参数应在 frontmatter 中声明 ### 性能优化 1. **两级缓存**:避免重复扫描文件系统 2. **条件过滤前置**:在索引阶段就过滤掉不兼容的 skill 3. **延迟加载**:只加载与当前任务相关的 skill 内容 说到底,这套Skill机制的设计思路很清晰:通过明确定义的生命周期和灵活的触发方式,让知识注入既有章可循,又不会显得死板。理解了这个流程,再去开发或优化自己的Skill,心里就有底了。
来源:https://www.jb51.net/ai/1034898.html
上一篇Claude Code Web Fetch 问题解决指南详细步骤与常见错误处理方法 下一篇阶跃造手机48小时获7张备案窗口期终结
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
你的下一代Claw不止OpenClaw一种选择
AI教程 · 2026-07-16

你的下一代Claw不止OpenClaw一种选择

某品牌推动人工智能全民普及,但其实现机制实则无聊,核心是厂商售卖代币的营销。为此打造企业级人工智能代理平台,提供管理后台、统计分析等能力,让人工智能真正落地企业场景,实现可运维与可量化。

淘宝商品详情API实时更新SKU价格与库存的方法
AI教程 · 2026-07-16

淘宝商品详情API实时更新SKU价格与库存的方法

淘宝商品详情API的实时性优化需从分层缓存隔离、分级异步轮询、精准字段筛选、SKU增量更新、超时重试与兜底、大促专项优化及消息回调机制入手,平衡接口稳定性、成本与时效性,实现企业级秒级数据监控。

年AI绘画新手超详细入门教程
AI教程 · 2026-07-16

年AI绘画新手超详细入门教程

在使用AI绘画工具时,许多人都常常困惑于一个问题:AI绘画关键词到底该如何撰写,才能生成真正高质量、富有质感的画面?答案其实并不复杂,关键就在于“合适”二字。 选对关键词,是生成好作品的第一步。如果关键词过于简单,比如只写“猫”“风景”,生成的画面往往平淡无奇,缺乏惊喜;但如果一头扎进复杂词汇堆里,

Agentic AI重启入口之争新趋势
AI教程 · 2026-07-16

Agentic AI重启入口之争新趋势

大模型突破推动AgenticAI进入超级创新周期,AI助手成为新一代用户入口。大模型创业企业、互联网平台、硬件厂商等各方围绕模型能力、Agent生态、流量和软硬件整合展开激烈竞争,争夺未来话语权。

OpenAI神秘草莓模型两周内上线,数学推理暴涨月费200美元已有用户付费
AI教程 · 2026-07-16

OpenAI神秘草莓模型两周内上线,数学推理暴涨月费200美元已有用户付费

OpenAI计划两周内发布推理模型“草莓”,需思考十至二十秒后再响应,虽然更智能但更慢也更贵。其月费或为200美元,擅长数学、编码及复杂任务。该模型基于自我博弈强化学习范式,旨在为下一代模型“猎户座”生成高质量数据。