插件
Hermes 有一个插件系统,用于在不修改核心代码的情况下添加自定义工具、钩子和集成。
→ 构建 Hermes 插件 —— 带有完整工作示例的分步指南。
快速概览
将目录放入 ~/.hermes/plugins/,包含 plugin.yaml 和 Python 代码:
~/.hermes/plugins/my-plugin/
├── plugin.yaml # 清单
├── __init__.py # register() —— 将模式连接到处理程序
├── schemas.py # 工具模式(LLM 看到的内容)
└── tools.py # 工具处理程序(调用时运行的内容)启动 Hermes —— 您的工具与内置工具一起出现。模型可以立即调用它们。
最小工作示例
这里是一个完整的插件,添加了一个 hello_world 工具并通过钩子记录每个工具调用。
~/.hermes/plugins/hello-world/plugin.yaml
name: hello-world
version: "1.0"
description: A minimal example plugin~/.hermes/plugins/hello-world/__init__.py
"""最小 Hermes 插件 —— 注册一个工具和一个钩子。"""
def register(ctx):
# --- 工具: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)
# --- 钩子:记录每个工具调用 ---
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。钩子在每次工具调用后打印一行日志。
./.hermes/plugins/ 下的项目本地插件默认被禁用。仅对受信任的仓库通过设置 HERMES_ENABLE_PROJECT_PLUGINS=true 在启动 Hermes 之前启用它们。
插件可以做什么
| 能力 | 方式 |
|---|---|
| 添加工具 | ctx.register_tool(name, schema, handler) |
| 添加钩子 | ctx.register_hook("post_tool_call", callback) |
| 添加 CLI 命令 | ctx.register_cli_command(name, help, setup_fn, handler_fn) —— 添加 hermes <plugin> <subcommand> |
| 注入消息 | ctx.inject_message(content, role="user") —— 请参阅注入消息 |
| 运送数据文件 | Path(__file__).parent / "data" / "file.yaml" |
| 捆绑技能 | 在加载时将 skill.md 复制到 ~/.hermes/skills/ |
| 基于环境变量控制 | plugin.yaml 中的 requires_env: [API_KEY] —— 在 hermes plugins install 期间提示 |
| 通过 pip 分发 | [project.entry-points."hermes_agent.plugins"] |
插件发现
| 来源 | 路径 | 使用场景 |
|---|---|---|
| 用户 | ~/.hermes/plugins/ | 个人插件 |
| 项目 | .hermes/plugins/ | 项目特定插件(需要 HERMES_ENABLE_PROJECT_PLUGINS=true) |
| pip | hermes_agent.plugins entry_points | 分布式包 |
可用钩子
插件可以为这些生命周期事件注册回调。有关完整详细信息、回调签名和示例,请参阅**事件钩子页面**。
| 钩子 | 触发时机 |
|---|---|
pre_tool_call | 任何工具执行之前 |
post_tool_call | 任何工具返回之后 |
pre_llm_call | 每轮一次,在 LLM 循环之前 —— 可以返回 {"context": "..."} 以将上下文注入用户消息 |
post_llm_call | 每轮一次,在 LLM 循环之后(仅成功轮次) |
on_session_start | 新会话创建(仅第一轮) |
on_session_end | 每次 run_conversation 调用结束 + CLI 退出处理程序 |
插件类型
Hermes 有三种插件:
| 类型 | 作用 | 选择 | 位置 |
|---|---|---|---|
| 通用插件 | 添加工具、钩子、CLI 命令 | 多选(启用/禁用) | ~/.hermes/plugins/ |
| 记忆提供商 | 替换或增强内置记忆 | 单选(一个激活) | plugins/memory/ |
| 上下文引擎 | 替换内置上下文压缩器 | 单选(一个激活) | plugins/context_engine/ |
记忆提供商和上下文引擎是提供商插件 —— 每种类型一次只能激活一个。通用插件可以以任何组合启用。
管理插件
hermes plugins # 统一交互式 UI
hermes plugins list # 带启用/禁用状态的表格视图
hermes plugins install user/repo # 从 Git 安装
hermes plugins update my-plugin # 拉取最新
hermes plugins remove my-plugin # 卸载
hermes plugins enable my-plugin # 重新启用已禁用插件
hermes plugins disable my-plugin # 禁用而不移除交互式 UI
运行不带参数的 hermes plugins 会打开一个复合交互屏幕:
Plugins
↑↓ navigate SPACE toggle ENTER configure/confirm ESC done
General Plugins
→ [✓] my-tool-plugin — Custom search tool
[ ] webhook-notifier — Event hooks
Provider Plugins
Memory Provider ▸ honcho
Context Engine ▸ compressor- 通用插件部分 —— 复选框,用 SPACE 切换
- 提供商插件部分 —— 显示当前选择。按 ENTER 进入单选选择器,您可以在其中选择一个激活的提供商。
提供商插件选择保存到 config.yaml:
memory:
provider: "honcho" # 空字符串 = 仅内置
context:
engine: "compressor" # 默认内置压缩器禁用通用插件
禁用的插件保持安装但在加载期间被跳过。禁用列表存储在 config.yaml 中的 plugins.disabled 下:
plugins:
disabled:
- my-noisy-plugin在运行会话中,/plugins 显示当前加载了哪些插件。
注入消息
插件可以使用 ctx.inject_message() 将消息注入活动对话:
ctx.inject_message("New data arrived from the webhook", role="user")签名: ctx.inject_message(content: str, role: str = "user") -> bool
工作原理:
- 如果 Agent 空闲(等待用户输入),消息将作为下一个输入排队并开始新轮次。
- 如果 Agent 轮次中( actively 运行),消息会中断当前操作 —— 与用户键入新消息并按 Enter 相同。
- 对于非
"user"角色,内容前缀为[role](例如[system] ...)。 - 如果消息成功排队返回
True,如果没有 CLI 引用可用(例如在网关模式下)返回False。
这使远程控制查看器、消息桥或 webhook 接收器等插件能够从外部来源将消息输入对话。
NOTE
inject_message 仅在 CLI 模式下可用。在网关模式下,没有 CLI 引用,该方法返回 False。