news 2026/6/6 12:37:19

从Hermes cli的源代码中学习skill

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从Hermes cli的源代码中学习skill

skill定义

结合anthropic,microsoft的前沿定义,可以将Skill总结如下:

Agent Skill 是一种可复用、可发现、可组合的能力单元,它将领域知识、执行流程(Workflow)、工具调用策略和资源封装在一起,使 Agent 能够在特定任务场景下稳定地复现专家级行为。

写成公式可以表示为

其中Skill正在成为Agent stack中独立于tool和memory的第4层抽象

其中的resource包含的类别很多,可以是独立的python脚本,专家知识,配置及依赖环境,比如第三方api或者mcp服务配置

Skill内部处理逻辑

从具体的Hermes agent的源码看skill部分的具体逻辑

Skill文件夹的结构

在Hermes的路径/.hermes/skills中可以找到hermes的skill包

常见skill文件夹中结构如下

~/.hermes/skills/ └── <category>/ └── <skill-name>/ ├── SKILL.md ← 必须,主文件 ├── references/ ← 可选,按需加载的深度文档 ├── templates/ ← 可选,模板文件(LaTeX、YAML 等) ├── scripts/ ← 可选,辅助脚本 └── assets/ ← 可选,图片等资源

这个skill的文件夹设计和一般的文件夹设计不同,其中包含的reference文件夹是一般skill不具备的,框架会自动发现references/templates/assets/scripts/四个目录,并在skill_view()返回值的linked_files字段中列出,供 LLM 按需调用。

Skill文件结构

以YAML Frontmatter作为文件开头的,作为描述skill的元数据,被两个---包围,作为LLM在系统提示词中看到的skill元描述内容,复合渐进式披露的原则

通常内容如下:

正文结构

顺序章节作用
1# 标题skill 名称
2## When to Use触发条件,最关键
3## Overview / Key Concepts核心概念速查
4## Steps / Workflow具体操作步骤
5## Examples可运行的代码示例
6## Common Pitfalls / Red Flags反面教材
7## Checklist / Verification收尾核查清单
8## References指向 references/ 子文件

示例

以市场预测的Polymarket Skill为例子,他的文件夹结构如下

skill/ ├── SKILL.md ← 2.9KB:概念、典型流程、3个API、注意事项 ├── references/ │ └── api-endpoints.md ← API 细节(按需加载) └── scripts/ └── polymarket.py

Polymarket 是一个预测市场平台,用户可以用真实金钱对未来事件的结果下注,比如"特朗普会赢得2028年大选吗?"、"比特币年底会超过10万美元吗?"。市场价格本身就代表概率——某个结果的价格是 0.65,就意味着市场认为这件事发生的概率是 65%。

其中SKILL.md内容为背景知识和操作规范

api-endpoints.md保存实际api的请求使用方式,是对SKILL.md中的补充

scripts/polymarket.py是一个可以直接运行的命令行工具,零依赖,全程用 Python 标准库。LLM可以直接进行调用

python3 polymarket.py search "bitcoin" # 搜索比特币相关市场 python3 polymarket.py trending # 看今天交易量最大的事件 python3 polymarket.py history 0xabc... # 看某个市场的价格历史 python3 polymarket.py book TOKEN_ID # 看 orderbook 深度

Hermes agent中代码逻辑

1.提取skill元数据

/.hermes/hermes-agent/agent/skill_utils.py

# skill_utils.py L532-544 def iter_skill_index_files(skills_dir: Path, filename: str): """Walk skills_dir yielding sorted paths matching *filename*.""" matches = [] for root, dirs, files in os.walk(skills_dir, followlinks=True): # 剔除 .git / venv / node_modules / __pycache__ 等 dirs[:] = [d for d in dirs if d not in EXCLUDED_SKILL_DIRS] if filename in files: matches.append(Path(root) / filename) # 按相对路径字典序排列,保证结果稳定 for path in sorted(matches, key=lambda p: str(p.relative_to(skills_dir))): yield path

提取每个skill的元数据,并在60字符处截断

# prompt_builder.py L990-1006 def _parse_skill_file(skill_file: Path) -> tuple[bool, dict, str]: raw = skill_file.read_text(encoding="utf-8") frontmatter, _ = parse_frontmatter(raw) # ← 解析 YAML frontmatter if not skill_matches_platform(frontmatter): return False, frontmatter, "" # ← 平台过滤(macos/linux/windows) return True, frontmatter, extract_skill_description(frontmatter) # skill_utils.py L518-526 def extract_skill_description(frontmatter: Dict[str, Any]) -> str: raw_desc = frontmatter.get("description", "") desc = str(raw_desc).strip().strip("'\"") if len(desc) > 60: return desc[:57] + "..." # ← 这就是系统提示词里看到的内容 return desc

2.检查两级缓存

/.hermes/hermes-agent/agent/prompt_builder.py

第一层(进程内 LRU)
_SKILLS_PROMPT_CACHE: OrderedDict 最多 8 个 entry
cache_key = (skills_dir, external_dirs, tools, toolsets, platform, disabled_skills)

第二层(磁盘 snapshot)
~/.hermes/.skills_prompt_snapshot.json
含 manifest(每个 SKILL.md 的 mtime + size),用于校验缓存是否过期

校验snapshot逻辑,如果命中则直接复用,而非重新扫描skill

# prompt_builder.py L919-934 def _load_skills_snapshot(skills_dir: Path) -> Optional[dict]: snapshot = json.loads(snapshot_path.read_text(encoding="utf-8")) # 版本号不匹配(代码升级后)→ 缓存失效 if snapshot.get("version") != _SKILLS_SNAPSHOT_VERSION: return None # manifest 不匹配(有 SKILL.md 文件被修改)→ 缓存失效,重新扫描 if snapshot.get("manifest") != _build_skills_manifest(skills_dir): return None return snapshot # 命中:直接用预解析的 metadata,跳过全量扫描

snapshot内容

3.组装系统提示词

/.hermes/hermes-agent/agent/system_prompt.py

# system_prompt.py L179-195 has_skills_tools = any( name in agent.valid_tool_names for name in ['skills_list', 'skill_view', 'skill_manage'] ) if has_skills_tools: skills_prompt = _r.build_skills_system_prompt( available_tools=agent.valid_tool_names, available_toolsets=avail_toolsets, ) if skills_prompt: stable_parts.append(skills_prompt) # 加入系统提示词的 stable 层

stable层属于系统提示词的一部分,并且系统提示词不参与上下文压缩,以保持kv缓存的命中率,

系统提示词被分成三层:

stable = 身份 + 工具指引 + skills 索引 ← 本会话不变,prefix cache 保持有效

context = AGENTS.md 等项目上下文 ← 按 cwd 变化

volatile = 记忆 + 时间戳 ← 每次对话都可能变

skills 索引放在stable层,意味着一旦 LLM API 缓存了这个 prefix,后续每轮对话不用重新计算这些 token,显著降低成本和延迟。这也是为什么 description 只截断到 60 字符而不是完整加载所有 SKILL.md 内容——索引要尽量短,以便 prefix cache 命中率更高。

最终注入格式

# prompt_builder.py L1235-1262 result = ( "## Skills (mandatory)\n" "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. ...\n" "\n" "<available_skills>\n" " research:\n" " - polymarket: Query Polymarket: markets, prices, orderbooks...\n" " - research-paper-writing: End-to-end academic paper writing ...\n" " software-development:\n" " - spike: Run a time-boxed experiment to validate a technolog...\n" " ...\n" "</available_skills>\n" "\n" "Only proceed without loading a skill if genuinely none are relevant." )

4.LLM决策调用

如果LLM在这个用户输入的语句中满足某个skill的触发条件,LLM返回一个tool_call

{ "tool": "skill_view", "arguments": { "name": "polymarket" } }

agent后端接受到tool_call指令,解析并执行工具

# tool_executor.py L542 / L110 def execute_tool_calls_sequential(agent, assistant_message, messages, ...): for tool_call in assistant_message.tool_calls: function_name = tool_call.function.name # = "skill_view" function_args = json.loads(tool_call.function.arguments) # 安全门:guardrail 检查、plugin block 检查 guardrail_decision = agent._tool_guardrails.before_call(function_name, function_args) if not guardrail_decision.allows_execution: ... # 拦截,不执行 # 最终分发执行 result = agent._invoke_tool(function_name, function_args, task_id, ...) messages.append(make_tool_result_message(function_name, result, tool_call.id))

skill_view通过注册表连接到真实的工具函数

# skills_tool.py L1517-1524 registry.register( name="skill_view", toolset="skills", schema=SKILL_VIEW_SCHEMA, handler=_skill_view_with_bump, # ← 真正执行的函数 check_fn=check_skills_requirements, emoji="📚", )

LLM收到返回示例

{ "success": true, "name": "polymarket", "content": "---\nname: polymarket\n...(SKILL.md 全文 2.9KB)...", "linked_files": { "references": ["references/api-endpoints.md"], "scripts": ["scripts/polymarket.py"] }, "usage_hint": "To view linked files, call skill_view(name, file_path=...)" }

5.阅读SKIll

LLM 读完 SKILL.md 后,如果需要实际查询数据,会调用terminal工具直接运行脚本:

# LLM 的 tool_call: { "tool": "terminal", "arguments": { "command": "python3 ~/.hermes/skills/research/polymarket/scripts/polymarket.py search 'bitcoin'" } }

如果需要查看api细节

# LLM 的 tool_call: { "tool": "skill_view", "arguments": { "name": "polymarket", "file_path": "references/api-endpoints.md" // ← file_path 参数 } }

LLM获取足够信息后则会按照SKILL内容做下一步操作。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/6 12:37:12

QMC音频加密破解:深度解析种子矩阵算法与高性能解密架构设计

QMC音频加密破解&#xff1a;深度解析种子矩阵算法与高性能解密架构设计 【免费下载链接】qmc-decoder Fastest & best convert qmc 2 mp3 | flac tools 项目地址: https://gitcode.com/gh_mirrors/qm/qmc-decoder 如何通过逆向工程实现QQ音乐QMC格式的高效解密&…

作者头像 李华
网站建设 2026/6/6 12:37:09

餐饮评价太多看不过来,怎样快速知道差评主要集中在哪方面?2026 AI Agent深度解析与实战方案

在2026年的餐饮市场&#xff0c;数字化竞争已从“流量争夺”转向“存量治理”。 面对美团、大众点评及各类外卖平台每日产生的海量非结构化评价数据&#xff0c; 传统的“店长抽查”或“关键词搜索”模式已彻底失灵。 餐饮企业平均利润率在2026年依然维持在3%至5%的窄区间&…

作者头像 李华
网站建设 2026/6/6 12:37:05

5分钟快速上手:LabelLLM开源数据标注平台完全指南

5分钟快速上手&#xff1a;LabelLLM开源数据标注平台完全指南 【免费下载链接】LabelLLM The Open-Source Data Annotation Platform 项目地址: https://gitcode.com/gh_mirrors/la/LabelLLM 想要为AI模型准备高质量训练数据&#xff1f;LabelLLM开源数据标注平台是你的…

作者头像 李华
网站建设 2026/6/6 12:36:02

康佳55寸电视LED背光灯条更换全流程与风险规避指南

1. 项目概述&#xff1a;一次高风险、高回报的康佳55寸电视灯条更换实录家里的康佳LED55K35U电视用了几年&#xff0c;最近屏幕开始出现暗角&#xff0c;开机时偶尔闪过一道横纹&#xff0c;看暗场电影时尤其明显。作为一名常年和电路板、元器件打交道的硬件工程师&#xff0c;…

作者头像 李华
网站建设 2026/6/6 12:35:25

8D报告怎么写

回复8D报告时&#xff0c;需遵循8D方法论的框架&#xff0c;同时结合客户需求和实际整改情况&#xff0c;确保回复内容清晰、准确、有说服力。以下是回复8D报告的关键要点和步骤&#xff1a; 1.D0&#xff1a;紧急响应措施若问题紧急&#xff0c;需在24小时内回复客户&#x…

作者头像 李华