ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Hermes智能体自定义技能实战:把重复工作流封装为可复用技能

Hermes智能体自定义技能实战:把重复工作流封装为可复用技能 你每天做的最多的工作是不是那种“不复杂但特别固定”的事情把一堆聊天记录整理成会议纪要把后台数据导出来改成固定格式的日报把零散的产品反馈归类成需求清单。每次做这些事你都得打开聊天窗口重新描述需求、贴范例、强调输出格式。Agent 一开始确实能听懂但它记不住你教完这次下次还得从头教一遍。后来我接触到了 Hermes 这个智能体项目才找到一个更顺手的解法把重复工作流程保存为自定义技能。说白了就是给 Agent 打造一个“专属工具箱”你只要做一次技能封装之后它就能自己判断什么时候该用、怎么用输出格式稳定还能自动调用外部工具。这篇文章我会从环境部署讲到技能原理再带你完整创建一个自定义技能最后把我在实际操作中踩过的坑和排查思路一并整理出来。适合刚接触 Agent 开发、或者已经在用类 Agent 工具但觉得“每次都重新写提示词太麻烦”的人。1. 为什么 Agent 需要自定义技能1.1 重复工作流程的痛点固定指令模板不够用先回到最基础的场景。大部分 AI 工具都支持“自定义指令”或者“预设 Prompt”你可以把一段固定指令模板保存下来下次复制粘贴就行。这个方法确实解决了一部分问题但它有几个明显的短板。第一个短板是触发靠人不靠语义。固定指令模板放在笔记软件里每次要用还得自己想起来翻Agent 不会根据你说话的意图自动匹配这段模板。第二个短板是完全没有参数化能力。同样是“生成周报”本周和上周的时间范围不一样本周的原始材料可能是一段聊天记录也可能是表格文件固定指令模板没有办法把这些变量拆出来。第三个短板更实际——它调用不了工具。复杂一点的重复流程往往不只是“写一段话”那么简单可能还要查数据库、跑一个 RPA 脚本、读取某个文件夹里的最新文件。固定提示词本质上是文本它不具备执行能力。我自己的习惯是把这些重复工作流程先列一个清单标出频率、耗时、输出格式是否固定只要三项都满足就值得做成一个技能。这个思路不仅适用于 Hermes也适用于任何支持技能机制的 Agent 项目。1.2 技能与普通指令模板的根本区别很多人第一次听说“自定义技能”这个词会误以为它就是“高级版预设提示词”。我在实际使用中的体感差距非常大技能和指令模板最核心的区别有三点。第一技能有结构化元信息。Hermes 的技能通常由一个描述文件、一个提示词模板和若干个执行脚本组成。描述文件里写着这个技能叫什么、什么时候触发、需要哪些参数这些信息会被加载进 Agent 的上下文让模型自主判断是否调用。第二技能能真正操作外部世界。它不只是输出文本还可以调用内置工具、执行 Python 脚本、触发浏览器自动化流程、读写文件。也就是说技能可以完成“取数—处理—生成—发送”这条完整链路。第三技能是可持续迭代和组合的。一个技能可以被其他技能调用你可以像拼积木一样搭出更复杂的工作流。用一个生活化的类比固定指令模板是备忘录技能是插件。备忘录提醒你做什么插件直接替你把事情办了。你给 Agent 装上一个“周报技能”它就能在你说“写本周周报”的时候自动打开上一步生成的工作记录、按模板整理成四段式结构、最后输出一份可以直接粘贴到邮件里的版本。1.3 什么时候该做技能什么时候不该做不是什么东西都适合封装成技能我在最开始也走过弯路什么事都想做成技能结果维护成本比手动做还高。后来总结出几个判断标准你可以在动手之前先过一遍。适合做技能的场景有三个特征高频重复每周至少用一次甚至每天都用输出边界清晰结果有固定格式或者明确结构流程可被显式描述你能把每一步列出来写成人能看懂的规则。比如日报生成、邮件分类、订单异常排查、多系统数据汇总都很合适。不适合做技能的场景也有三个特征每次需求差异太大比如写一篇广告创意文案虽然高频但每次方向、人群、风格完全不同技能反而会限制发挥主观判断占比过高比如面试评估、用户访谈分析需要大量上下文理解不适合做成固定模板输出不可验证如果技能跑完你都不知道结果对不对那就先别自动化。记住一个原则技能是给“稳定流程”用的不是给“灵感创作”用的。2. Hermes 环境准备本地部署与配置2.1 部署形态怎么选Docker、Python 环境还是桌面版Hermes 这类智能体项目的部署方式一般有三种源码 Python 环境运行、Docker 容器化运行、以及图形化的桌面版本。我在不同机器上的使用体验可以给你做参考。如果你的电脑是 Windows并且不想折腾依赖冲突我建议优先考虑 Docker Desktop。好处是环境隔离项目自带的依赖、Python 版本、模型配置都封装在镜像里不会污染系统环境。坏处是第一次拉镜像比较慢而且 Docker Desktop 本身对内存有要求。如果你在 Linux 服务器上跑直接用 Python 虚拟环境更轻量启动速度也更快。我自己生产的做法是日常调试用 Python 虚拟环境部署到长期运行的服务器上时用 Docker Compose。至于桌面版它适合完全不碰命令行的用户但做技能开发时不方便看日志和改配置所以我不太推荐重度开发者依赖桌面版。2.2 Windows 系统部署 Hermes 的具体步骤从下载到配置跑通我整理了一份可以直接照着做的流程。第一步是准备基础环境安装 Python 3.10 或更高版本并且勾选“Add Python to PATH”如果选择 Docker 路线安装 Docker Desktop 并启用 WSL2 后端。这一步里最容易踩的坑是 Python 版本太低Hermes 的依赖里有不少库对 3.9 以下的版本已经不作兼容了。第二步是克隆或下载项目仓库建议放到一个路径里没有中文和空格的纯英文目录下比如D:\dev\hermes。我自己第一次部署就是因为文件夹叫“我的项目”导致不少脚本报编码错误折腾了大半天。随后创建虚拟环境cd D:\dev\hermes python -m venv venv venv\Scripts\activate pip install -r requirements.txt第三步是配置模型服务。Hermes 本身是一个 Agent 框架它需要接一个底层的大模型来完成文本理解。你在配置里需要指定模型的服务地址、API Key 和模型名称。很多人在这一步卡住的原因是搞不清楚“模型服务”和“Hermes”的分工Hermes 负责调度、技能加载、工具调用模型负责理解语言和生成回复。可以简单理解成 Hermes 是驾驶系统大模型是引擎。# config.yaml 示例片段 model: provider: openai_compatible base_url: http://127.0.0.1:8000/v1 api_key: sk-local-test name: your-model-name temperature: 0.3这里我建议显式设置temperature: 0.3或更低因为技能执行场景需要稳定的输出温度越高越容易跑偏。2.3 验证安装跑通一个冒烟测试环境配置完别急着写技能先跑一个冒烟测试确认 Agent 能正常回应。我在里约项目里通常会执行一条最简单的技能列表命令hermes skill list这条命令会读取技能目录并把已经加载的技能名称显示出来。如果命令报错优先检查技能目录路径是否正确如果输出为空说明目录里还没有任何技能这是正常的。然后再启动 Agent 服务在对话里随便问一句“你好请介绍一下你自己”。只要模型有正常回复说明链路是通的。所谓冒烟测试就是在正式使用之前用最小成本验证关键路径能跑通。我的习惯是每次改完配置都跑一遍冒烟测试几十秒就能定位是不是基础环境出了问题。3. 技能Skill在 Hermes 中的工作方式3.1 一个技能到底有哪些组成部分在 Hermes 中一个技能不是一个单纯的提示词而是一个功能单元。从我实际搭建的目录看一个标准技能由三个核心文件组成外加一个可选的执行脚本。第一个是技能定义文件通常叫SKILL.md用 Markdown 或 YAML 格式记录技能的名称、描述、触发场景和参数声明。这个文件是整个技能的大脑。第二个是提示词模板负责提供执行规则相当于技能的操作手册。第三个是执行脚本通常是 Python 文件负责真正去调用外部工具、处理文件、调用 API。如果这个技能只需要模型按模板输出文本没有外部动作执行脚本可以省略。技能目录结构一般长这样skills/ weekly-report/ SKILL.md prompt.md schema.json run.py当你把技能放进 Hermes 的技能目录并重启服务后Hermes 会把这些技能的描述信息加载进上下文字段。每当用户输入一段话Agent 会先判断当前请求是否匹配某个技能的描述如果匹配就按照该技能定义的文件去生成和调用。3.2 什么时候触发技能描述里的描述才决定一切我在实际操作中发现决定一个技能能否被正确触发的关键全在SKILL.md里的 description 字段。这个字段会被嵌入到模型的系统提示词中模型拿它来判断“用户当前这句话和这个技能是不是同一件事”。所以写描述的时候要注意两个点。第一要把触发场景和边界说清楚比如“当用户提到上周、本周、周报、period summary 相关说法时优先使用本技能”这比只写“周报技能”有效得多。第二要说明技能能够接受的参数有哪些比如“本周”和“上周”就是不同的时间范围参数。模型会根据你的描述尝试从用户的话里提取参数值这个过程叫参数填充。我通常会做一个对比实验来说明这一点。比如描述写成“生成周报”模型很多时候不知道该不该调用尤其是在用户只说半句话的时候。但描述写成“根据用户提供的工作记录生成四段式周报。当用户提到周报、本周总结、weekly report 时触发可从对话中提取时间范围”触发准确率会显著提升。很多人的技能不被调用问题往往不在代码而在描述写得不够准确。3.3 harness 与 agent 的分工在 Agent 开发里有两个词经常被混在一起harness 和 agent。我自己的理解是agent 是决策者它负责理解用户的最终目标harness 是执行框架它负责把 agent 的想法变成实际动作比如加载技能、调用工具、管理上下文窗口、处理循环控制。以 Hermes 的技能调用为例完整链路是这样的用户输入文本后harness 先组装上下文把系统提示词、可用的技能描述、历史对话记录一起发给大模型模型返回结果要么是一段正常回复要么是一个函数调用指令比如“调用 weekly-report 技能参数 date_range本周”harness 收到这个指令后再去加载对应的技能脚本执行里面定义的动作。所以技能能不能被调用取决于 agent 的决策技能能不能正常运行取决于 harness 的执行。搞清楚这个分工排查问题的时候就不会稀里糊涂了。3.4 技能不是魔法模型本身要支持函数调用还有一点必须提醒如果底层模型不支持函数调用或工具调用Hermes 的技能机制就很难正常运转。因为模型需要通过结构化的方式告诉 harness“我决定调用某个技能”这一步依赖模型的能力。我在本地测试时使用过支持工具调用的开源模型也使用过一些输出能力较弱的模型体验差异很大。建议你在选择底层模型时确认它支持 function calling 或 tool use否则就算技能配置再完善Agent 也无法稳定地调用它。4. 手把手创建第一个自定义技能4.1 从真实场景出发把“周报生成”做成技能纸上谈兵没什么意思我们直接做一个能用的技能。我选择“周报生成”这个场景来演示因为它高频、边界清晰、省时效果又明显。需求描述我是做项目推进的每周都要整理一份周报内容包括本周已完成事项、进行中事项、风险和下周计划。原始素材通常是零散的工作记录和会议纪要。我希望 Agent 帮我完成的事情是把这些原始素材整理成结构清晰的周报并最终输出一段可以直接提交的版本。明确边界之后我开始设计技能。技能名定为weekly-report输入参数有两个一个是date_range表示时间范围另一个是raw_material表示原始工作记录。输出格式是四段式结构。在设计阶段我在笔记本上先手写了一遍提示词确认这套规则自己是能读懂的再往下落文件。这个习惯很重要如果你自己都没法把流程讲清楚模型也做不到。4.2 创建技能目录与定义文件先在 Hermes 的技能目录下新建一个文件夹名字和技能名称保持一致方便管理。目录名称我建议都用小写字母和短横线避免带空格和大写字母因为一些脚本工具在解析带空格的路径时容易出问题。mkdir -p skills/weekly-report cd skills/weekly-report然后创建SKILL.md内容是技能的对外说明。我的写法如下--- name: weekly-report description: 根据用户提供的工作记录或会议纪要生成格式化周报。 当用户提到“周报”“本周总结”“本周工作”“weekly report”等说法时优先使用该技能。 可从对话中提取时间范围默认使用“本周”。 parameters: date_range: type: string required: false description: 周报覆盖的时间范围例如“本周”“上周” raw_material: type: string required: true description: 原始工作记录可以是用户直接粘贴的文本 --- # 周报生成技能 将零散的原始记录整理成适合同步给项目组和管理层的周报。这里最关键的是 description 部分前面花了大篇幅讲的就是这个。它决定了 Agent 什么时候该调用这个技能。参数声明也要写清楚这将帮助模型在调用时自动填参数。4.3 编写提示词模板接下来创建prompt.md这是技能的实际指令。我把它当成一份“给实习生看的操作手册”来写要求覆盖输出格式、语言风格、处理规则并且给一个简单示例。示例很关键模型在少数情况下需要模仿示例的格式。你是项目助理负责把原始工作记录整理成周报。 处理规则 1. 输入是用户提供的原始记录可能包含多段内容先按主题归类。 2. 输出统一为四段 - 本周完成列出已完成的事项每条不超过50字。 - 进行中列出正在进行中的事项标注当前进展。 - 风险与问题列出需要协调或可能延期的事项。 - 下周计划列出下个周期的重点工作。 3. 语言简洁不要口语化。 4. 如果原始记录包含数字或关键数据尽量以“事项名称数据”的形式保留。 5. 最后增加一段“一句话给管理层的摘要”。 原始记录 {{ raw_material }}编写提示词时有个小技巧把变量用类似{{ raw_material }}的占位符写出来这样技能在运行时会把模型提取到的参数填入模板。在 Hermes 的运行逻辑里你可以在执行脚本中把参数传入 prompt 渲染器也可以用模板引擎直接替换具体写法看项目版本。重点是这个模板应该是一个“稳定规则”不要每次改来改去。4.4 注册技能与测试文件创建完成后回到 Hermes 根目录重新加载技能列表。如果你的是有热加载的版本可以在对话中直接输入“请调用 weekly-report 技能生成周报”来触发如果你的版本需要重启就先重启服务再执行hermes skill list确认技能已经被识别。第一次测试时我会先给一个最简单的输入“这周做完了用户调研并输出了报告初稿下周二准备给业务方评审。另外发现一个风险数据库迁移的进度比预期慢两天。”然后观察输出是否符合四段式结构。如果输出格式不对先看 prompt 模板有没有表述清楚如果触发了技能但没有填参数检查 SKILL.md 的参数声明如果根本没触发检查模型是否支持工具调用、技能描述是否足够明确。这里我想强调一个经验测试技能时不要用真实的长数据先用 10 行以内的假数据跑通链路再逐步加大难度。这样排查成本会低很多。4.5 参数化让技能可复用为了让技能更灵活我在 SKILL.md 里定义了date_range参数这样用户说“上周的周报”时模型会自动把 date_range 填成“上周”而不是每次都用同一套输出。如果你希望技能输出不同的风格也可以增加一个style参数比如“简洁型”“数据型”。但参数不是越多越好每增加一个参数模型提取错误的概率就会增加一分。我个人的建议是参数数量控制在两到三个以内并且所有参数都给一个默认值。多一个必填参数就多一个失败的可能。5. 进阶玩法把技能接到工具和记忆上5.1 在技能里调用工具走出“纯文本”的限制很多人把这个阶段叫做“给 Agent 加上手和脚”。如果你只是让模型按模板生成文本那还只是效率工具不算真正的新能力。真正让 Agent 学会新能力是让它可以操作外部系统。回到周报例子上假如你每天的工作记录不是粘贴在对话里的而是存在某个文件夹里的 md 文件或者是某个项目管理平台导出的 CSV你可以在技能的执行脚本run.py里写文件读取逻辑import glob from pathlib import Path def execute(input_text: str , date_range: str 本周, **context): files sorted(Path(f./records/{date_range}).glob(*.md)) combined_lines [] for file_path in files: combined_lines.append(f来源文件{file_path.name}) combined_lines.append(file_path.read_text(encodingutf-8)) raw_material \n.join(combined_lines) # 将 raw_material 传给 prompt 渲染器这里省略具体调用 return {raw_material: raw_material, date_range: date_range}这段代码的思路是技能执行时先按日期范围去目录里拿文件把内容拼接成原始素材再交给提示词模板去生成周报。这样你就能从“手动粘贴记录”变成“Agent 自己去读文件”。再进一步你可以把 RPA 技能接进来。比如让 Hermes 启动一个浏览器自动化脚本从后台系统把当天的销售数据下载下来再调用数据整理技能自动生成报表。我在做这部分开发时通常会先为 RPA 脚本单独写一个冒烟测试确认它能正常跑通再接到 Hermes 技能里避免问题混杂在一起不好定位。5.2 把多步骤工作流保存为技能自定义技能真正好用的地方不只是保存一段提示词而是能把一条完整的工作流保存下来。比如我音频节目组常用的一个流程是抓取后台订单数据 → 清洗重复项 → 生成日报表 → 发送到指定的通知群。这四个步骤涉及数据读取、字段处理、文本生成、接口调用但整体是高度固定的一个月操作三十多次。我把这套流程封装成了一个叫daily-order-report的技能执行脚本里依次调用这几个模块def execute(input_text: str , **context): orders fetch_orders() cleaned clean_orders(orders) summary summarize(cleaned) send_notification(summary) return {status: sent, summary: summary}技能内部可以有清晰的分步执行逻辑只要每步都能输出结果给下一步使用即可。这么做的好处是你不用关心 Hermes 内部是怎么调度这些函数的它把技能脚本当作一个整体来执行最后把结果交给模型来生成面向用户的回复。对我自己来说这是“把重复工作流程保存为自定义技能”这句话最实在的落地场景。5.3 给技能加上记忆跨会话复用的关键默认情况下每次对话结束后Agent 会清空上下文。这意味着技能上一次执行的结果下一次不会自动保留。如果想做到“这周的周报能参考上周的周报”就需要给技能接上记忆模块。我在实践中用的是最简单的方式在技能目录里放一个memory.json执行技能时读取执行完后写入。周报技能的 memory 文件大概存这样的结构{ last_report: 上周主要完成了用户调研输出了报告初稿……, last_updated: 2025-03-16, next_plan: 下周推进数据库迁移与业务方评审 }在 prompt 模板里增加一段“参考信息”把本地上次保存的周报摘要放进去让模型在撰写本周周报时保持连续性。但记忆不是越多越好我建过一个失败的案例把一年内的报告全塞进上下文结果模型被历史信息干扰写出来的内容啰嗦又跑题。所以记忆只保留最近最相关的几个关键摘要就行。更稳妥的做法是在技能执行脚本里做摘要只把之前报告的结论部分写入记忆而不是完整的历史。5.4 技能之间的组合像积木一样搭流程技能还可以互相调用。我经常跟朋友说单个技能像是一个零件组合起来才是一台机器。Hermes 允许在执行脚本里调用其他技能目录里的脚本或者通过上下文让模型“间接调用”。举个例子我有一个fetch-data技能负责取数又有一个format-report技能负责格式化输出。组合技能时我在编排脚本里先调用fetch-data拿到原始数据再调用format-report生成最终文档。这种做法的好处是单个技能保持简单组合逻辑单独维护测试时出问题能精准定位到是取数坏了还是格式化坏了。建议你把可复用的步骤拆成独立小技能比如“从 CSV 读取数据”“把数据生成图表”“把图表发送到群”然后在高阶技能里做组合。顺序不要写死先根据实际场景画一张简单的流程清单再按清单去编排调用。6. 常见问题与排查技巧实录6.1 报错 agent execution terminated due to error这条报错在 Agent 开发中很常见字面意思就是“执行被终止”因为你请求的链路里某个环节已经崩了。根据我的经验原因通常集中在三种情况。第一种是工具调用失败。技能脚本里访问了不存在的文件或者调用的 API 返回了异常状态码。排查方式是看 Hermes 的日志输出错误堆栈会定位到run.py的某一行。第二种是模型返回了非法的函数调用参数。比如技能定义里要求date_range是字符串但模型传了一个对象harness 在解析时就会终止。这种情况可以在技能定义里加强参数校验。第三种是上下文太长导致超时当原始素材非常大时脚本可能被模型服务的 token 限制打断。我一般通过减少输入内容或增加摘要步骤来解决。6.2 Agent 无法生成回复couldnt generate a response我还踩过一种很让人头大的情况Agent 既不报具体错误也不输出最终结果而是来回打转最后提示 “agent couldnt generate a response”。这种多半是循环控制出了问题。最常见的原因是技能执行结果没有回流给模型模型看不到工具调用返回了什么自然无法生成总结。这时你要检查 harness 的配置确保障 技能执行后的返回值能被重新放入上下文。第二种原因是模型服务端本身报错比如请求超时、并发限制查看模型服务那边的日志就能确认。第三种原因是上下文被塞满导致模型没有足够空间生成最终回复。解决办法是限制历史对话轮数或者对中间结果做摘要压缩。我的建议是给 Agent 设置最大执行轮数一般默认 8 轮就够了超过就主动失败避免无限循环烧掉时间和成本。6.3 技能没被触发先检查 description技能不被触发是新手最常遇到的问题但 99% 的情况不是代码有问题而是 description 写得不够具体。模型需要靠这段描述来判断是否调用技能如果描述写得太泛比如“生成周报”模型在遇到“帮我总结一下这个星期的事情”时可能就不知道该不该触发。排查的方法是先看日志确认 Agent 有没有把技能描述加载进上下文。然后做一次人工测试在描述里加上明显的触发词“周报、本周总结、weekly report”都列进去。另外还可以在提示词模板的开头写一句“当用户提到周报相关需求时必须使用本技能”虽然作用有限但在兼容性不太好的模型上能起到强提示效果。6.4 RPA 冒烟测试失败怎么定位如果你像我一样把技能接到了 RPA 流程上我强烈建议你为 RPA 脚本单独做冒烟测试不要等到 Hermes 集成后才发现问题。冒烟测试的思路是用最小可执行样本跑通主链路。比如你写了一个浏览器自动登录脚本冒烟测试就先只测“打开首页输入账号密码点击登录确认跳转到后台”不做任何业务操作。如果这类测试失败多半是选择器定位不准网页改版后元素 ID 变了。你需要在 RPA 脚本里把关键元素的定位状态打成日志这样 Hermes 技能调用失败时一眼能看出是哪个步骤卡住。我自己的项目里会把 RPA 的输出 JSON 化每一步执行完都返回当前状态和关键数据Hermes 侧统一解析。这套做法帮我省掉了大量排查时间。6.5 技能维护几条实在经验技能开发完不是终点维护才是大头。我那段时间踩出来的几条经验总结到这里希望能帮你少走弯路。技能目录和技能名称要保持稳定中途改名会导致依赖它的其他技能全部失效改的时候要检查所有引用。每次修改技能定义后必须重新跑一遍冒烟测试不要只改不测测试成本很低但线上出问题的成本很高。给技能增加一个“变更记录”字段哪怕只是几行字半年后你会感谢自己。最后定期清理不再使用的技能技能目录里堆了太多长期不用的技能会占用上下文窗口反而干扰 Agent 的判断。我一般按月清理一次超过两个月没调用的技能先归档再说。至于排查工具我一般分三层第一层看 Hermes 的日志确认技能加载和调用链路第二层看模型服务的日志确认模型返回了什么第三层在技能脚本的关键位置插入print或者写日志文件定位具体执行到哪一步。这套三层定位法看起来土但在实际项目里比任何高级调试工具都管用。
返回列表