Hermes Agent 飞书 Bot 部署经验总结
记录在 Ubuntu 24.04 虚拟机上从零部署 Hermes Agent(NousResearch/hermes-agent),
接入智谱 bigmodel 作为 LLM 后端,并打通飞书 WebSocket 双向消息的完整流程与踩坑点。
时间:2026-07-05
0. 准备清单
| 项目 | 说明 |
|---|---|
| 宿主机 | Windows 11 + PowerShell 5.1 |
| 虚拟机 | Ubuntu 24.04.3 LTS,VMWare Workstation,1 个 NAT 网络 |
| VM IP | 192.168.111.0/24 网段(按需替换) |
| VM 用户 | 普通用户 vmuser(sudo 组)+ root(密码登录 + SSH key) |
| 工具链 | paramiko(Windows 端 SSH)、lark-oapi(飞书 SDK,hermes 依赖)、Python 3.12 |
| 飞书账号 | 已创建企业自建应用,开启了机器人能力,获得 App ID / App Secret |
| LLM 凭据 | 智谱 bigmodel GLM_API_KEY(实名认证后免费档可用) |
1. 虚拟机初始化
1.1 SSH key + root 登录
# 宿主机生成 ed25519 key
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
通过 paramiko 远程执行(避免在 VM 控制台操作):
# 关键步骤(伪代码,按顺序)
# 1) 改 root 密码(unattended)
echo "root:NEW_ROOT_PW" | chpasswd
# 2) 写 root 授权 key
mkdir -p /root/.ssh && chmod 700 /root/.ssh
cat > /root/.ssh/authorized_keys <<< "ssh-ed25519 AAAA... user@host"
chmod 600 /root/.ssh/authorized_keys
# 3) 改 sshd 配置
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
sed -i 's/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sshd -t && systemctl restart ssh
坑:Ubuntu 24 默认锁 root 密码登录;/etc/pam.d/login 不引用 pam_securetty,所以 securetty 改不改都无所谓。GDM 登录界面默认隐藏 UID=0 用户,要登录 root 必须点 “未列出?” 手动输入。
1.2 国内镜像源
# APT
cat > /etc/apt/sources.list.d/aliyun.list <<EOF
deb https://mirrors.aliyun.com/ubuntu noble main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu noble-security main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu noble-updates main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu noble-backports main restricted universe multiverse
EOF
apt update # 52MB, 7s
# pip
mkdir -p ~/.pip
cat > ~/.pip/pip.conf <<EOF
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
timeout = 120
trusted-host = pypi.tuna.tsinghua.edu.cn
[install]
trusted-host = pypi.tuna.tsinghua.edu.cn
EOF
2. 安装 Hermes Agent
2.1 下载与定制安装脚本
# 装基础工具
apt install -y curl wget
# 下载 install.sh
curl -fsSL https://res1.hermesagent.org.cn/install.sh -o /tmp/hermes_install.sh
坑 1:官方镜像慢。res1 镜像下 60MB 源码包要 15min+。解决方案:sed 替换 MIRROR_BASE_URL 强制走 GitHub:
# 替换默认镜像为无效值,让 install.sh 回退到 GitHub 源
sed -i 's|MIRROR_BASE_URL="${HERMES_MIRROR_BASE_URL:-https://res1.hermesagent.org.cn}"|MIRROR_BASE_URL="${HERMES_MIRROR_BASE_URL:-https://invalid-mirror.invalid}"|' /tmp/hermes_install.sh
GitHub 60MB tarball 实测 1s 传完(前提:网络能直连 GitHub,否则需要 proxychains)。
坑 2:setup wizard 失败。hermes setup 需要 TTY,SSH 远程跑会报 /dev/tty: 没有那个设备或地址。解决方案:直接跳过 setup,手工编辑 /root/.hermes/.env 和 config.yaml。
2.2 安装核心组件
# 装运行时依赖
apt install -y python3-venv python3-dev build-essential libffi-dev
# 执行安装(用清华 pip 源)
HERMES_PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
bash /tmp/hermes_install.sh
安装步骤会自动:
- 识别环境(Ubuntu)
- 检测 Python 3.12
- 警告缺 ripgrep/ffmpeg 但跳过
- 下载源码(GitHub 60MB)
- 创建 venv
- 装 pip 依赖(清华源)
- 创建
~/.local/bin/hermes软链 - 同步 72 个 skills
# 验证
/root/.local/bin/hermes --version
# Hermes Agent v0.18.0 (2026.7.1)
坑 3:PATH 不永久。root 登录新 shell 找不到 hermes。解决方案:
echo 'export PATH=$HOME/.local/bin:$PATH' >> /root/.bashrc
3. 配置 LLM(智谱 bigmodel)
3.1 用对 provider
Hermes 内置 zai provider 专门对接智谱。provider: "custom" 会强制走本地推理服务器路径,用 no-key-required placeholder,忽略所有 API key(含 OPENAI_API_KEY)。
# /root/.hermes/config.yaml
model:
default: "glm-4.7"
provider: "zai" # ← 不是 "custom"
base_url: "https://open.bigmodel.cn/api/paas/v4"
# /root/.hermes/.env
GLM_API_KEY=<your_zhipu_key>
GLM_BASE_URL=https://open.bigmodel.cn/api/paas/v4
3.2 模型名(实测 bigmodel 2026-07 端点)
| 用途 | 模型名 | 备注 |
|---|---|---|
| 文本主 | glm-4.7 | 不要带 -Flash 后缀(端点上不存在) |
| 视觉 | glm-4.6v | 基础版稳定;-flash 后缀会触发 1305 限流 |
| 视觉备选 | glm-4v / glm-4v-plus | 准确率低但能跑 |
| 文本兜底 | glm-4.5-air | 免费档限速更宽松 |
| 图像生成 | cogview-3 / cogview-3-flash | 不是视觉理解 |
bigmodel 错误码速查:
1211= 模型不存在1302= 账号 RPM 限速1305= 模型级限流
踩坑:用 hermes auth add zai 走认证流程更稳(Hermes CLI 会自动生成 BigModel credential record 并关联 zai provider)。
3.3 视觉 / 辅助模型
auxiliary:
vision:
provider: "zai"
model: "glm-4.6v"
web_extract:
provider: "zai"
model: "glm-4.7"
tts_audio_tags:
provider: "zai"
model: "" # 留空走主模型
session_search:
provider: "zai"
model: "" # 留空走主模型
# Smoke test
hermes -z "Reply with exactly PONG" # → "PONG"
4. 接入飞书(lark-oapi WebSocket 模式)
4.1 飞书应用配置
- 飞书开放平台 → 创建企业自建应用
- 添加能力:机器人
- 权限管理:开通
im:message、im:message.group_at_msg、im:message.p2p_msg、im:message:send_as_bot等 - 事件订阅:添加
im.message.receive_v1(接收消息) - 复制 App ID + App Secret
注意:WebSocket 模式不需要配置回调 URL 或公网 webhook,比 webhook 模式省心。
4.2 装依赖
source /root/.hermes/hermes-agent/venv/bin/activate
pip install lark_oapi aiohttp websockets
# → 装 lark_oapi-1.7.0, pycryptodome, requests-toolbelt
4.3 写 .env
# 追加到 /root/.hermes/.env
cat >> /root/.hermes/.env <<EOF
# >>> Feishu (added by setup) >>>
FEISHU_APP_ID=<your_app_id>
FEISHU_APP_SECRET=<your_app_secret>
FEISHU_DOMAIN=feishu
FEISHU_HOME_CHANNEL=
FEISHU_ALLOW_ALL_USERS=true
GATEWAY_ALLOW_ALL_USERS=true
FEISHU_DM_POLICY=open
FEISHU_GROUP_POLICY=open
# <<< Feishu <<<
EOF
chmod 600 /root/.hermes/.env
4.4 启动 Gateway
坑 4:后台启动。hermes gateway run 是阻塞进程;用 setsid + & 在 SSH exec_command 里会随父进程一起死。解决方案:用 Python Popen + start_new_session=True:
# /tmp/spawn_gw.py
import os, subprocess
env = os.environ.copy()
env["LANG"] = "C.UTF-8"
env["LC_ALL"] = "C.UTF-8"
env["PATH"] = f"/root/.local/bin:{env.get('PATH','')}"
log = open("/tmp/gateway.log", "wb")
subprocess.Popen(
["/root/.hermes/hermes-agent/venv/bin/hermes", "gateway", "run", "--accept-hooks"],
cwd="/root", env=env,
stdin=subprocess.DEVNULL, stdout=log, stderr=subprocess.STDOUT,
start_new_session=True,
)
# 启动
python3 /tmp/spawn_gw.py
# 验证
ps -ef | grep hermes
# root 79399 1 ... hermes gateway run --accept-hooks
tail -f /tmp/gateway.log
# [Lark] [INFO] connected to wss://msg-frontier.feishu.cn/ws/v2?...
4.5 验证
# 用同 key 调飞书 OpenAPI 验证 token
curl -X POST https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal \
-H "Content-Type: application/json" \
-d '{"app_id":"<APP_ID>","app_secret":"<APP_SECRET>"}'
# → {"code":0,"expire":7200,"tenant_access_token":"t-..."}
5. 防火墙 & 安全
5.1 关闭 GNOME 自动锁屏
# 7 项 gsettings(timmoc 和 root 用户都设)
gsettings set org.gnome.desktop.session idle-delay 0
gsettings set org.gnome.desktop.screensaver lock-enabled false
gsettings set org.gnome.desktop.screensaver lock-delay 0
gsettings set org.gnome.desktop.screensaver idle-activation-enabled false
gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing'
gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-type 'nothing'
gsettings set org.gnome.settings-daemon.plugins.power idle-dim false
5.2 GDM 显示 root 登录
# /etc/pam.d/gdm-password: 注释掉第 3 行 user != root 那一行
# /etc/gdm3/custom.conf: AllowRoot=true, AutomaticLoginEnable=false
# /var/lib/AccountsService/users/root: 新建 [User] SystemAccount=true
systemctl restart gdm
5.3 防火墙
# Hermes 走出站 WebSocket,不需要入站端口
# 飞书 API: open.feishu.cn:443, msg-frontier.feishu.cn:443
# 出站无需特殊配置
6. 常见坑速查表
| 现象 | 根因 | 解决 |
|---|---|---|
hermes setup 报 /dev/tty: 没有那个设备或地址 | 无 TTY | 跳过 setup,手工改 .env / config.yaml |
hermes -z 报 HTTP 401 | provider: "custom" 强制 no-key | 改 provider: "zai" |
| bigmodel 报 “模型不存在 (1211)” | 模型名拼写错(如加了 -Flash) | 用 curl /v1/models 探测真实名单 |
| bigmodel 报 “限速 (1305/1302)” | 触发了模型级或账号级限流 | 换 -air 后缀或等几分钟 |
| res1 镜像 15min 拉不完 60MB | 镜像带宽差 | sed 替换 MIRROR_BASE_URL 走 GitHub |
| gateway 一启动就死 | setsid + & 在 SSH exec_command 里不够 detached | Python Popen + start_new_session=True |
| gateway list 显示 “not running” | 进程没 detach 或被杀 | 查 `ps -ef |
| 飞书 bot 收不到消息 | 缺事件订阅 im.message.receive_v1 | 飞书开发者后台加权限 |
| 飞书 bot 拒收所有消息 | 默认 pairing/allowlist policy | 设 FEISHU_ALLOW_ALL_USERS=true + *_POLICY=open |
lark_oapi ModuleNotFoundError | hermes venv 没装 | pip install lark_oapi aiohttp websockets |
| 视觉模型返回 “yellow” 误判 | glm-4.6v 准确率有限 | 试 glm-4.6v-plus 或人工校验 |
7. 运维命令速查
# 状态
hermes status
hermes gateway list
ps -ef | grep hermes
# 日志
tail -f /tmp/gateway.log
# 重启
pkill -9 -f 'hermes gateway'
python3 /tmp/spawn_gw.py
# 改配置后生效
systemctl reload ssh # sshd_config
# gateway 改 .env 需重启
8. 待办(可选)
- 配 systemd service 让 gateway 开机自启
- 装 Docker 让镜像源(daemon.json)真的能用
- 设 webhook 模式作为 WebSocket 的备份链路
- 用
hermes doctor --fix修剩余的 config 版本落后问题 - 配 allowlist 白名单收紧访问(生产环境)
- 监控:用
hermes cron+ 飞书通知做心跳
9. 关键文件清单
| 路径 | 作用 |
|---|---|
/root/.hermes/.env | 凭据 + 平台配置(Feishu、GLM) |
/root/.hermes/config.yaml | 模型 + auxiliary 段 |
/root/.hermes/hermes-agent/ | Hermes 源码 + venv |
/root/.local/bin/hermes | CLI 软链 |
/tmp/gateway.log | Gateway 运行时 log |
/tmp/spawn_gw.py | 重启脚本 |
/etc/ssh/sshd_config | SSH 配置(root 登录) |
/etc/gdm3/custom.conf | GDM root 登录 |
/etc/pam.d/gdm-password | 注释掉 user != root |
~/.pip/pip.conf | pip 清华源 |
/etc/apt/sources.list.d/aliyun.list | APT 阿里源 |
10. 总结
全流程 ~1.5 小时(含多个网络探测 + 失败重试)。
关键经验:
provider: "zai"不是 “custom” —— 单这一条卡了 20 分钟- res1 镜像慢 → sed 强制走 GitHub,提速 1000 倍
- gateway 必须 Python Popen + start_new_session ——
setsid在 SSH exec_command 里不够 - WebSocket 模式 > Webhook 模式 —— 不需要公网 IP/端口映射
- lark_oapi 必须手工装 —— hermes 默认 deps 没包含飞书 SDK
- bigmodel 模型名无
-Flash后缀 —— 端点上不存在,得用curl /v1/models探测
一次配置长期运行:零依赖人工干预,机器人 7×24 接收飞书消息。