深入解析Hermes自定义技能:构建稳定复用的Agent工作流 📅 发布时间:2026/9/9 6:40:14 👁 浏览次数: 说实话我第一次认真研究 Agent 时心里想的是“这不就是个能聊天的模型包装吗”。真正让我改变看法的是在 Hermes 里把一个重复做了半年的工作流固化成了自定义技能。从那天起我才意识到 Agent 和普通聊天工具之间的分水岭不在模型多大、上下文多长而在于你能不能把那些重复执行、固定指令模板的事情变成一套可以被随时调用的能力。Hermes 的自定义技能机制解决的核心问题就是一件事让 Agent 学会你希望它稳定复用的动作而不是每次都在对话里重新教它一遍。如果你正在用 Hermes 做 Agent 开发或者你已经受够了每天复制粘贴同一段提示词那这篇文章值得你花十分钟看完。我会从技能机制的底层逻辑讲起再带你手写一个能跑通的技能最后把我调试技能时踩过的坑挨个说一遍。1. 技能机制到底在解决什么问题1.1 复制粘贴提示词的天花板先还原一个我自己的真实场景。之前我在做服务巡检每周五都需要汇总一周的服务状态、磁盘占用、错误日志然后再按照固定格式写一份周报。最原始的做法是打开模型对话框把日期、数据源、输出格式这些信息一次性粘贴进去等它给我生成一段报告。问题在于这个流程里“固定”的部分远比我以为的多。输出格式必须跟团队模板对齐风险等级的描述措辞有严格要求甚至某些关键词不可以出现。这些约束每次都要在提示词里写一遍只要哪次复制漏了一段输出的格式立刻开始漂移。更别提不同周的数据源还要临时改来改去整个流程既费时间又非常容易出错。这套操作的本质是把一段需要复用的流程用对话的方式每次重新描述一遍。但凡模型没有严格按你脑子里的规则执行你就要补充说明、再生成一次循环往复。这其实就是提示词的天花板——它缺乏结构没有被命名没有参数接口也谈不上稳定复用。1.2 技能、提示词、插件与 Harness 的区别很多人在接触 Hermes 这类框架时会混淆几个常见概念提示词Prompt、技能Skill、插件Plugin和 Harness。我在用了一段时间后自己总结了一张对比表概念本质上是什么解决的问题典型特征提示词一段自然语言指令让模型理解单次任务要求一次性、无结构、不稳定技能带参数、带步骤的任务模板让 Agent 稳定执行反复出现的任务有名称、描述、参数和执行流程插件外部系统/工具的适配器让 Agent 能够调用外部能力封装 API、命令行、数据库连接等HarnessAgent 的执行环境和流程骨架让决策可以被观察、控制、纠错负责调度、记忆、中断、记录有个比较容易绕进去的问题是“Harness 和 Agent 到底谁是谁”。我的理解是Agent 是那个做决策的大脑它决定下一步要做什么、调用什么Harness 是承载这个决策的运行时框架它负责把 Agent 的决策翻译成可执行的步骤并在每个步骤之间做状态管理。你可以把 Agent 当成一个员工把 Harness 当成这家公司的管理制度和办公系统而技能就是这个员工手里已有的标准作业流程SOP——遇到同类任务时他不需要再从头想一遍怎么干。把这三个东西分开之后你就会发现技能处于一个很特殊的位置它不是某个外部工具的适配层而是“任务流程”的复用单元。工具是技能可以调用的资源技能是用这些资源去完成一类任务的模板。1.3 什么工作适合被固化成技能不是所有任务都适合技能化。我在这上面吃过亏一开始恨不得把什么都变成技能结果反而把自己绕晕了。现在我评估一个工作流是否值得技能化基本就看几条标准高频重复这个任务你是不是每周、每天都干一周只干一次、而且内容千差万别的事情固化收益很低。流程稳定执行步骤是不是大致固定如果每次执行顺序都变技能内部的编排逻辑就没法沉淀。输入输出明确你能说清楚这个任务的输入是什么日期、来源、参数、输出是什么格式、结构、审核标准吗规则可描述过程中的判断逻辑比如什么情况算高风险、什么情况需要升级处理能被写清楚。符合这些标准的典型场景包括日报周报生成、数据定期汇总、巡检报告输出、测试用例批量准备、固定格式文件转换等等。反过来那些天然依赖发散创意的任务比如“帮我想一句品牌 slogan”或者“策划一个全新栏目”我就建议你不要硬做成技能。因为这种任务每一次的需求差别太大做成技能反而会限制模型的发挥空间。好的技能化候选对象是那种你已经重复到快吐了的工作流。2. 把技能定义拆开看Hermes 自定义技能的构成与调用逻辑2.1 一个技能的本质函数化的任务模板如果你写过代码理解技能会非常容易。技能本质上就是一个“函数化的任务模板”——它拥有和函数几乎一样的组成结构技能名称相当于函数名用于在能力列表中唯一标识。描述信息相当于函数的 docstring告诉模型这个技能是干什么的、什么时候该用。参数定义相当于函数签名声明调用这个技能需要哪些输入。执行步骤/提示模板相当于函数体定义拿到参数之后该怎么执行。输出约束相当于返回值规范说明最终输出的结构和格式。我见过很多人跳过“描述信息”这一步直接写正文这是非常致命的。在 Hermes 这类用大模型驱动调度的框架里描述信息不是给人看的注释而是给模型看的“索引”。模型每次收到一个用户请求都会在技能列表中做语义匹配匹配的依据主要就是技能描述。描述写得好技能才可能被正确唤起描述写得含糊你做得再精细也白搭。不同的 Hermes 版本对技能文件的具体格式可能会有些差异但思路是通用的一个目录代表一个技能目录里包含描述文件、模板文件和可选的脚本文件。这种“一个目录一个技能”的组织方式结构清晰也方便用 Git 做版本管理。2.2 Agent 如何发现并调用技能技能机制最核心的设计是“以语义匹配决定是否调用”。我来描述一下实际发生的过程用户输入请求后Harness 会把请求和当前上下文一起交给模型。模型在规划阶段会看到一个当前可用的技能列表——注意模型看到的不是你代码里的文件夹名字而是每个技能 description 字段里的自然语言描述。它开始判断“用户要求的事情和哪个技能描述的场景吻合”举个例子你的技能叫weekly_report描述里如果只写“生成周报”模型在犹豫要不要调用时其实缺乏足够的判断依据。它可能会觉得“周报”这个词太模糊不确定用户问的“帮我总结一下这周干了啥”是不是同一件事。但如果描述写的是“当用户要求汇总本周工作内容并输出包含概况、重点事项、问题风险、下周计划的周报时使用”匹配成功率会大幅提升。调用时模型还会从对话内容中抽取参数。这个环节也很关键参数的 number 类型、格式、默认值定义得越清楚模型抽取就越准。Hermes 内部一般会把每个参数渲染成技能模板里的变量再交给后续执行步骤使用。换句话说参数定义的质量会直接影响整个技能的稳定性。2.3 技能在执行循环里如何运转技能本身是一个模板但它真正跑起来是在 Harness 的执行循环里完成的。这也是为什么理解 Harness 对用好技能很重要。在 Hermes 里技能很少是“一条提示词直接输出结果”那么简单的。更常见的情况是Harness 先解析技能定义把参数注入到模板中然后生成一个执行计划执行计划中的每一步都会经过观测、校验、记录如果某一步出现异常Harness 可以选择重试、跳过或者把错误信息反馈给模型让模型决定下一步怎么办。这种“带截断点和状态记录”的设计给我带来的实际好处是技能执行到一半出问题时我可以通过日志清楚地看到是哪一步出的问题而不是面对一个黑盒。我第一次调试技能时看到日志里记录了完整的工具调用链真的有种从“盲人摸象”变成“拿着图纸干活”的感觉。后面我会详细讲那个常见报错execution terminated due to error的排查思路本质上就是要从这个执行循环的角度去定位问题。3. 动手写第一个技能环境准备、目录结构与参数化模板3.1 准备一个适合调试的 Hermes 运行环境在写技能之前你需要有一个能跑起来的 Hermes。我自己的部署经验是Docker 是最省心的选择。官方镜像会把大部分依赖问题都屏蔽掉你只需要把本地目录挂载进容器再把模型服务的 API Key 或者本地模型地址配置好就行。如果你用的是 Windows我建议优先考虑 Docker DesktopWSL2 后端比较稳。纯 Windows 原生部署也不是不能跑但依赖版本冲突会花掉你很多本不该花的时间。我第一次在 Windows 上折腾时光是解决 Python 和 C 运行库的问题就耗了一个晚上后来切到 Docker 容器整个安装加启动不到十分钟。另外技能调试阶段我强烈建议你用一个成本可控的模型后端。比如把 DeepSeek 这类价格便宜、响应速度也够用的模型接进来作为日常技能执行的主力。这样你在反复测试技能时不用担心调用费用像流水一样出去。等技能逻辑稳定了再切换到效果更好的大模型也不迟。3.2 技能目录与注册方式在你确定 Hermes 已经能正常对话之后下一步就是找到技能目录。我习惯把技能目录理解成“插槽”每个子目录就是一个独立技能。常见的结构大致长这样hermes-skills/ └── skills/ └── weekly-report/ ├── skill.yaml ├── prompt.md └── scripts/ └── format.pyskill.yaml里放的是元信息和参数定义prompt.md是执行模板scripts目录放辅助脚本。不同版本的 Hermes 对字段命名可能不一样但“描述 参数 模板”的整体框架是通用的。你可以在自己的项目仓库里搜一下skills目录看看自带的示例技能长什么样——最好的学习方式永远是先照葫芦画瓢。注册方式一般有两种一种是改了目录之后需要重启 Hermes 才能重新扫描技能列表另一种是支持热更新扫描命令或 API 触发后可以重新加载。我个人习惯在开发阶段用热更新模式改完技能立刻测试效率高出不少。3.3 用周报生成场景写一个参数化技能下面我用“周报生成”这个场景给你展示一个技能定义的核心内容。注意这不是某个固定版本的标准答案而是一个通用范式你落到自己环境时需要对照官方 Schema 微调。name: weekly_report description: 当用户要求汇总本周工作并按周报格式输出时使用。 输入本次周报覆盖的开始日期、结束日期、工作内容来源。 输出包含本周概况、重点事项、问题风险、下周计划的周报。 parameters: - name: start_date type: string description: 本周开始日期 example: 2026-02-09 - name: end_date type: string description: 本周结束日期 example: 2026-02-13 - name: source type: string description: 工作内容来源如 git 提交记录、会议纪要、项目管理工具 example: git log prompt: | 请基于以下信息生成周报 周期{start_date} 至 {end_date} 内容来源{source} 要求按以下结构输出 1. 本周概况用 3-5 句话概括整体进展 2. 重点事项逐条说明附带进展状态和影响范围 3. 问题风险列出当前阻塞或潜在风险并给出等级 4. 下周计划按优先级列出不超过 5 条这里有几个设计上的关键点第一description要写成“当……时候使用”的形式而不是简单写“生成周报”。这能显著提高模型唤起技能的准确率。第二参数不超过 3 个每个参数都提供了example。示例值对模型抽取参数有很大帮助我实测下来给了示例之后参数抽取的准确率能提升不少。第三prompt里用的是变量插值执行时 Hermes 会把{start_date}等变量替换成模型抽取出来的实际值。这样技能模板就具备了参数化能力而不是每用一次就要改一次文件。3.4 测试技能的三段式验证技能写完注册成功不代表它就能正常工作。我平时会把测试拆成三段分别验证这样出了问题能快速定位。**第一段参数抽取测试。**只测试模型能不能从用户输入里准确提取出 start_date、end_date、source 这三个参数。我会故意用很口语化的输入比如“帮我写下周报这周从周一开始到周五内容看 git 最近一周的提交”。如果模型抽出来的参数不对那就是 description 或参数定义有问题跟后面的执行无关。**第二段流程执行测试。**用固定参数直接触发技能看执行步骤是否完整跑完。这一段重点观察有没有报错、步骤顺序对不对、输出结构是否稳定。**第三段多样本回归。**换不同的输入说法去调用同一个技能验证它在不同表达下都能稳定唤起。我记得第一次测试时用“帮我总结一下这周”能唤起用“把周的进展整理成周报发我”就失败了。后来加了一些同义表述到描述里问题才解决。这三段都跑通之后一个技能才算真正可以上岗。4. 完整案例把巡检报告流程固化为可复用技能4.1 从人工巡检流程中拆出可自动化步骤光写一个周报技能可能还不足以展示技能机制的威力。我再用一个更有代表性的案例来说明服务巡检报告生成。在没做技能化之前我每周的巡检流程是这样的人工操作登录服务器检查各服务进程是否存活。查看磁盘使用率重点看有没有接近阈值的分区。拉取最近一段时间的错误日志挑出需要关注的异常。把数据汇总到一张报告里按“服务状态 / 磁盘 / 日志异常 / 风险提示”分组输出。根据磁盘使用率和错误日志频次给每个风险点标记高、中、低等级。整个过程快的话四十分钟慢的话一两个小时而且每次输出的格式会因为当时心情和状态不同而飘忽不定。技能化要做的事情就是把第 1 到第 5 步固化成一套可重复执行的逻辑。我把这个流程拆成了三个子任务数据采集、报告生成、通知推送。其中前两个是核心第三个可以后续再加。拆完之后技能设计的思路就清晰了数据采集可以调用脚本或命令行报告生成用固定模板风险等级判断写成规则不让模型自由发挥。4.2 步骤编排与工具接入在 Hermes 里这种多步骤流程的技能通常需要绑定外部工具来执行采集动作。你可以在技能里定义要执行的命令或者依赖预先写好的采集脚本然后让 Harness 按顺序调用。我当时设计的技能流程是这样的步骤一调用check_services.sh扫描服务进程状态输出存活列表。步骤二调用check_disk.sh读取各分区磁盘使用率。步骤三调用scan_errors.py从日志文件里提取最近 24 小时内的 error 级别记录。步骤四把前三步的数据送入报告生成模板由模型按固定结构生成巡检报告。步骤五根据预设阈值对高风险项做标注。这里有个非常值得注意的设计原则让脚本负责确定性的事情让模型负责总结和润色。服务状态、磁盘数字这些都是硬数据应该由脚本精确读取绝不能让模型凭感觉“猜测”。模型真正擅长的是理解这些数据并用结构化语言写出一份可读性好的报告。每一步之间我都加了超时设置和失败处理逻辑。比如磁盘检查脚本如果执行失败Harness 会记录错误并把失败信息返回给模型模型可以决定是重试还是跳过继续。如果没有这层容错一个技能只要有一个环节偶尔抽风整条流程就会直接死掉。4.3 输出模板与告警分级巡检报告的输出不是模型自由发挥的而是我在技能模板里预先定义好的# 巡检报告示例模板 ## 服务状态概览 - 存活服务... - 异常服务... ## 磁盘使用率 - 分区 /dev/sda1xx% - 分区 /dev/sdb1xx% ## 日志异常摘要 - 错误日志数量xx - 高频错误... ## 风险提示 - 高风险...例如单分区使用率超过 85% - 中风险... - 低风险...风险等级的判断规则我会直接写进技能模板里比如磁盘使用率超过 85% 视为高风险。错误日志中出现连接拒绝、超时等关键词且频次超过阈值视为中风险。服务进程异常退出一律按高风险处理。这些规则看起来简单但价值极大。因为一旦把规则写清楚模型就不需要靠“感觉”去判断风险等级输出的稳定性会明显提升。这其实也是技能和普通提示词的核心差别之一技能可以把业务规则编码进执行流程而提示词只能靠模型临场发挥。4.4 实测效果和调优记录这个技能跑起来之后效果非常直观。原来人工巡检需要四十分钟到一个小时技能自动化后从触发到拿到完整报告大概只需要几分钟而且格式每次都保持一致。省下来的时间主要是两块一是省去了反复整理数据的机械操作二是省去了反复调整报告格式的沟通成本。调优过程中我也遇到了一些问题。最典型的是上下文过长。技能执行到报告生成步骤时如果采集到的日志太多塞给模型的指令就会膨胀模型容易在其中“迷路”输出的报告结构开始不稳定。我的解决办法有两个一是对日志做前置截断只把高频错误和最近的异常样本传给模型二是把报告生成的模板拆得更精简减少不必要的指令占位。调整之后格式漂移的情况明显减少。在模型选择上我最终把日常执行放在了 DeepSeek 这类成本可控的模型上报告质量完全够用。触发故障应急这样的重要场景我才会切到更强的模型。不同模型对同一技能的执行效果会有差异建议你在技能稳定后多换几个模型跑一遍看哪个最稳、哪个性价比最高。5. 踩坑实录技能不生效、参数抽取混乱与执行中断5.1 Agent“看不见”技能描述写法的锅我第一次写完技能注册成功后兴冲冲地跟 Hermes 说“帮我检查一下服务”结果它完全没调用我的技能而是直接按常识回答了我一通。当时我就很困惑技能明明加载了为什么不生效后来我查看了日志发现模型仍在“可用技能列表”中搜索但它觉得用户请求和技能描述匹配不上。问题就出在我给技能的 description 写得太简短。我写的是“执行服务巡检”而用户说的是“帮我查一下现在这服务还正常吗”——模型认为这两句话语义对不上所以去了普通对话分支。解法也很简单把 description 改写成包含更多触发场景的描述核心是解决“模型在什么情况下该调用它”的问题。改完之后用户哪怕换几十种说法提问模型都能稳定命中这个技能。从那以后我写技能第一步永远是“先把 description 写到能覆盖三种常见用户说法为止”。5.2 参数过多会导致抽取不稳定另一个我踩得很深的坑是参数泛滥。有一段时间我想做一个复杂一点的数据分析技能定义了八个参数包括数据源地址、日期范围、统计维度、排序方式、对比基准等等。结果测试时发现模型经常抽错参数要么漏填要么把两个相近参数的值搞反。这个问题的根源在于大模型对长参数列表的抽取能力并不像你以为的那么强。超过五个参数之后混淆率会明显上升。我的调整思路是固定不变的配置写死在技能内部不暴露成参数。能合并的参数尽量合并比如把“开始日期”和“结束日期”合并为一个“日期范围”字符串。每个参数必须给出示例值帮助模型理解格式。最终我把参数压缩到了三个抽取准确率一下子回到了非常理想的水平。记住一条经验技能参数越少模型越不容易犯错。参数不是展示你设计能力的舞台而是影响稳定性的变量。5.3 execution terminated due to error 的完整排查链路如果你经常和 Agent 框架打交道大概率见过execution terminated due to error这个通用错误提示。我第一次遇到它时整个人是懵的因为它看起来像是一个信息量为零的报错。经过几次调试后我总结出一套固定排查链路。这是一次完整的问题排查记录复现最小场景不要带着完整的长流程去测先用最简单的最小输入触发技能。比如只跑数据采集不跑报告生成只传一个参数不传全部参数。这样可以缩小问题范围。看日志定位阶段在 Hermes 的日志里找到执行链路确认是从规划阶段模型拟定步骤就失败还是执行阶段工具调用/脚本运行才失败。两个阶段的修复方式完全不同。规划阶段出错多半是模板太复杂执行阶段出错多半是工具或命令的问题。检查工具调用返回如果你的技能里绑定了脚本把脚本单独拿出来跑一遍。我遇到过最蠢的情况是脚本本身没问题但在 Hermes 的运行目录下路径不一样导致找不到文件。这种问题看错误日志里的路径信息很快就能发现。检查上下文是否超限技能执行到中间步骤时如果每个步骤的输出都被塞进上下文长流程很容易把上下文窗口占满。占满之后后续步骤无法继续就会形成执行中断。我的发现是很多中断不是逻辑bug就是上下文管理的问题——要么截断要么压缩要么减少步骤产出的文本量。分段隔离测试把技能模板从中间拆开前半段跑一次后半段跑一次确定具体是哪一个步骤导致的中断。这种方法虽然原始但定位问题非常高效特别适合在完整链路中找不到线索的时候。修复后回归改完一处之后不要只跑一次成功就算完。我会连续跑五次确保修复是稳定的。因为技能执行涉及大模型决策天然带有随机性单次通过不代表问题已经消失。5.4 技能描述撞车多个相似技能怎么区分当你的技能库越来越大另一个问题会出现两个技能描述很像模型不知该调哪个。我当时的处境是有一个“日报生成”技能和一个“周报生成”技能description 写得都差不多结果用户说“帮我写个总结”模型随机挑了一个输出格式完全不对。解决办法是在描述里写清楚时间范围和其他区分条件。日产的描述突出“仅汇总当天工作”周报强调“汇总某一周、包含下周计划”同时在参数里把日期范围的不同点写明。模型在匹配时就会更倾向于根据用户请求中的时间信息做判断。如果你有多个技能确实功能高度重叠那说明你可能不需要把它们分开定义合并成一个带模式参数的技能会更省事。技能之间要有清晰的边界不要让模型去做艰难的二选一。6. 从单个技能走向技能库版本、组合与团队协作6.1 把技能当代码来管理技能不是写完就一劳永逸。它会随着业务流程调整、模型版本更替而需要修改。一旦你开始认真维护技能就应该把它当成代码来管理放进 Git 仓库、写清楚提交信息、每次修改都经过可追溯的变更记录。我见过一些人直接在部署机器的目录里改技能文件改完也不记录。等到技能出了问题想回退都不知道该回退到哪个版本。更合理的做法是本地开发测试完提交到仓库再通过部署流程同步到运行环境。这样整个变更链路有迹可循也方便多人在同一套技能库上协作。还有一点是技能的回归测试。每次修改技能不要只验证你改的那个点要把这个技能覆盖的典型场景全部跑一遍。大模型执行的不确定性决定了一个字段的修改可能影响另一个原本正常的流程。6.2 组合技能让子技能互相调用当技能数量多起来之后你会发现很多技能之间存在公共部分。比如“报告生成”这个能力周报在用巡检报告也在用。这时候不用每建一个技能就把公共逻辑复制一遍更好的做法是拆出基础子技能再让主流程去调用它们。以巡检报告为例我最终把技能拆成了下面这样collect_metrics负责执行数据采集脚本输出结构化数据。generate_report负责根据数据和模板生成报告。send_notice负责把报告推送到指定的通知渠道。巡检报告主技能只需要描述自己的整体流程内部按顺序调用这三个子技能。这样每个子技能保持简单、单独可测组合在一起又能覆盖复杂的业务场景。这个思路跟代码开发里的“函数组合”完全一致。6.3 团队共用技能库的规范如果你不是一个人在维护技能而是和团队共享一套技能库那就需要一些共识性的规范。根据我自己带小团队用 Agent 的经验下面几条规则能让协作顺畅很多命名规范技能名统一用snake_case比如generate_report不要用中文名或带空格的名字。描述规范description 必须以“当用户要求……时使用”开头保证模型对每个技能的业务边界都清楚。参数规范必须有 example 字段避免让模型通过猜的方式去填参数。安全边界技能涉及命令执行、文件访问时要做权限控制。给技能最小权限能读就只读能只调一个脚本就不要放开任意命令执行。这不只是防外部风险也是防止模型在某次规划中做出不可预期的危险操作。团队协作中还有一个容易忽略的点技能库要有“负责人”。每个技能必须有人对它负责出了问题能找到人来修。否则技能库很快就会变成谁都能改、但又没人真正维护的垃圾场。6.4 有些事真的不适合技能化讲了这么多技能怎么建、怎么维护最后我想泼一点冷水不是什么东西都该变成技能。我见过有人试图把“项目复盘报告”做成长长长的技能里面塞了十几条指令结果用起来效果还不如让模型直接生成。原因是项目复盘这件事每次的目标对象、结论深度、受众群体差异极大根本不具备“稳定的执行流程”。强行技能化反而让模型的自由度被压缩输出的内容变得套路化。判断一个任务该不该技能化你可以回到开头那几条标准问自己它高频吗流程稳定吗输入输出明确吗规则可描述吗如果四个问题里有任何一个是否定的那就先别急等流程再跑一段时间成熟了再固化。技能化的目的是解放你而不是为了让你维护一套沉重的技能模板。我自己现在的习惯是每隔一段时间就复盘一下手上的重复工作挑出最烦人、最机械的那个流程把它做成技能。一次只做一个做扎实了再做下一个。这样技能库始终保持精简每个技能也都被真实业务验证过而不是一堆中看不中用的半成品。最后分享一个我自己的小体会刚开始用 Hermes 时我总想着让 Agent 一步到位学会所有东西结果很快被技能维护的成本压得喘不过气。真正让我尝到甜头的反而是从最简单、最痛的单一流程入手把一个技能打磨到其他同事也愿意使用。那之后我才慢慢意识到自定义技能的价值不在于数量多而在于每一个都能稳定复用。造工具最开心的一刻永远是它帮你把一件原本不想干的重复工作彻底甩开的时候。