DeepAI Paper Hermes Agent 教程,Hermes 记忆、技能与辅助任务 Hermes Agent 技能不触发?skill description 60 字截断与路由排错指南

Hermes Agent 技能不触发?skill description 60 字截断与路由排错指南

如果你给 Hermes Agent 写了一个很完整的 Skill:有多段 description、有 “When to use”、有触发短语、有反例说明,但实际聊天时 Agent 还是不用它,反而去调用别的工具、查旧会话、或者完全猜错方向,那么问题可能不在 Skill 主体代码,而在系统提示词里的技能索引只展示了 description 前 60 个字符

这篇文章基于 NousResearch/hermes-agent issue #13944,整理一个非常适合自定义技能作者排查的问题:

System prompt skill index truncates descriptions to 60 chars

换成人话就是:你写给模型看的技能介绍太长,但模型在第一轮路由时根本看不到后面的关键触发条件。

> 适合搜索关键词:Hermes Agent skill not triggeredHermes skill description 60 charsHermes Agent skills routing wrongavailable_skills description truncatedskills_prompt_snapshot description ends with ...


先给结论:这不是“技能代码坏了”,而是“路由信号没被模型看到”

Hermes Agent 的技能选择大致有两个阶段:

1. 系统提示词中注入 <available_skills> 技能索引; 2. 模型根据这个索引判断是否需要调用某个 Skill 或进一步查看技能详情。

问题在于,issue #13944 指出系统提示词技能索引里,description 曾被硬截断到:

57 chars + ...

也就是大约 60 字符。

所以你在 SKILL.md 里写了:

---
description: Report the live status of Trevor's active LLM fine-tune on node1, including step, loss, ETA, health, and when to use this for phrases like "how is training", "training status", "loss curve"...
---

模型在系统提示词里可能只看到:

Report the live status of Trevor's active LLM fine-tune o...

后面真正有用的:

  • node1
  • training status
  • step
  • loss
  • ETA
  • “不要和某某 skill 混淆”

全都被截掉了。

结果就是:技能明明存在,但模型路由时没有足够信息判断“该用它”。


如何判断自己遇到的是这个问题?

1. 现象层面

你可能看到:

  • 自定义 Skill 已安装,但 Agent 很少主动调用;
  • 用户说了明确触发词,Agent 仍然不用对应 Skill;
  • Agent 调用了 session_search、通用 shell、记忆搜索,甚至拿旧会话里的过期命令来做;
  • 你把 skill body 写得越详细,效果反而没改善;
  • 把关键词塞到 description 开头后,命中率突然变好。

这些都说明:问题可能不是执行逻辑,而是第一眼看到的技能摘要不够有辨识度

2. 检查 .skills_prompt_snapshot.json

issue 里提到可以检查缓存快照:

import json
with open('.skills_prompt_snapshot.json') as f:
    snap = json.load(f)
truncated = sum(1 for e in snap['skills'] if e.get('description','').endswith('...'))
print(f"{truncated}/{len(snap['skills'])} descriptions truncated")

如果大量 description 以 ... 结尾,就说明系统提示词里的技能索引不是完整描述。

你也可以直接搜索某个技能:

import json
with open('.skills_prompt_snapshot.json') as f:
    snap = json.load(f)
for e in snap['skills']:
    if e.get('name') == 'check-training-status':
        print(e.get('description'))

如果输出只有前几十个字符,那你在 description 后半段写的触发词,模型在路由阶段根本没看到。


为什么 skills_list() 里有 1024 字,但系统提示词只有 60 字?

issue #13944 的核心点是:Hermes 当时存在两条不同代码路径。

路径用途description 长度
system prompt skill index会话启动时给模型看的技能索引约 60 chars
skills_list() tool模型主动调用后看到的技能列表MAX_DESCRIPTION_LENGTH = 1024

这就形成一个“鸡生蛋”问题:

  • 完整 description 只有调用 skills_list() 后才看得到;
  • 但模型要不要调用 skills_list(),又取决于系统提示词里那段被截断的简短索引;
  • 如果索引太模糊,模型可能根本不会走到查看完整技能详情那一步。

这也是为什么 issue 作者认为 60 字截断会 undermining skill routing。


维护者最后怎么处理?

这里要特别注意,不要误读成“最终取消 60 字限制”。

issue 评论里维护者明确表示:不打算直接把系统提示词里的描述放大到很长,因为那会在每次加载时消耗大量 token。更现实的方向是:

  • 保留短描述约束,控制系统提示词成本;
  • 让 Skill 作者更清楚地知道:description 前 60 字非常关键;
  • 后续通过文档、authoring chain、system_prompt_preview 等方式反馈实际会进入系统提示词的内容。

后续评论也提到,#24294 采取的是另一种路线:不改变截断限制,而是在技能创建/编辑响应里通过 system_prompt_preview 等方式暴露这个约束。

所以这篇文章的结论不是“升级后所有长描述都能完整进入 prompt”,而是:

> Skill description 要按“前 60 字可独立完成路由”的标准来写。


正确写法:把触发词和用途塞进前 60 字

很多人写 Skill description 会像写 README:先铺背景,再解释能力,最后列 When to use。

对 Hermes 的技能路由来说,这个顺序不理想。

不推荐

This skill provides a comprehensive interface for checking and reporting the current state of a long running training job...

问题是前 60 字里没有:

  • 训练状态
  • step
  • loss
  • ETA
  • node1
  • fine-tune

模型看不出该什么时候用。

推荐

Training status: step, loss, ETA, node1 fine-tune health

这句话短,但高密度地告诉模型:

  • 这是训练状态 Skill;
  • 适合 step / loss / ETA;
  • 和 node1 / fine-tune 相关;
  • health 检查也适用。

如果你还有更长的说明,放到正文或后续 sections 里,但 description 开头必须像搜索广告标题一样精准。


一个实用模板:60 字以内 description 怎么写

可以按这个格式:

[核心对象] + [动作/能力] + [触发词] + [排除歧义词]

示例:

Wechat MP draft: rewrite, format, publish article posts
Server deploy: nginx, docker, logs, rollback, health check
Training status: step, loss, ETA, GPU, node1 fine-tune
DeepAI article SEO: keyword, outline, CTA, WordPress publish
Video edit: cut clips, subtitles, cover, export for Douyin

核心原则:

  • 前 60 字不要写客套话;
  • 不要用 “This skill helps you…” 开头;
  • 先写用户会说的词;
  • 写动词和名词,不写抽象形容词;
  • 如果容易和别的 Skill 混淆,把区别词放前面;
  • 重要实体名、平台名、命令名要靠前。

Skill 作者排错清单

如果你的 Skill 不触发,按这个顺序检查:

1. 打开 SKILL.md; 2. 找到 frontmatter 里的 description:; 3. 数一下前 60 个字符里有没有核心触发词; 4. 检查 .skills_prompt_snapshot.json 里实际展示的 description; 5. 如果以 ... 结尾,确认被截掉的是否正是关键 trigger; 6. 把最重要的 3-6 个关键词挪到 description 开头; 7. 重启 gateway / session,确保 snapshot 重新生成; 8. 用用户真实问法测试,而不是只问“列出技能”; 9. 如果仍不触发,再检查 tool schema、skill name、skills_list、日志和权限问题。


为什么这对 SEO 内容生产也有启发?

这个问题本质上和 SEO 标题很像:搜索引擎和用户先看到的是标题/摘要,而不是全文。

Hermes Skill description 的前 60 字,就像搜索结果里的标题:

  • 不要铺垫;
  • 不要泛泛而谈;
  • 先命中搜索意图;
  • 先放高价值关键词;
  • 让模型一眼知道“什么时候该用它”。

这也是我们在 paper.deepai.wang 写技术文章时一直坚持的原则:标题不能照搬 GitHub issue,而要改成用户会搜索的问题,例如:

Hermes Agent 技能不触发?skill description 60 字截断与路由排错指南

比:

System prompt skill index truncates descriptions to 60 chars

更像真实用户会搜的内容。


DeepAI API 中转站在这里的关系

这个 issue 本身不是 API 网关问题,也不是模型 provider 问题。

DeepAI API 中转站可以帮助你在 Cherry Studio、Cline、Dify、Open WebUI 等支持 OpenAI Compatible API 的工具里统一:

  • Base URL;
  • API Key;
  • 模型选择;
  • 多供应商调用路径;
  • 团队内配置标准。

但它不会自动修复 Hermes Skill description 被截断、系统提示词技能索引不清晰、或 Skill 作者把触发词写在第 100 个字符之后的问题。

更准确的组合方式是:

  • 用 DeepAI API 中转站统一模型接入;
  • 用清晰的短 description 提升 Agent 技能路由;
  • .skills_prompt_snapshot.json 和真实问法测试技能是否被模型看见。

FAQ

为什么我写了很详细的 When to use,Agent 还是不用?

因为模型在初始路由时可能只看到 description 的前 60 字,而不是完整 When to use。把关键触发词放到 description 开头。

直接把 description 写成 1024 字有用吗?

skills_list() 可能有用,但系统提示词里的技能索引不一定展示完整内容。不要假设长描述能进入第一轮路由上下文。

这个问题已经修复了吗?

issue #13944 已 closed/completed,但维护者没有选择“取消 60 字截断”作为最终方向,而是倾向于保留限制并让作者明确知道这个约束。后续提到的 system_prompt_preview 是帮助作者看到实际进入系统提示词的内容。

我应该把 skill name 写长一点吗?

skill name 也重要,但不要只依赖 name。最稳的是:name 简短明确,description 前 60 字包含触发对象、动作和关键词。

Agent 调用了旧版 Skill 或旧命令怎么办?

这可能是 skill routing 失败后,模型转而搜索旧会话或记忆,拿到了过期片段。先修 description 路由,再清理/更新旧记忆和会话缓存。


总结

Hermes Agent 技能不触发,不一定是 Skill 代码坏了。很多时候是模型在系统提示词里的 <available_skills> 只看到了一个被截断的模糊 description。

最实用的修复不是把说明越写越长,而是把 description 前 60 字写成高密度路由信号:

对象 + 动作 + 触发词 + 区分词

对自定义 Agent 工作流来说,这和 SEO 标题、广告标题、工具 schema description 是同一个逻辑:最关键的信息必须出现在模型第一眼能看到的位置。

Related Post

没装 Claude,Agent 却偏要调用 Claude:Hermes delegate_task 的“示例诱导”问题没装 Claude,Agent 却偏要调用 Claude:Hermes delegate_task 的“示例诱导”问题

Hermes delegate_task 在工具 schema 中把 claude 和 Claude Code 写成显眼示例,可能诱导 Agent 在未安装 Claude 的环境里尝试 Claude ACP。本文复盘 #22013:为什么工具说明本身也是 prompt surface,以及如何用环境检测和 schema gating 降低误调用。

Gemini 刚开始 thinking,Hermes streaming 就炸了:.content 字段缺席引发的 AttributeErrorGemini 刚开始 thinking,Hermes streaming 就炸了:.content 字段缺席引发的 AttributeError

Hermes 接 Gemini Code Assist streaming 时,reasoning-only delta 还没有正文 content,下游却访问 delta.content,导致 SimpleNamespace 抛 AttributeError。本文复盘 #24974:streaming adapter 应该始终保持 OpenAI-style delta schema 稳定,content 可以是 None,但字段不能缺席。

Copilot 接入里最隐蔽的坑:模型目录、Token 与企业端点其实是同一条链Copilot 接入里最隐蔽的坑:模型目录、Token 与企业端点其实是同一条链

Hermes Copilot provider 的问题不只是 context window 写错:静态模型目录、原始 GitHub token、OAuth client ID、企业 endpoint 是同一条能力发现链。本文复盘 #7731 与 #15114,解释为什么 Copilot 不能当普通 OpenAI-compatible 接口处理。