分享一套 Hermes Agent Skills 开发实战教程,以“陌陌回复信息”为场景,完整拆解 Skills 机制、目录规范、代码实现、注册调试与部署上线全流程。不管你是刚接触 Agent 开发的新手,还是想把 Skills 引入生产项目的开发者,都能照着一步步跑通。
1. Hermes Agent 与 Skills 机制详解
1.1 什么是 Hermes Agent
Hermes Agent 是一个面向多场景的 AI Agent 框架,它的定位是让开发者用相对轻量的方式,把自己的业务逻辑封装成“可被 Agent 调用”的功能模块。你可以把它理解成一个带“技能系统”的智能助手外壳:Agent 本体负责接收任务、理解意图、调度工具,而具体干活的能力则交给不同的 Skills 去完成。
和普通聊天机器人不同,Hermes Agent 更强调任务的落地执行能力。例如:
- 收到一条新的陌陌消息后,根据消息内容自动判断是否需要回复;
- 根据关键词匹配预设回复模板;
- 将消息分类、记录到外部数据库或知识库;
- 定时检查未读消息并提醒用户。
这些能力如果写死在主程序里,每加一个场景就要改一次 Agent 核心代码;而通过 Skills 机制,我们可以把每个场景拆成独立技能,动态加载、独立维护、按需调用。
1.2 什么是 Skills,为什么需要 Skills
Skills 是 Hermes Agent 的“外挂能力包”。一个 Skill 通常包含:
- 一份描述文件:说明这个技能是干什么的、什么时候该用;
- 一个或多个可执行脚本:具体执行逻辑;
- 可选的配置文件:定义规则、参数、模板等。
Skills 的价值可以从三个角度来看。
从开发效率看,Skills 实现了关注点分离。Agent 主程序不需要关心陌陌消息怎么处理、关键词怎么匹配,它只需要知道你注册了一个叫momo-reply的技能,并在合适的时机调用它。
从维护角度看,Skills 是独立部署单元。某个技能出现问题,不会拖垮整个 Agent。技能逻辑更新时,也只需要替换对应目录,不需要重新启动 Agent 主体。
从复用角度看,Skills 可以跨项目迁移。同一个回复技能,改改配置就能从陌陌迁移到其他 IM 平台;同一个知识库查询技能,也可以被不同 Agent 项目复用。
1.3 AI Agent Skills 与 Agent 的区别
这里需要区分两个概念。
Agent 是“大脑”,负责接收任务、拆解计划、选择工具、执行动作。它具备上下文理解、多步推理和决策能力。你可以把它理解为“调度中心”。
Skills 是“手脚”,是 Agent 可以调用的具体能力单元。Skills 本身不负责复杂推理,只负责执行被分配的任务,比如“读取消息并匹配模板”“调用 HTTP 接口发回复”“把数据写入数据库”。
两者配合的方式是:Agent 先分析用户请求,判断需要调用哪个 Skill,然后携带参数触发 Skill 执行。Skill 执行完毕后把结果返回给 Agent,Agent 再决定下一步动作。
在很多教程中,Skills 被等同于“给 Agent 装插件”,这个比喻是比较准确的。插件本身不能独立完成完整业务,但离开插件,Agent 就缺少实际干活的手段。
2. 环境准备与基础配置
2.1 安装 Hermes Agent
不同环境下安装 Hermes Agent 的方式略有差异,本文以常见的 Python 环境为例。
首先确保本机已经安装 Python 3.10 及以上版本,并建议使用虚拟环境隔离项目依赖:
# 创建并激活虚拟环境 python3 -m venv hermes-env source hermes-env/bin/activate # Windows 下为 hermes-env\Scripts\activate # 安装 Hermes Agent(示例命令,请以实际官方安装文档为准) pip install hermes-agent如果你使用的是 macOS,需要注意系统自带的 Python 版本通常较低。建议先通过 Homebrew 安装较新版本 Python,再创建虚拟环境:
brew install python@3.11 python3.11 -m venv hermes-env source hermes-env/bin/activate pip install --upgrade pip pip install hermes-agent安装完成后,可以用一行命令验证是否成功:
hermes --version如果能正常输出版本号,说明核心安装已经完成。
2.2 配置 API Key 与大模型接入
Hermes Agent 本身不内置大模型推理能力,它需要接入一个 LLM API 来充当“大脑”。常见选择包括 OpenAI 兼容接口、阿里百炼等国内大模型平台。
在项目根目录下创建.env文件:
# .env LLM_API_KEY=你的API_Key LLM_BASE_URL=https://api.openai.com/v1 LLM_MODEL=gpt-4o-mini或者使用阿里百炼:
# .env LLM_API_KEY=你的阿里百炼API_Key LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 LLM_MODEL=qwen-plus注意:不同平台的 base_url 和模型名称差异较大,请以你的模型服务商实际文档为准。填写错误的 base_url 是新手最常见的报错原因之一。
2.3 验证 Agent 基础对话能力
配置好环境变量后,启动 Hermes Agent 交互模式:
hermes如果安装和配置都正确,你应该能进入一个类似命令行聊天的交互界面。此时随便输入一句“你好”,Agent 应该能基于大模型返回回复。
如果出现连接超时、401 鉴权失败等错误,先不要往下继续,优先解决网络连通性和 API Key 配置问题。之后再进 Skills 开发。
3. 开发“陌陌回复信息”Skills 前的设计思路
3.1 需求场景分析
我们要开发的 Skill 是“陌陌回复信息”。在动手写代码前,先把需求拆细。
典型使用场景包括:
- 用户收到多条陌陌消息,希望 Agent 自动回复常见问题;
- 用户不在电脑前,Agent 根据预设规则先回复对方,避免让对方等待;
- 用户希望将消息按关键词分类,重要消息单独提醒;
- 用户在陌陌对话中需要快速应答,例如“在吗”“你好”“价格多少”。
由此可见,这个 Skill 的核心能力不是“替用户聊天”,而是“根据规则做自动应答”。因此设计上必须考虑:
- 如何获取新消息?是轮询接口,还是接收 Webhook 推送?
- 如何判断哪条消息需要回复?全部回复会导致骚扰,必须设置过滤规则。
- 回复文案从哪里来?固定模板、关键词模板,还是交给大模型生成?
- 高频发送是否会被平台风控?必须设置发送频率控制。
其中,消息获取方式取决于你用的是陌陌开放平台的企业接口,还是个人使用的自动化方案。本文以“已验证的合法授权 API 或本地消息回调”为前置条件,演示 Skills 内部处理逻辑。具体消息来源的接入方式,需要根据你的实际授权通道来确定。
3.2 Skills 目录结构与文件规范
建议在 Hermes Agent 项目下建立如下目录结构:
hermes-agent-project/ ├── .env ├── skills/ │ └── momo-reply/ │ ├── SKILL.md │ ├── main.py │ ├── config.yaml │ └── templates/ │ ├── greeting.txt │ ├── price.txt │ └── default.txt ├── logs/ └── run.py各文件职责如下:
SKILL.md:技能的元信息描述,告诉 Hermes Agent 这个技能的用途、触发条件和参数说明。main.py:技能核心逻辑,负责消息读取、规则匹配、模板调用和结果返回。config.yaml:关键词规则、回复模板路径、发送频率等配置。templates/:存放回复模板,方便在没有代码开发经验的运营同学维护文案。logs/:运行日志。
3.3 回复策略设计
自动回复最容易踩的坑是“什么都想自动回复”。实际设计时,建议把消息分为三类:
第一类是可直接自动回复的消息。比如“你好”“在吗”“多少钱”“怎么联系你”等常见问题,关键词命中后直接使用模板回复。
第二类是需要人工确认的消息。比如客户问到个性化价格、特殊需求、投诉反馈,此时自动回复应明确告知“稍后人工回复”,而不是让大模型自由发挥导致错误承诺。
第三类是垃圾消息或无关消息。直接过滤,不回复、不记录、不打扰。
这三类消息在config.yaml中分别对应auto_reply_rules、manual_reply_keywords、block_keywords。
4. 完整实战:编写并注册 momo-reply Skills
下面进入核心环节。我们将从创建一个 Skill 目录开始,逐步编写技能描述、核心逻辑、配置文件,最终让 Hermes Agent 能够识别并调用这个技能。
4.1 创建 Skill 目录与技能描述文件
首先创建技能目录:
cd hermes-agent-project mkdir -p skills/momo-reply/templates接着编写skills/momo-reply/SKILL.md。这个文件是 Agent 识别技能的关键,描述写得越清晰,Agent 在遇到相关任务时越容易正确调用。
--- name: momo-reply description: > 处理陌陌新消息并自动回复。 当收到陌陌用户的聊天消息时,先对消息内容进行规则判断。 如果命中的是自动回复关键词,就使用对应模板回复; 如果命中人工处理关键词,则生成提示消息并通知人工介入; 如果命中屏蔽词,则不回复并标记忽略。 version: 1.0.0 author: your-name triggers: - 陌陌消息 - 回复陌陌新消息 - momo message - 自动回复 parameters: - name: message description: 陌陌新消息内容 type: string required: true - name: sender_id description: 发送者ID,用于回复消息时定位会话 type: string required: true --- # momo-reply Skill 本技能用于自动回复陌陌平台的新消息。 ## 调用流程 1. 接收新消息内容与发送者ID 2. 按关键词规则判断消息类型 3. 根据消息类型选择回复策略 4. 返回回复结果给 Agent这个文件的核心是 metadata 部分。name是脚本内部标识,description是给 Agent 看的技能说明,triggers是触发词,parameters是调用时需要传入的参数。
4.2 编写核心回复逻辑 main.py
接下来编写skills/momo-reply/main.py。这个脚本实现了整个自动回复的核心逻辑。
# 文件路径:skills/momo-reply/main.py import os import re import time from pathlib import Path import yaml class MomoReplySkill: """陌陌回复信息技能""" def __init__(self, config_path: str = None): self.config = self._load_config(config_path) self.last_reply_time = {} def _load_config(self, config_path: str = None): """加载 YAML 配置文件""" if config_path is None: config_path = Path(__file__).parent / "config.yaml" with open(config_path, "r", encoding="utf-8") as f: return yaml.safe_load(f) def classify_message(self, message: str) -> str: """ 按规则对消息进行分类。 返回值: - "auto": 可自动回复 - "manual": 需要人工介入 - "block": 应忽略或屏蔽 """ if not message or not message.strip(): return "block" # 检查屏蔽词 for keyword in self.config.get("block_keywords", []): if keyword in message: return "block" # 检查人工处理关键词 for keyword in self.config.get("manual_reply_keywords", []): if keyword in message: return "manual" # 检查自动回复关键词 for rule in self.config.get("auto_reply_rules", []): pattern = rule.get("pattern", "") if re.search(pattern, message, re.IGNORECASE): return "auto" # 默认走人工处理,避免乱回复造成业务风险 return "manual" def build_reply(self, message: str, category: str) -> dict: """根据消息分类构建回复内容""" templates = self.config.get("templates", {}) if category == "auto": # 遍历规则,找到第一个匹配的模板 for rule in self.config.get("auto_reply_rules", []): pattern = rule.get("pattern", "") if re.search(pattern, message, re.IGNORECASE): template_key = rule.get("template", "default") reply_text = self._render_template( templates.get(template_key, templates.get("default", "")) ) return {"action": "reply", "content": reply_text} if category == "manual": reply_text = self._render_template(templates.get("manual_reply", "")) return {"action": "notify", "content": reply_text} if category == "block": return {"action": "ignore", "content": ""} return {"action": "ignore", "content": ""} def _render_template(self, template: str) -> str: """渲染模板文本,可以替换占位符""" current_time = time.strftime("%Y-%m-%d %H:%M:%S") return template.replace("{{time}}", current_time) def handle_message(self, sender_id: str, message: str) -> dict: """ 对外暴露的统一入口。 返回格式: { "action": "reply" | "notify" | "ignore", "content": "回复内容或提示内容" } """ # 频率控制:同一发送者 30 秒内最多回复一条 now = time.time() last_time = self.last_reply_time.get(sender_id, 0) if now - last_time < self.config.get("min_reply_interval", 30): return {"action": "ignore", "content": ""} self.last_reply_time[sender_id] = now category = self.classify_message(message) result = self.build_reply(message, category) return result # 供 Hermes Agent 调用的入口函数 if __name__ == "__main__": import json import sys skill = MomoReplySkill() # 支持命令行参数调用:python main.py sender_id message if len(sys.argv) >= 3: sender_id = sys.argv[1] message_text = sys.argv[2] else: # 从 stdin 读取 JSON raw_input = sys.stdin.read().strip() data = json.loads(raw_input) sender_id = data.get("sender_id", "") message_text = data.get("message", "") result = skill.handle_message(sender_id, message_text) print(json.dumps(result, ensure_ascii=False, indent=2))这个脚本有几个设计亮点值得说明。
第一,消息分类逻辑是独立方法,方便单独测试。你可以直接调用classify_message验证某条消息会被分类成什么,而不需要真正发送消息。
第二,默认分类是“manual”而不是“auto”。这是很多自动回复系统容易忽略的地方:当消息无法匹配任何规则时,宁可通知人工介入,也不要让 Agent 随便编一句话回复。因为回复内容一旦涉及业务承诺、价格、时间等敏感信息,错误回复的代价远大于“晚回复一会儿”。
第三,加入了 30 秒频率限制。同一个发送者短时间内多次触发,只会回复第一条,避免被平台判定为骚扰行为。
4.3 编写关键词规则配置 config.yaml
config.yaml是整个技能的可配置中心。把关键词和模板从代码里抽离出来,后续运营同学不需要改代码就能调整回复策略。
# 文件路径:skills/momo-reply/config.yaml # 同一发送者最小回复间隔(秒) min_reply_interval: 30 # 屏蔽关键词:命中后直接忽略 block_keywords: - "广告" - "兼职" - "刷单" - "加V" - "赌博" # 需要人工介入的关键词 manual_reply_keywords: - "价格" - "优惠" - "合同" - "投诉" - "发票" - "退款" - "定制" # 自动回复规则,按从上到下顺序匹配 auto_reply_rules: - pattern: "你好|您好|在吗|在不在|hi|hello" template: greeting - pattern: "怎么联系|联系方式|微信|电话|手机" template: contact - pattern: "产品|介绍|业务|做什么" template: intro - pattern: "时间|几点|营业" template: working_time - pattern: "地址|在哪|位置" template: address # 回复模板 templates: greeting: "您好,我已经收到您的消息,稍后人工会回复您。如果需要立即帮助,可以留言说明。" contact: "您好,我们的联系方式是:138****1234(工作时间 9:00-18:00)。" intro: "您好,我们提供软件开发与运维服务,具体业务介绍请留下您的需求,我们会安排同事与您联系。" working_time: "您好,我们的工作时间是工作日 9:00-18:00。当前消息可能无法即时回复,请耐心等待。" address: "您好,我们的办公地址在北京市朝阳区****,欢迎提前预约来访。" default: "您好,您的消息已收到,我们会尽快处理。" manual_reply: "您的问题需要专业同事处理,已转人工,请稍等。当前时间:{{time}}"4.4 将 Skill 注册到 Hermes Agent
光有目录和代码还不够,还需要让 Hermes Agent 知道这个技能的存在。
在 Hermes Agent 的 config 目录下的skills.yaml或主配置文件中注册该技能:
# config/skills.yaml skills: - name: momo-reply path: skills/momo-reply enabled: true entry: main.py配置项说明:
name:技能唯一标识path:技能目录相对路径enabled:是否启用entry:入口脚本文件名
部分版本的 Hermes Agent 支持自动扫描 skills 目录,此时可以跳过注册步骤。建议还是显式注册,方便快速停用某个技能。
重启 Agent:
hermes restart或者退出当前交互模式后重新运行:
hermes4.5 运行与验证
先单独运行 Skill 脚本,验证核心逻辑是否正常。
测试自动回复:
cd skills/momo-reply python main.py "user_001" "你好,在吗?"预期输出:
{ "action": "reply", "content": "您好,我已经收到您的消息,稍后人工会回复您。如果需要立即帮助,可以留言说明。" }测试人工介入:
python main.py "user_002" "你们的价格是多少?"预期输出:
{ "action": "notify", "content": "您的问题需要专业同事处理,已转人工,请稍等。当前时间:2025-01-15 14:30:00" }测试屏蔽词:
python main.py "user_003" "加V,兼职刷单"预期输出:
{ "action": "ignore", "content": "" }三个用例通过后,就可以在 Hermes Agent 中测试完整调用链路了。在 Agent 对话中输入:
有新陌陌消息,发送者 user_001,内容为:你好在吗?Agent 会识别任务意图,触发momo-reply技能,并返回回复结果。整个过程的日志会记录在logs/目录下,便于排查。
5. 常见问题与排查思路
5.1 问题排查表
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| Agent 不识别 momo-reply 技能 | 技能未注册或路径配置错误 | 检查 skills.yaml 中 name、path 是否与目录一致 |
| 调用技能时提示“skill not found” | 技能目录被移动或删除 | 确认路径存在,重新注册并重启 Agent |
| 无论发什么消息都走 manual | 正则表达式未匹配到 auto_reply_rules | 用 python3 -c 单独测试正则是否命中 |
| 发送频率过高 | min_reply_interval 配置过小 | 调大间隔,建议 30 秒以上 |
| 中文乱码 | 文件编码不是 UTF-8 | 统一使用 UTF-8 保存所有 py/yaml/txt 文件 |
| Agent 直接大模型生成回复,不走技能 | SKILL.md 的 triggers 描写不准确 | 增强 description 和 triggers,明确触发场景 |
| Python 依赖缺失 | 未安装 pyyaml | 执行 pip install pyyaml |
5.2 典型问题分析
问题一:技能触发了,但返回空内容。
排查顺序如下:
- 先执行
python main.py test_user "你好",确认脚本本身有输出。 - 检查 SKILL.md 中 parameters 名称是否与分析器传入参数一致。如果 Agent 传入的是
user_id,而脚本入口接收的是sender_id,就会拿到空值。 - 查看日志中技能的调用参数,确认参数是否成功传递。
问题二:自动回复被平台判定为骚扰。
这通常是频率控制缺失导致的。若消息获取侧是 Webhook 推送,瞬间可能收到多条消息,如果没有间隔限制,技能会秒回大量消息。
解决方案是同时在两个层面做限制:技能内部设置min_reply_interval,消息获取侧设置单用户每日回复上限。
# 在 config.yaml 中扩展每日上限 max_reply_per_day: 50问题三:Agent 偶尔绕过技能,直接用大模型回复。
这种问题通常是因为技能描述不够清晰。大模型无法判断“什么场景必须用技能”,于是选择自由发挥。
修改SKILL.md的 description,让它更明确:
description: > 处理陌陌新消息时必须使用本技能,禁止直接生成回复内容。 收到陌陌消息后,先调用本技能进行判断。5.3 通用排查步骤
遇到问题时,建议按下面顺序操作:
- 查看日志。Hermes Agent 的
logs/目录下会有运行日志,先定位有没有技能调用的记录。 - 单独测试脚本。把 Skill 从 Agent 中摘出来,用命令行传参方式运行,确认核心逻辑无误。
- 逐级简化。把规则减少到最小,只保留一条自动回复规则,验证通路。
- 恢复完整规则。确认通了以后,再逐步加回其他规则,定位是哪个规则导致的问题。
6. 最佳实践与工程建议
6.1 规则优先,大模型兜底
陌陌自动回复这个场景,天然适合“规则优先”而不是“大模型优先”。
原因是成本从低到高排序应该依次是:完全规则匹配 → 模板变量填充 → 大模型生成。前两者成本低、速度快、可控性强、并且不会有幻觉;大模型生成适合处理那些规则覆盖不到但确实需要语义理解的场景。
推荐的执行顺序是:
- 屏蔽词检查优先,直接忽略垃圾消息;
- 关键词规则匹配,命中自动回复模板;
- 敏感词触发人工介入提示;
- 以上都没命中时,才考虑让大模型生成候选回复,并且加一条系统提示限制“不确定时不要承诺业务细节”。
6.2 模板与代码分离
把回复文案写在templates/目录下,而不是硬编码在main.py中,这个设计在真实项目中收益很大。
运营人员可以独立维护文案,不需要理解 Python 代码。只需要按模板格式修改 txt 文件,重启 Agent 或触发技能重新加载配置即可生效。
文案文件按业务场景命名:
templates/ ├── greeting.txt ├── contact.txt ├── intro.txt ├── working_time.txt ├── address.txt └── manual_reply.txt每个文件内容保持简洁:
# templates/manual_reply.txt 您的问题需要专业同事处理,已转人工,请稍等。当前时间:{{time}}6.3 日志记录与审计
自动回复类技能必须要有完整日志,原因有两个:一是业务上需要追溯某条回复是在什么时间、基于什么规则发出的;二是出现问题时,没有日志几乎无法排查。
建议在handle_message中增加日志输出:
# 在 skills/momo-reply/main.py 中增加日志 import logging logging.basicConfig( filename=str(Path(__file__).parent.parent.parent / "logs" / "momo-reply.log"), level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s" ) logger = logging.getLogger("momo-reply")每次处理消息时记录:
logger.info("sender=%s message=%s category=%s action=%s", sender_id, message, category, result.get("action"))日志字段至少包括:时间、发送者 ID、原始消息内容、消息分类、最终动作、回复内容。注意,涉及用户个人信息时要遵守数据安全规范,建议对发送者 ID 做脱敏处理。
6.4 合规与安全边界
这个部分非常重要。
自动回复技能只应接入你已经获得合法授权访问的消息通道。如果是基于陌陌开放平台或企业服务接口,必须严格遵守平台开发者协议,不可以使用任何非官方破解、劫持、模拟登录等非法方案去读取或发送消息。
同时需要注意:
- 消息内容中可能包含用户隐私,不得在日志中记录完整消息内容,建议只记录脱敏后的摘要。
- 自动回复文案不得包含色情、赌博、虚假宣传、诱导分享等内容。
- 发送频率必须克制,高频自动回复不仅影响用户体验,还可能触发平台风控。
- 涉及业务承诺的回复文案(价格、时效、售后)必须经过业务方审核。
6.5 Skill 开发过程中的测试策略
建议为 Skill 建立三份测试数据。
第一份是“必须是自动回复”的用例集。例如:你好、在吗、你们做什么的、怎么联系你。
第二份是“必须人工处理”的用例集。例如:你们的报价单能发我一份吗、我要投诉你们服务态度。
第三份是“必须忽略”的用例集。例如:兼职刷单加V、各类广告文案。
每次修改规则后,把三份用例集跑一遍,能有效防止“修好一个场景,搞坏另一个场景”的回归问题。
7. 总结与后续学习建议
到这里,一个完整的 Hermes Agent 陌陌回复信息 Skills 已经开发并跑通了。
我们完成了以下关键动作:
- 理解了 Hermes Agent 与 Skills 的关系,明白 Skills 是 Agent 的可插拔能力单元;
- 完成 Hermes Agent 安装与基础配置;
- 设计了三层消息分类策略:自动回复、人工介入、忽略;
- 编写了完整的
SKILL.md、main.py、config.yaml; - 通过了三个典型测试用例的验证;
- 梳理了常见问题和排查路径。
接下来如果你想继续深入,建议优先探索这几个方向:
第一个方向是消息通道接入。把当前脚本中的消息入口从命令行参数改为 Webhook 方式,让技能能够实时响应推送的新消息。
第二个方向是多轮对话能力。当前技能是单轮自动回复,如果消息场景需要多轮问答,可以引入会话状态存储。
第三个方向是外部知识库集成。热搜词里提到“外挂知识库”,这正是 Skills 的进阶玩法——把产品手册、常见问题文档挂载到知识库中,让 Agent 在自动回复时能基于知识库内容应答,而不只是固定模板。
Skills 开发的核心逻辑可以总结为:先定义清楚触发条件,再设计好消息分类规则,最后让回复内容可控、可审计、可回溯。这套方法论不限于陌陌,换到任何 IM 平台的自动回复场景都可以复用。
如果你在实操中遇到了 SKILL.md 描述不生效、正则不匹配、参数传递异常等问题,建议先从日志和数据入手,把输入输出打出来,问题通常就能暴露出来。