插件
Hermes 提供了一套插件系统,用于在不修改核心代码的前提下扩展自定义工具、hooks 和集成。
→ Build a Hermes Plugin — 含完整可运行示例的逐步指南。
快速概览
把一个目录放到 ~/.hermes/plugins/ 下,并包含 plugin.yaml 和 Python 代码:
~/.hermes/plugins/my-plugin/
├── plugin.yaml # manifest
├── __init__.py # register() — wires schemas to handlers
├── schemas.py # tool schemas (what the LLM sees)
└── tools.py # tool handlers (what runs when called)
重新启动 Hermes 后,你的工具就会与内置工具一起出现,模型可以立即调用它们。
最小可运行示例
下面是一个完整插件示例:它添加一个 hello_world 工具,并通过 hook 记录每次工具调用。
~/.hermes/plugins/hello-world/plugin.yaml
name: hello-world
version: "1.0"
description: A minimal example plugin
~/.hermes/plugins/hello-world/__init__.py
"""Minimal Hermes plugin — registers a tool and a hook."""
def register(ctx):
# --- Tool: hello_world ---
schema = {
"name": "hello_world",
"description": "Returns a friendly greeting for the given name.",
"parameters": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name to greet",
}
},
"required": ["name"],
},
}
def handle_hello(params):
name = params.get("name", "World")
return f"Hello, {name}! 👋 (from the hello-world plugin)"
ctx.register_tool("hello_world", schema, handle_hello)
# --- Hook: log every tool call ---
def on_tool_call(tool_name, params, result):
print(f"[hello-world] tool called: {tool_name}")
ctx.register_hook("post_tool_call", on_tool_call)
把这两个文件放到 ~/.hermes/plugins/hello-world/ 后重启 Hermes,模型就可以调用 hello_world,hook 也会在每次工具调用后输出一条日志。
默认情况下,项目本地插件 ./.hermes/plugins/ 是关闭的。只有在你信任该仓库时,才应通过 HERMES_ENABLE_PROJECT_PLUGINS=true 启用。
插件能做什么
| 能力 | 方式 |
|---|---|
| 添加工具 | ctx.register_tool(name, schema, handler) |
| 添加 hooks | ctx.register_hook("post_tool_call", callback) |
| 添加 slash 命令 | ctx.register_command(name, handler, description) |
| 添加 CLI 子命令 | ctx.register_cli_command(name, help, setup_fn, handler_fn) |
| 注入消息 | ctx.inject_message(content, role="user") |
| 附带数据文件 | Path(__file__).parent / "data" / "file.yaml" |
| 打包技能 | ctx.register_skill(name, path) |
| 用环境变量做门控 | 在 plugin.yaml 中写 requires_env: [API_KEY] |
| 通过 pip 分发 | [project.entry-points."hermes_agent.plugins"] |
插件发现来源
| 来源 | 路径 | 用途 |
|---|---|---|
| Bundled | <repo>/plugins/ | 随 Hermes 一起发布 |
| User | ~/.hermes/plugins/ | 个人插件 |
| Project | .hermes/plugins/ | 项目专用插件(需设置 HERMES_ENABLE_PROJECT_PLUGINS=true) |
| pip | hermes_agent.plugins entry_points | 可分发包 |
如果同名,后面的来源会覆盖前面的来源,因此用户插件可以替换同名 bundled 插件。
插件默认是 opt-in
无论是用户插件、bundled 插件还是 pip 插件,默认都不会自动加载。 发现系统会识别它们,因此它们会显示在 hermes plugins 与 /plugins 中,但只有当插件名被加入 ~/.hermes/config.yaml 的 plugins.enabled 时,才会真正加载。这可以防止 hooks 或工具在你未明确同意的情况下运行。
plugins:
enabled:
- my-tool-plugin
- disk-cleanup
disabled:
- noisy-plugin
切换状态有三种方式:
hermes plugins # interactive toggle (space to check/uncheck)
hermes plugins enable <name> # add to allow-list
hermes plugins disable <name> # remove from allow-list + add to disabled
执行 hermes plugins install owner/repo 后,系统会询问是否立刻启用。若用于脚本场景,可通过 --enable 或 --no-enable 跳过提示。
面向旧用户的迁移行为
当你升级到引入 opt-in 插件机制的 Hermes 版本时(配置模式 v21+),~/.hermes/plugins/ 中已存在且不在 plugins.disabled 里的用户插件,会自动被迁移到 plugins.enabled,以保持原有工作流不变。但 bundled 插件不会自动启用,仍需你手动选择。
可用 hooks
插件可以在以下生命周期节点注册回调。详细签名和示例见 Event Hooks page。
| Hook | 触发时机 |
|---|---|
pre_tool_call | 工具执行前 |
post_tool_call | 工具返回后 |
pre_llm_call | 每轮 LLM 循环前一次,可返回 {"context": "..."} 注入上下文 |
post_llm_call | 每轮 LLM 循环成功结束后 |
on_session_start | 新会话首次创建时 |
on_session_end | 每次 run_conversation 结束时 |
插件类型
Hermes 有三类插件:
| 类型 | 作用 | 选择方式 | 位置 |
|---|---|---|---|
| General plugins | 添加工具、hooks、slash 命令、CLI 命令 | 可多选 | ~/.hermes/plugins/ |
| Memory providers | 替换或增强内置记忆 | 单选 | plugins/memory/ |
| Context engines | 替换内置上下文压缩器 | 单选 | plugins/context_engine/ |
记忆大模型提供商(provider)和上下文引擎属于 provider plugins,同一时间每类只能启用一个;通用插件则可自由组合启用。
管理插件
hermes plugins # unified interactive UI
hermes plugins list # table: enabled / disabled / not enabled
hermes plugins install user/repo # install from Git, then prompt Enable? [y/N]
hermes plugins install user/repo --enable # install AND enable (no prompt)
hermes plugins install user/repo --no-enable # install but leave disabled (no prompt)
hermes plugins update my-plugin # pull latest
hermes plugins remove my-plugin # uninstall
hermes plugins enable my-plugin # add to allow-list
hermes plugins disable my-plugin # remove from allow-list + add to disabled
交互界面
直接运行 hermes plugins 会打开一个组合式交互界面:
Plugins
↑↓ navigate SPACE toggle ENTER configure/confirm ESC done
General Plugins
→ [✓] my-tool-plugin — Custom search tool
[ ] webhook-notifier — Event hooks
[ ] disk-cleanup — Auto-cleanup of ephemeral files [bundled]
Provider Plugins
Memory Provider ▸ honcho
Context Engine ▸ compressor
- General Plugins 区域:用 SPACE 切换;选中表示在
plugins.enabled中,未选中表示在plugins.disabled中 - Provider Plugins 区域:显示当前选中的 provider;按 ENTER 进入单选器
- bundled 插件会带有
[bundled]标签
provider plugin 的选择会保存到 config.yaml:
memory:
provider: "honcho"
context:
engine: "compressor"
enabled / disabled / neither 三种状态
插件有三种状态:
| 状态 | 含义 | 在 plugins.enabled? | 在 plugins.disabled? |
|---|---|---|---|
enabled | 下一次会话会加载 | Yes | No |
disabled | 被显式关闭,即使也在 enabled 中也不会加载 | irrelevant | Yes |
not enabled | 已被发现,但从未启用 | No | No |
新安装插件和 bundled 插件的默认状态都是 not enabled。hermes plugins list 会显式展示这三种状态,方便你区分“明确关闭”和“尚未启用”。
在运行中的会话里,/plugins 会显示当前已经加载的插件。
注入消息
插件可以通过 ctx.inject_message() 向当前对话注入消息:
ctx.inject_message("New data arrived from the webhook", role="user")
签名: ctx.inject_message(content: str, role: str = "user") -> bool
行为如下:
- 如果智能体 空闲,消息会排队作为下一轮输入,并触发新一轮会话
- 如果智能体 正在处理中,这条消息会像用户手动输入新消息一样中断当前流程
- 当
role不是"user"`` 时,内容会自动加上[role]` 前缀 - 如果当前没有 CLI 引用(例如在 gateway 模式),则返回
False
这使得远程控制、消息桥接或 webhook 接收器等插件,可以从外部源把消息送入当前对话。
inject_message 仅在 CLI 模式下可用。在 gateway 模式中由于没有 CLI 引用,该方法会返回 False。
完整细节见 full guide。