当前位置: 首页 > news >正文

AIGC标识 Hermes Skill Runtime 架构拆解:三层加载如何压住 Agent 上下文成本

文窗口太贵,技能越多,越不能一次性把所有细节暴露给模型。Hermes 选择了一条更朴素的路:​运行时扫描​,分层披露,只有在真正用到某个技能时才付出更多 token。
inline-01.jpg

图:模型先看到技能地图,而不是一次性读完整手册

Skill Runtime 的基本边界:主目录、外部目录与命名空间
Hermes 把 ~/.hermes/skills/ 视为技能的主目录。它是默认读写位置,也是本地技能的单一真实来源。外部目录通过 external_dirs 接入,更多承担扩展和共享的角色,默认不会改变本地主目录的权威性。

典型目录长这样:

~/.hermes/skills/
├── category/
│ └── skill-name/
│ └── SKILL.md
├── .hub/
│ ├── lock.json
│ ├── quarantine/
│ └── audit.log
├── .bundled_manifest
└── .archive/
这里有几个工程取舍。SKILL.md 是技能入口;.hub 保存 Hub 相关的本地状态;.archive 和 .bundled_manifest 属于维护层数据,不应该参与正常技能扫描。Hermes 在遍历时会主动排除这些目录,也会跳过 .git、node_modules、虚拟环境、缓存目录等高噪声路径。

EXCLUDED_SKILL_DIRS = frozenset((
“.git”, “.github”, “.hub”, “.archive”,
“.venv”, “venv”, “node_modules”, “site-packages”,
pycache”, “.tox”, “.nox”, “.pytest_cache”,
“.mypy_cache”, “.ruff_cache”
))
命名空间是另一条边界。普通技能用 skill-name 解析,插件技能用 namespace:skill 解析。这个冒号并不是装饰,它告诉运行时先拆出插件命名空间,再去插件目录里找对应技能。没有这个规则,插件生态很快会撞名。

def parse_qualified_name(name: str) -> Tuple[Optional[str], str]:
if “:” not in name:
return None, name
return tuple(name.split(“:”, 1))
本地优先也很关键。同名技能出现时,Hermes 不会让外部目录悄悄覆盖用户本地版本;真正发生多候选冲突时,它会返回明确错误和所有匹配路径,让用户改用完整相对路径。这个决定减少了“为什么今天调用的不是昨天那个技能”的排查成本。

Level 0:skills_list 只给模型一张轻量地图
会话启动时,Hermes 不会把每个技能的正文都塞进上下文。skills_list() 只返回技能元数据,大约是一个固定的 token 成本。原文估算 Level 0 约为 3k tokens,这笔成本会在会话启动时支付;后面的完整技能内容和参考文件,只有在触发时才成为边际成本。

Level 0: skills_list() -> 仅技能元数据,约 3k tokens
Level 1: skill_view(name) -> 完整 SKILL.md,通常 10-100k tokens
Level 2: skill_view(name, path) -> 技能目录内的某个参考文件
Level 0 的目标不是“让模型读懂所有技能”,而是让模型知道有哪些技能、每个技能大概负责什么、是否适合当前平台和环境。它更像一张地图,不是一本手册。
mermaid-01.png

图:Level 0 从目录扫描到条件激活过滤的完整链路

返回值只保留必要字段:

{
“name”: “skill-name”,
“description”: “Brief description…”,
“category”: “category-name”,
“tags”: [“tag1”, “tag2”]
}
这个阶段的扫描没有依赖 SQLite 或预构建 JSON 索引。Hermes 每次执行 skills_list() 都会重新扫文件系统:

def iter_skill_index_files(skills_dir: Path, filename: str):
for root, dirs, files in os.walk(skills_dir, followlinks=True):
dirs[:] = [d for d in dirs if d not in EXCLUDED_SKILL_DIRS]
if filename in files:
yield Path(root) / filename
dirs[:] 的原地修改是一个小但实用的优化。它不是在遍历后过滤结果,而是在 os.walk() 继续递归之前剪掉不该进入的目录。技能数量少于千级时,这种按需扫描足够简单,维护成本也比额外索引低。

Level 0 还会处理平台和环境匹配。platforms 为空时默认通过;macos 会映射到 darwin,linux、windows 也有对应映射。Termux 需要特殊处理,因为它跑在 Android 上,却经常要兼容 Linux 技能。

PLATFORM_MAP = {
“macos”: “darwin”,
“linux”: “linux”,
“windows”: “win32”
}
环境字段也在这个阶段过滤。Hermes 内置识别 kanban、docker、s6,未知环境默认通过。这个默认值有点宽松,但它避免了一个更糟的问题:新环境还没被运行时认识时,技能全部消失。

_KNOWN_ENVIRONMENTS = frozenset({“kanban”, “docker”, “s6”})
条件激活是 Level 0 里更像 Agent 的部分。技能可以声明 requires_toolsets、requires_tools,也可以声明 fallback_for_toolsets、fallback_for_tools。前者表示依赖不可用就隐藏;后者表示主工具可用时自己退场。比如一个 DuckDuckGo 搜索技能可以只在正式 Web 工具不可用时出现。
mermaid-02.png

图:依赖工具与 fallback 工具共同决定技能是否显示

这样做的好处是,模型看到的不是“所有可能工具”,而是当前会话真正有意义的工具。对 Agent 来说,这比单纯减少 token 更重要,因为候选越乱,错误调用的概率越高。

Level 1:skill_view 的难点在名字解析,而不是读文件
当模型决定使用某个技能时,才进入 Level 1。skill_view(name) 会读取完整 SKILL.md,执行必要的前置处理,然后把完整技能说明交给模型。
mermaid-03.png

图:Level 1 的命名解析、冲突检查与内容预处理

四层名称解析策略体现了兼容性优先级:

策略 1:直接路径

direct_path = search_dir / name
if direct_path.is_dir() and (direct_path / “SKILL.md”).exists():
return direct_path / “SKILL.md”

策略 2:递归按目录名匹配

for found_skill_md in iter_skill_index_files(search_dir, “SKILL.md”):
if found_skill_md.parent.name == name:
return found_skill_md

策略 3:按 frontmatter 的 name 字段匹配

fm, _ = _parse_frontmatter(fm_content)
if fm.get(“name”) == name:
return found_skill_md

策略 4:兼容旧式扁平 .md 文件

for found_md in search_dir.rglob(f"{name}.md"):
if found_md.name != “SKILL.md”:
return found_md
直接路径优先,说明 Hermes 鼓励用户在冲突时显式指定位置。目录名匹配符合大多数人的直觉;frontmatter 名称匹配给重命名目录留下空间;legacy .md 负责兼容旧技能。

真正撞名时,运行时不会装作没事:

if len(candidates) > 1:
return json.dumps({
“success”: False,
“error”: f"Ambiguous skill name ‘{name}’: {len(candidates)} skills match",
“matches”: [str(smd) for _, smd in candidates],
“hint”: “Use full relative path instead”
})
这比“按某个顺序静默选第一个”可靠得多。技能是会执行命令、写文件、访问外部系统的,名称解析上的模糊不该被吞掉。

插件技能在 Level 1 里走一条相似但带命名空间的链路。skill_view(“plugin:skill”) 会先定位插件,再找插件内的技能。如果插件存在但技能不存在,运行时可以列出可用技能;如果找到了,会在返回内容前附加上下文横幅,提醒模型这是哪个插件的一部分,以及有哪些 sibling skills 可以用限定名调用。

[Bundle context: This skill is part of the 'plugin' plugin.
Sibling skills: skill1, skill2.
Use qualified form to invoke siblings (e.g. plugin:skill1).]
Level 1 的后半段是技能内容预处理。Hermes 支持模板变量:

${HERMES_SKILL_DIR} -> 当前技能目录的绝对路径
${HERMES_SESSION_ID} -> 当前会话 ID
如果配置允许,还可以执行内联 shell:

Current date: !date -u +%Y-%m-%d
Git branch: !git -C ${HERMES_SKILL_DIR} rev-parse --abbrev-ref HEAD
这个能力很锋利,所以它应该被视为受控扩展,而不是普通 Markdown 特性。技能内容一旦能执行命令,路径安全和注入检测就必须跟上。Hermes 对技能名做了绝对路径、Windows drive、… 路径穿越检查,也内置了一批 prompt injection 模式,例如 ignore previous instructions、system prompt:、。

Hub 安装技能还有额外安全扫描,重点检查数据渗出、破坏性命令、Shell 注入和 prompt 注入。它不能证明技能一定安全,但能挡住一批低成本攻击。

配置注入也发生在 Level 1。技能可以在 frontmatter 里声明自己需要的配置项:

metadata:
hermes:
config:
- key: wiki.path
description: Path to wiki directory
default: ~/wiki
prompt: Wiki directory path
运行时会从配置文件读取 skills.config.<logical_key>,没有值就用默认值,再展开 ~ 和环境变量。最后把结果追加到技能内容里:

[Skill config (from ~/.hermes/config.yaml):
wiki.path = /Users/erik/wiki
]
这里可以看出 Hermes 对“技能加载”和“技能管理”分得很清楚。加载是按需读取和注入;管理则走 skill_manage,支持 create、patch、edit、delete、write_file、remove_file。如果开启 skills.write_approval,写入不会直接落盘,而是进入 ~/.hermes/pending/skills/,等待用户 review、diff、approve 或 reject。

Level 2:参考文件把长技能拆成可控切片
inline-02.jpg

图:低频细节被延后到参考文件,按需进入上下文

很多技能的主文件不应该无限膨胀。Hermes 的 Level 2 允许按路径读取技能目录内的参考文件:

skill_view(“skill-name”, “references/api.md”)
这一步解决的是另一个 token 问题:有些知识只在特定分支下需要,比如 API 细节、样式规范、平台适配说明。把这些内容全塞进 SKILL.md,会让每次技能加载都变重;拆到 references/ 以后,主技能只负责路由和原则,细节按需进入上下文。

可以把三层加载理解成这张表:

层级 入口 模型拿到什么 主要成本 适合放什么
Level 0 skills_list() 名称、描述、分类、标签 会话启动固定成本 技能发现与选择信号
Level 1 skill_view(name) 完整 SKILL.md 使用技能时的边际成本 工作流、边界、关键规则
Level 2 skill_view(name, path) 某个参考文件 分支触发成本 API 细节、模板、长规范
原文尾部提到的性能优化、安全机制、平台环境匹配,其实都应该放回这三层里看。Level 0 负责过滤和候选控制;Level 1 负责解析、预处理和安全检查;Level 2 负责把低频细节延后。这样理解后,Hermes Skill System 就不是“技能列表 + 技能详情”的二段式接口,而是一套围绕上下文窗口设计的运行时。

一次完整调用:从会话启动到技能内容进入上下文
会话启动时,Hermes 读取配置,解析外部目录,然后扫描技能元数据:
mermaid-04.png

图:会话启动时只注入精简技能元数据

用户触发技能后,完整内容才进入模型上下文:
mermaid-05.png

图:技能被触发后才读取完整说明进入上下文

如果技能再请求 references/api.md,才进入 Level 2。这个顺序让技能系统可以支持很多技能,又不会在每次会话里一次性支付全部成本。

http://www.jsqmd.com/news/1168857/

相关文章:

  • CANN/runtime错误消息示例
  • 终极指南:如何用AALC自动化助手彻底解放你的Limbus Company游戏时间
  • 3分钟快速上手:Nanobrowser智能浏览器助手完整指南
  • 武汉AI品牌曝光优化公司实测观察:从RAG架构到本地化落地的服务商样本解析 - 商业观察
  • 2026南充本地黄金回收内行深度解析:今日价格、熔金内幕与门店真实测评 - 小城生活闲谈
  • 武汉家庭教育指导师报名入口 - 当下教育培训干货
  • 中科院:AI大模型“更努力学习“反而更容易忘光,真相让人意外
  • 学习路径的 A/B 实验设计:怎么证明 AI 推荐比固定路线更有效
  • 2026宁波冰种翡翠回收哪家不压成色价 易奢福宁波三十年老店本地榜首 - 肉松卷
  • 医院陪诊系统源码:用户端+陪诊师端+管理后台整体架构设计方案
  • 2026最新避坑指南宁波二手翡翠回收前估价要准备什么 - 肉松卷
  • 免费解锁《植物大战僵尸》宽屏视野:告别黑边,沉浸式体验终极指南
  • 三分钟快速上手:如何让微信网页版在浏览器中完美运行
  • OptiScaler终极指南:如何为所有显卡解锁AI超分辨率技术
  • 欧米茄售后维修中心整机外观翻新维保地点一览(2026),附定位导航与到店出行完整攻略 - 欧米茄中国售后中心
  • 下一代设计系统:AI 原生组件的形态与交互范式思考
  • 2026年7月最新哈尔滨伯爵官方售后服务热线与网点地址查询 - 亨得利钟表维修中心
  • 武汉高三全日制复读学校哪家好|襄五高中往届生复读初高中衔接培优招生 - 湖北升学规划
  • Loop Engineering与Hermes Agent:AI智能体开发完整实战指南
  • huggingface_hub 0.22.0 下载优化:snapshot_download 并发下载 10GB 模型提速 3 倍
  • 国家中小学智慧教育平台电子课本解析工具:3分钟极速下载教材的完整指南
  • 2026深圳高端首饰奢侈品回收攻略|钻石名表金钻饰品正规门店甄选 - 全国二奢机构参考
  • Zulu AI开发搭子调教指南:上下文感知+规则驯化+IDE原生流
  • ParsePDM:Java实现的跨平台PDM文件解析架构与技术方案
  • 装修行业GEO服务商本地获客榜:装企AI推荐、内容运营与线索承接观察 - 商业先知
  • JXBWKWebView JSBridge实战指南:实现Web与Native无缝通信
  • AWS Bedrock平台接入Claude Fable 5:完整工程实践指南
  • 2026筑宅安|蚌埠阳光房漏水专业修缮,家装商用玻璃顶渗漏、屋面工程一站式根治渗水难题 - 筑宅安
  • 国家中小学智慧教育平台电子课本解析工具:3分钟极速下载指南
  • 精准捕捉蚊虫活跃规律AI智能按需驱蚊 - 优企甄选