Web Dashboard 与 Kanban 看板
本教程共 25 篇 · 第 23 篇 · 更新于 2026-07-26 · 约 18 分钟阅读
23. Web Dashboard 与 Kanban 看板
本节目标:掌握 Hermes Agent 的可视化管理能力—用浏览器面板替代手敲命令,用 Kanban 看板协调多个 Agent 协作,用持久化目标让 Agent 自己跑完,再了解人格、皮肤、宠物和插件这些个性化与扩展手段。
前面章节讲的大多是命令行操作。但不是所有人都喜欢敲命令—有时候你想在浏览器里点几下就改完配置,或者一眼看到所有会话的 Token 消耗。这一章就来讲 Hermes Agent 的可视化管理层,以及几个让 Agent 更好用、更好玩的功能。
Web Dashboard:浏览器里的管理面板
一行命令启动
Web Dashboard 是一个浏览器端的管理界面。不用编辑 YAML 文件,不用记 CLI 命令,点点鼠标就能管理配置、API Key、会话、日志和定时任务。
hermes dashboard
运行后自动打开 http://127.0.0.1:9119。整个面板跑在你本地机器上,数据不离开 localhost。
常用启动参数:
# 自定义端口
hermes dashboard --port 8080
# 不自动打开浏览器
hermes dashboard --no-open
# 绑定到所有网卡(危险!共享网络下会暴露 API Key)
hermes dashboard --host 0.0.0.0
Warning
--host 0.0.0.0会把面板暴露到局域网,任何能访问你 IP 的人都能看到 API Key。只有在配了防火墙和强密码认证后才用这个选项。
安装依赖
默认安装不包含 HTTP 服务和 PTY 辅助库,需要额外装两个可选依赖:
cd ~/.hermes/hermes-agent && uv pip install -e ".[web,pty]"
web拉入 FastAPI / Uvicorn(面板本身需要)pty拉入 ptyprocess(Chat 标签页内嵌终端需要,仅限 POSIX)
图省事可以直接装全部:
cd ~/.hermes/hermes-agent && uv pip install -e ".[all]"
面板有哪些页面
Dashboard 是机器级管理面板—一个服务管理这台机器上所有 Profile。侧边栏有 Profile 切换器,选择哪个 Profile,配置、API Key、技能、MCP、模型和聊天页就跟着切换。
主要页面一览:
| 页面 | 干什么 |
|---|---|
| Status | 实时总览:Agent 版本、网关状态、活跃会话数、最近 20 条会话 |
| Chat | 浏览器里内嵌完整 TUI,斜杠命令、模型选择器、工具卡片全都能用 |
| Config | 表单编辑 config.yaml,150+ 字段自动发现,下拉框 + 开关 |
| API Keys | 管理 .env 里的密钥,按 LLM / 工具 / 消息平台分组,带注册链接 |
| Sessions | 浏览所有会话,全文搜索,展开看完整消息历史,导出 JSON |
| Logs | 查看 agent / gateway / errors 日志,按级别和组件过滤,实时刷新 |
| Analytics | 用量分析:Token 消耗、缓存命中率、成本估算,按天和模型拆分 |
| Cron | 创建和管理定时任务,设置 cron 表达式和投递目标 |
| Profiles | 创建和管理 Profile,设置模型、技能、SOUL.md |
| Skills | 浏览、搜索、开关技能,从 Hub 安装新技能 |
| MCP | 管理 MCP 服务器,添加 / 测试 / 启用 / 禁用 |
| Webhooks | 管理 Webhook 订阅,创建后拿到路由 URL 和 HMAC 密钥 |
| Pairing | 审批和撤销消息平台用户配对 |
| Channels | 连接消息平台,跟 hermes setup gateway 完全对等 |
| Kanban | 看板管理(后面重点讲) |
TipConfig 页面改完点 Save 就写入
config.yaml,下一个会话或网关重启后生效。跟hermes config set改的是同一个文件,不会冲突。
多 Profile 管理
一个 Dashboard 服务管所有 Profile。侧边栏的 Profile 切换器决定当前管理哪个 Profile,选中非默认 Profile 时顶部会显示橙色横幅,避免你改错地方。
选择状态保存在 URL 里(?profile=<name>),所以深链接像 http://127.0.0.1:9119/skills?profile=worker 可以直接打开指定 Profile 的技能页。
从 Profile 别名启动也会路由到机器级面板:
worker dashboard
# 面板已运行:打开浏览器并预选 worker
# 面板没运行:启动机器级面板并预选 worker
如果你想让某个 Profile 跑独立的面板服务(比如不同 Profile 暴露不同认证),加 --isolated:
worker dashboard --isolated
Chat 标签页:浏览器里跑 TUI
Chat 标签页把完整的 Hermes TUI 嵌进了浏览器。你在终端里能做的事—斜杠命令、模型选择器、工具调用卡片、Markdown 流式渲染、审批提示—在这里全都能做。
工作原理:
/api/pty打开一个 WebSocket(用面板的 session token 认证)- 服务器在伪终端里启动
hermes --tui - 键盘输入传到 PTY,ANSI 输出流回浏览器
- xterm.js 的 WebGL 渲染器把每个字符画到整数像素网格上
NoteChat 标签页需要 POSIX 内核(Linux、macOS 或 WSL2)。原生 Windows 安装下,面板其他功能正常,但 Chat 标签页会提示你用 WSL2。
右侧有个会话切换栏,可以不离开页面就切换不同会话。从 Sessions 标签页点播放图标(▶)也能跳到 Chat 页恢复指定会话。
远程后端连接
Hermes Desktop 默认启动自己的本地后端,但也能连远程机器上跑的 Dashboard。这在你想用家里 GPU 服务器跑模型、但桌面端开在笔记本上时很有用。
设置步骤:
- 在远程机器上启动 Dashboard,绑定到非本地地址
- 设置用户名密码认证
- 在 Desktop 的 Settings -> Gateway -> Remote gateway 填入远程 URL
远程机器的 systemd 配置示例:
[Service]
EnvironmentFile=%h/.hermes/.env
ExecStart=/path/to/venv/bin/python -m hermes_cli.main dashboard \
--host 0.0.0.0 --port 9119 --no-open
.env 文件里放认证信息:
HERMES_DASHBOARD_BASIC_AUTH_USERNAME=admin
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD=choose-a-strong-password
HERMES_DASHBOARD_BASIC_AUTH_SECRET=<32+ 随机字节; openssl rand -base64 32>
验证认证是否生效:
curl -s http://VM_IP:9119/api/status | jq '.auth_required, .auth_providers'
# true
# ["basic"]
auth_required: true 且列表里有 "basic",说明 Desktop 的登录流程能正常工作。
Kanban:多 Agent 任务看板
什么是 Kanban 看板
Kanban 是一个持久化的任务看板,让多个 Profile 协作完成工作。每个任务是 SQLite 数据库里的一行,每次交接都是一行任何 Profile 都能读写的记录,每个工作者是独立的操作系统进程。
跟 delegate_task 的区别:
delegate_task | Kanban | |
|---|---|---|
| 形态 | RPC 调用(fork -> join) | 持久化消息队列 + 状态机 |
| 父级 | 阻塞等子 Agent 返回 | 创建后即放手 |
| 子级身份 | 匿名子 Agent | 有名字的 Profile,记忆持久 |
| 可恢复 | 不行,失败就是失败 | 阻塞 -> 解除 -> 重跑;崩溃 -> 回收 |
| 人工介入 | 不支持 | 随时评论 / 解除阻塞 |
| 审计追踪 | 上下文压缩后丢失 | SQLite 里的行永久保存 |
一句话区分:delegate_task 是函数调用,Kanban 是工作队列。
Tip用
delegate_task的场景:父 Agent 需要一个简短推理结果后继续,不涉及人工,结果回到父级上下文。用 Kanban 的场景:工作跨 Agent 边界、需要扛过重启、可能需要人工输入、可能被不同角色接手、或者需要事后可查。
核心概念
- Board(看板):一个独立的任务队列,有自己的 SQLite 数据库。单项目用默认
default看板就行,多项目可以一项目一看板 - Task(任务):一行记录,有标题、正文、指派人、状态(
triage | todo | ready | running | blocked | done | archived) - Link(链接):父 -> 子依赖关系。调度器在所有父任务完成后自动把子任务从
todo提升到ready - Comment(评论):Agent 之间的通信协议。工作者被启动时会读完整评论线程作为上下文
- Workspace(工作区):工作者操作的目录,有三种:
scratch(默认):临时目录,任务完成后删除(声明为产物的文件会被保留)dir:<path>:已有共享目录,完成后保留worktree:git worktree,适合编码任务,完成后保留
- Dispatcher(调度器):长驻循环,每 N 秒(默认 60)扫描一次:回收过期声明、回收崩溃工作者、提升就绪任务、原子声明、启动指派的 Profile
- Tenant(租户):看板内的可选命名空间,一个专家集群可以服务多个业务
两个入口
看板有两个入口,背后是同一个 SQLite 数据库:
- Agent 通过
kanban_*工具集驱动:kanban_show、kanban_list、kanban_complete、kanban_block、kanban_heartbeat、kanban_comment、kanban_create、kanban_link、kanban_unblock。模型直接调用工具,不走 CLI - 你通过 CLI / 斜杠命令 / Dashboard 驱动:
hermes kanban ...或/kanban ...,给人和自动化脚本用
快速上手
# 1. 初始化看板(可选,第一次用任何 kanban 命令会自动初始化)
hermes kanban init
# 2. 启动网关(内嵌调度器)
hermes gateway start
# 3. 创建任务
hermes kanban create "研究 AI 融资格局" --assignee researcher
# 4. 实时查看活动
hermes kanban watch
# 5. 查看看板
hermes kanban list
hermes kanban stats
调度器默认跑在网关进程里,不用额外装服务。网关在跑,就绪任务下一个 tick(默认 60 秒)就会被捡起来。
配置项:
# config.yaml
kanban:
dispatch_in_gateway: true # 默认值
dispatch_interval_seconds: 60 # 默认值
Warning不要同时跑网关内嵌调度器和独立的
hermes kanban daemon,两个调度器抢同一个kanban.db会导致声明竞争。独立 daemon 已废弃,用网关就行。
看板页面
Dashboard 里的 Kanban 标签页有六列,从左到右:
- Triage:原始想法。默认调度器会自动跑分解器(decomposer),把大任务拆成子任务分发给最合适的专家 Profile
- Todo:已创建但等依赖,或未指派
- Ready:已指派,等调度器声明
- In Progress:工作者正在跑。开启「Lanes by profile」后按指派人分组
- Blocked:工作者要人工输入,或断路器跳闸
- Done:已完成
顶部有搜索、租户、指派人过滤器,还有 Lanes by profile 开关和 Nudge dispatcher 按钮(立即跑一次调度,不等下一个间隔)。
任务依赖与自动提升
任务之间可以建父子依赖:
SCHEMA=$(hermes kanban create "设计认证数据库 schema" \
--assignee backend-dev --tenant auth-project --priority 2 \
--body "设计用户/会话/令牌表结构。" \
--json | jq -r .id)
API=$(hermes kanban create "实现认证 API 端点" \
--assignee backend-dev --tenant auth-project --priority 2 \
--parent $SCHEMA \
--body "POST /register, POST /login, POST /refresh, POST /logout." \
--json | jq -r .id)
hermes kanban create "写认证集成测试" \
--assignee qa-dev --tenant auth-project --priority 2 \
--parent $API \
--body "覆盖正常路径、密码错误、令牌过期、并发刷新。"
因为 API 依赖 Schema,测试依赖 API,只有 Schema 开始时是 ready。其他两个停在 todo,等父任务完成后自动提升。这叫依赖提升引擎—没有 API 就不会有人去写测试。
工作者的工具调用循环
调度器启动工作者后,工作者模型做的第一件事是调用 kanban_show() 读自己的任务。然后干活,最后调 kanban_complete() 或 kanban_block() 结束。
# 工作者的工具调用(不是你敲的命令)
kanban_show()
# -> 返回标题、正文、工作上下文、父任务、历史尝试、评论
# (工作者读上下文,用终端/文件工具设计 schema、写迁移、跑检查、提交)
kanban_heartbeat(note="schema 已起草,正在写迁移")
kanban_complete(
summary="users(id, email, pw_hash), sessions(id, user_id, jti, expires_at)",
metadata={
"changed_files": ["migrations/001_users.sql", "migrations/002_sessions.sql"],
"decisions": ["bcrypt 哈希", "JWT 会话令牌", "7 天刷新, 15 分钟访问"],
},
)
kanban_show 默认读 $HERMES_KANBAN_TASK,工作者不需要知道自己的 ID。kanban_complete 把摘要和元数据写到当前 task_runs 行,关闭这次运行,把任务状态翻到 done—一步原子操作。
阻塞与重试
Kanban 真正比 TODO 列表强的地方在这里。一个工程师实现功能,审查者打回,工程师改了再提交,审查者通过。
工作者发现问题后主动阻塞:
# 工作者的工具调用
kanban_block(
reason="审查:密码强度检查缺失,重置链接不是一次性的(30 分钟内可重放)",
)
# -> 任务转到 blocked,本次运行以 outcome='blocked' 结束
你从 Dashboard 点「Unblock」或命令行解除:
hermes kanban unblock $IMPL
# 或聊天里:/kanban unblock $IMPL
调度器把任务提升回 ready,下一个 tick 重新启动工作者。这是同一个任务的新一次运行。工作者调 kanban_show() 时会看到上次阻塞的原因,知道该修什么,不用从头读整个需求。
断路器与崩溃恢复
真实环境里工作者会失败:缺凭据、OOM 被杀、网络抖动。调度器有两道防线:
断路器:连续 N 次启动失败后自动阻塞(默认 kanban.failure_limit: 2)。防止看板在永远跑不起来的任务上空转。
# 创建时指定最大重试次数
hermes kanban create "部署到预发布(缺凭据)" \
--assignee deploy-bot --tenant ops \
--max-retries 3
三次连续失败后,任务转到 blocked,outcome 是 gave_up。不再重试,等人来解除。
崩溃检测:工作者的 PID 消失但 TTL 还没到期,调度器会检测到并回收任务,递增失败计数器。但只有 PID 真的死了才回收—一个活着的工作者(比如模型在一次无工具的 LLM 调用里卡了 20 分钟)会得到声明延长,不会被杀。
多看板管理
一个安装可以有多个看板,每个项目一个:
# 查看磁盘上的看板
hermes kanban boards list
# 创建新看板
hermes kanban boards create atm10-server \
--name "ATM10 Server" \
--description "Minecraft 模组服务器运维" \
--icon 🎮 \
--switch
# 不切换看板直接操作
hermes kanban --board atm10-server list
hermes kanban --board atm10-server create "重启 ATM 服务器" --assignee ops
# 切换当前看板
hermes kanban boards switch atm10-server
看板间隔离是绝对的:独立 SQLite 数据库、独立工作区和日志目录、工作者只能看到自己看板的任务。跨看板建链接不允许。
幂等创建(给自动化用)
Webhook 或 cron 触发任务时,不希望重复创建。用 --idempotency-key:
# 第一次调用创建任务。相同 key 的后续调用返回已有任务 ID
hermes kanban create "每晚运维巡检" \
--assignee ops-reviewer \
--idempotency-key nightly-ops-$(date +%Y-%m-%d)
Worker Lanes:工作者通道
Worker Lane 是调度器能路由任务的进程类别。每个 Lane 有身份(指派人字符串)、启动机制和生命周期终止契约。
默认 Lane:指派人就是 Profile 名,调度器跑 hermes -p <assignee> chat -q <prompt>,工作者拿到 KANBAN_GUIDANCE 系统提示注入,用 kanban_* 工具结束运行。
编排者 Lane:一种特殊的 Profile Lane—编排者的工具集包含 kanban 但排除 terminal / file / code / web。它的活是把高层目标分解成子任务,然后退后。
每次声明必须以下面三种方式之一结束:
kanban_complete(summary=..., metadata=...):任务成功,状态翻到donekanban_block(reason=...):任务等人工输入,状态翻到blocked- 工作者进程退出但没调工具:内核回收,标记
crashed(PID 死了)或gave_up(断路器跳闸)或timed_out(超时)
Note对于改代码的任务,惯例是用
reason前缀review-required:来阻塞(而不是直接 complete),这样 Dashboard 会显示该任务待审查。结构化元数据(改了哪些文件、跑了多少测试、PR 链接)放到kanban_comment里。
持久化目标:/goal 循环
让 Agent 自己跑完
/goal 给 Hermes 一个跨轮次存活的目标。每轮结束后,一个轻量级评判模型检查目标是否达成。没达成就自动喂一个继续提示到同一会话,直到目标完成、你暂停或预算用完。
灵感来自 Codex CLI 的 /goal(作者 Eric Traut, OpenAI),核心思路是让目标跨轮次存活、不达目的不停。
适合用 /goal 的场景:
- “修掉 src/ 里所有 lint 错误,验证 ruff check 通过”
- “把 repo Y 的 feature X 移植过来,含测试,CI 变绿”
- “调查会话 ID 在压缩时漂移的原因,写份报告”
如果你本来要说三次”继续”,那就该用 /goal。
快速上手
/goal 修掉 tests/hermes_cli/ 里所有失败的测试,确保 scripts/run_tests.sh 对该目录通过
你会看到:
- 目标已设置:
⊙ Goal set (20-turn budget): <你的目标> - 第 1 轮运行:Hermes 开始干活
- 评判运行:评判模型判定
done或continue - 循环触发:如果
continue,看到↻ Continuing toward goal (1/20): <评判理由> - 终止:最终看到
✓ Goal achieved: <理由>或⏸ Goal paused - N/20 turns used
常用命令
| 命令 | 作用 |
|---|---|
/goal <文本> | 设置(或替换)目标,立即开始第一轮 |
/goal draft <文本> | 从一句话起草结构化完成契约,然后设置 |
/goal show | 打印当前目标的完成契约 |
/goal status | 显示当前目标和状态 |
/goal pause | 停止自动继续,不清除目标 |
/goal resume | 恢复循环(轮次计数归零) |
/goal clear | 彻底删除目标 |
/goal wait <pid> [reason] | 挂起循环等后台进程,退出后自动恢复 |
/subgoal <文本> | 追加额外验收标准,不重置循环 |
完成契约
模糊的目标会导致模糊的判定。一个完成契约有五个可选字段:
| 字段 | 含义 |
|---|---|
outcome | 完成时必须为真的最终状态 |
verification | 证明结果的具体测试 / 命令 / 产物 |
constraints | 不能改或不能退化的东西 |
boundaries | 哪些文件 / 目录 / 工具在范围内 |
stop_when | 什么条件下 Hermes 该停下来问你 |
让 Hermes 帮你起草(推荐):
/goal draft 把认证服务从 session cookies 迁移到 JWT
或者内联写:
/goal 把认证迁移到 JWT
verify: pytest tests/auth 通过
constraints: /login 响应结构不变
boundaries: 只动 services/auth 及其测试
stop when: 需要 DB schema 迁移
后台进程自动等待
有些目标卡在耗时几分钟的后台进程上(CI、构建、部署)。目标循环会自动检测:评判模型看到 Agent 的活跃后台进程,返回 wait 而不是 continue,循环就挂起,等进程结束后再恢复。
你不用敲任何东西—这是评判模型根据进程上下文自己决定的。手动覆盖用 /goal wait <pid> 和 /goal unwait。
人格与 SOUL.md
SOUL.md 是什么
SOUL.md 是 Agent 的主要身份—系统提示里的第一个位置,定义了 Agent 是谁。它放在 ~/.hermes/SOUL.md,更准确地说是当前实例的 HERMES_HOME/SOUL.md。
关键行为:
- Hermes 启动时如果不存在会自动创建一个默认的
- 已有的用户 SOUL.md 永远不会被覆盖
- 只从
HERMES_HOME加载,不看当前工作目录(避免在不同项目间人格意外改变) - 空文件或加载失败会回退到内置默认身份
- 内容经过提示注入扫描和截断后原样注入
NoteSOUL.md 管的是身份和语气(人格层面),AGENTS.md 管的是项目约定(架构、编码规范、文件路径)。别搞混了。
编辑 SOUL.md
# 大多数用户
~/.hermes/SOUL.md
# 自定义 HERMES_HOME
$HERMES_HOME/SOUL.md
好的 SOUL.md 内容示例:
# Personality
你是一个务实的资深工程师,品味过硬。
你追求真实、清晰和有用,不搞客套。
## Style
- 直接但不冷漠
- 重内容轻废话
- 觉得方案有问题就直说
- 不确定就坦白说
- 除非需要深入,否则解释尽量精简
## What to avoid
- 阿谀奉承
- 炒作用语
- 用户框架有问题还跟着走
- 过度解释显而易见的东西
/personality 预设
除了 SOUL.md,还有 /personality 命令提供会话级的系统提示叠加。内置几种预设人格,也可以自定义。SOUL.md 是持久身份,/personality 是会话级覆盖。
皮肤主题
皮肤控制 CLI 的视觉呈现:横幅颜色、转圈表情、响应框标签、品牌文字、工具活动前缀。
注意区分两个概念:
- Personality 改的是 Agent 的语气和用词
- Skin 改的是 CLI 的外观
切换皮肤
/skin # 显示当前皮肤并列出可用皮肤
/skin ares # 切到内置皮肤
/skin mytheme # 切到自定义皮肤 ~/.hermes/skins/mytheme.yaml
或在配置文件里设默认:
display:
skin: default
内置皮肤
| 皮肤 | 风格 | 特点 |
|---|---|---|
default | 经典金色 | 暖金边框,米色文字,可爱转圈表情 |
ares | 战神深红 | 深红边框配铜色点缀,攻击性动词(“forging”、“marching”) |
mono | 纯灰度 | 全灰无色,适合录屏 |
slate | 冷蓝开发者风 | 皇家蓝边框,冷静专业 |
daylight | 浅色主题 | 深色文字配蓝边框,适合亮色终端 |
warm-lightmode | 暖棕浅色 | 羊皮纸色调,适合亮色终端 |
poseidon | 海神深蓝 | 深蓝到海绿渐变,海洋主题转圈(“charting currents”) |
sisyphus | 西西弗斯灰度 | 极简灰白,巨石主题(“pushing uphill”) |
charizard | 火山橙红 | 烧橙到余烬渐变,火焰主题 |
自定义皮肤
在 ~/.hermes/skins/ 下放 YAML 文件,缺失的键自动从 default 继承:
# ~/.hermes/skins/mytheme.yaml
name: mytheme
description: 我的自定义主题
colors:
banner_border: "#CD7F32"
banner_title: "#FFD700"
ui_accent: "#FFBF00"
ui_ok: "#4caf50"
ui_error: "#ef5350"
response_border: "#FFD700"
spinner:
waiting_faces: ["(⚔)", "(⛨)", "(▲)"]
thinking_verbs: ["forging", "plotting", "hammering plans"]
branding:
agent_name: "Hermes Agent"
welcome: "Welcome! Type /help for commands."
宠物精灵
装饰性的小伙伴
Pet 是一个小型动画吉祥物,在 CLI、TUI 和桌面端里对 Agent 的活动做出反应(空闲、跑工具、思考、完成、失败)。
宠物来自公开的 petdex 画廊。纯装饰,不影响 Token 消耗、提示缓存或 Agent 行为。默认关闭,装了选了才会出现。
六种动画状态
| Agent 活动 | 宠物状态 |
|---|---|
| 工具/轮次失败 | failed |
| 计划完成(所有 todo 做完) | jump(庆祝) |
| 轮次干净完成 | wave |
| 工具执行中 | run |
| 模型思考/读取中 | review |
| 等你回应(审批/澄清提示打开) | waiting |
| 没事发生 | idle |
命令
# 浏览画廊
hermes pets list
hermes pets list cat
# 一步安装并激活
hermes pets install boba --select
# 预览动画(Ctrl+C 停止)
hermes pets show
# 检查设置
hermes pets doctor
会话内用斜杠命令:
/pet:开关宠物/pet list:浏览画廊/pet scale 0.5:调整大小/pet <slug>:领养指定宠物/pet off:关闭
生成宠物
除了装现成的,还能用 /hatch <描述> 让 Hermes 生成全新宠物。两步流程:
- 基础草稿:生成几个”这宠物该长什么样”的廉价变体,你选一个
- 孵化:用选中的基础图作为参考,为每个状态生成一行动画,切成帧打包成标准 spritesheet
生成需要支持参考图的图像后端:Nous Portal、OpenRouter、OpenAI(gpt-image-2)、Krea。
插件系统
给 Hermes 加自定义能力
插件系统让你不改核心代码就能加自定义工具、钩子和集成。把一个目录丢进 ~/.hermes/plugins/,里面有 plugin.yaml 和 Python 代码,重启 Hermes 你的工具就出现在内置工具旁边。
插件目录结构:
~/.hermes/plugins/my-plugin/
├── plugin.yaml # 清单
├── __init__.py # register() - 把 schema 接到 handler
├── schemas.py # 工具 schema(模型看到的)
└── tools.py # 工具 handler(被调用时跑的)
最小示例
~/.hermes/plugins/hello-world/plugin.yaml:
name: hello-world
version: "1.0"
description: A minimal example plugin
~/.hermes/plugins/hello-world/__init__.py:
"""最小 Hermes 插件 - 注册一个工具和一个钩子。"""
import json
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, **kwargs):
del kwargs
name = params.get("name", "World")
return json.dumps({"success": True, "greeting": f"Hello, {name}!"})
ctx.register_tool(
name="hello_world",
toolset="hello_world",
schema=schema,
handler=handle_hello,
description="Return a friendly greeting for the given name.",
)
# --- 钩子:记录每次工具调用 ---
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 了。
插件能做什么
| 能力 | 怎么做 |
|---|---|
| 加工具 | ctx.register_tool(name=..., toolset=..., schema=..., handler=...) |
| 加钩子 | ctx.register_hook("post_tool_call", callback) |
| 加斜杠命令 | ctx.register_command(name, handler, description) |
| 加 CLI 命令 | ctx.register_cli_command(name, help, setup_fn, handler_fn) |
| 注入消息 | ctx.inject_message(content, role="user") |
| 打包技能 | ctx.register_skill(name, path) |
| 环境变量门控 | requires_env: [API_KEY] 写在 plugin.yaml 里 |
| pip 分发 | [project.entry-points."hermes_agent.plugins"] |
| 注册消息平台 | ctx.register_platform(name, label, adapter_factory, ...) |
| 注册图像生成后端 | ctx.register_image_gen_provider(provider) |
| 注册视频生成后端 | ctx.register_video_gen_provider(provider) |
| 注册记忆后端 | 继承 MemoryProvider,放 plugins/memory/<name>/ |
| 注册模型提供商 | register_provider(ProviderProfile(...)),放 plugins/model-providers/<name>/ |
| 跑宿主持有的 LLM 调用 | ctx.llm.complete(...) / ctx.llm.complete_structured(...) |
插件发现位置
| 来源 | 路径 | 用途 |
|---|---|---|
| 内置 | <repo>/plugins/ | 随 Hermes 发布 |
| 用户 | ~/.hermes/plugins/ | 个人插件 |
| 项目 | .hermes/plugins/ | 项目专属(需 HERMES_ENABLE_PROJECT_PLUGINS=true) |
| pip | hermes_agent.plugins entry_points | 分发的包 |
| Nix | services.hermes-agent.extraPlugins | NixOS 声明式安装 |
插件默认不启用
通用插件和用户安装的后端默认禁用—发现得到(在 hermes plugins 里能看到),但不加到 plugins.enabled 不会加载任何钩子或工具。这防止第三方代码未经你同意就运行。
plugins:
enabled:
- my-tool-plugin
- disk-cleanup
disabled: # 可选拒绝列表 - 同时出现在两个列表里时优先拒绝
- noisy-plugin
三种切换方式:
hermes plugins # 交互式开关(空格勾选)
hermes plugins enable <name> # 加入允许列表
hermes plugins disable <name> # 移出允许列表 + 加入拒绝列表
Note内置的平台插件(IRC、Teams 等)和后端插件(图像生成等)不受
plugins.enabled控制—它们是 Hermes 基础设施的一部分,自动加载,通过各自的配置项(如gateway.platforms.<name>.enabled)控制是否启用。只有第三方通用插件才需要显式同意。
可用钩子
插件可以注册这些生命周期事件的回调:
| 钩子 | 触发时机 |
|---|---|
pre_tool_call | 任何工具执行前 |
post_tool_call | 任何工具返回后 |
pre_llm_call | 每轮一次,LLM 循环前—可返回 {"context": "..."} 注入上下文 |
post_llm_call | 每轮一次,LLM 循环后(仅成功轮次) |
on_session_start | 新会话创建(仅第一轮) |
on_session_end | 每次 run_conversation 结束 + CLI 退出 |
on_session_finalize | CLI/网关销毁活跃会话时 |
这一章覆盖了 Hermes Agent 的可视化和个性化层。Web Dashboard 让你不用敲命令就能管好一切,Kanban 让多个 Agent 像团队一样协作,/goal 让 Agent 自己跑完长任务,SOUL.md / 皮肤 / 宠物让你的 Agent 有自己的个性,插件系统则把扩展能力交到你手里。下一章讲安全—怎么管好密钥和凭据,不让敏感信息泄露。