
字节笔记本
2026年10月5日 · 约 23 分钟读完
Hermes Agent 模型迁移与调优实录
把 Agent 的大脑从本地搬到云端,是自托管 Agent 用户的必经之路。本文完整记录一次 Hermes Agent 的配置迁移:主模型从本地 Ollama 的 kimi-k2.6:cloud 切换到 z.ai Anthropic 端点上的 glm-5-turbo,13 项 auxiliary 辅助任务分档接入硅基流动的免费代金券模型,期间顺手把版本升到 v0.18.0,并排查了 Telegram 的隐形代理来源。全篇都是真实踩坑记录,最有价值的是一个极具迷惑性的 403 根因。
一、迁移前后的整体变化
| 项 | 起点 | 终点 |
|---|---|---|
| 主模型 | kimi-k2.6:cloud @ 本地 Ollama | glm-5-turbo @ z.ai /api/anthropic |
| Auxiliary | provider: auto(11 项) | 分档接入硅基流动免费模型(13 项) |
| 版本 | v0.15.1 | v0.18.0 |
| 平台 | Telegram + QQBot | 仅 Telegram(QQBot 因不兼容已删) |
| Reactions | 开启 | 关闭 |
| Rich messages | 关闭 | 开启 |
初始配置里,主模型依赖本地 Ollama:
model:
default: kimi-k2.6:cloud
provider: custom
base_url: http://127.0.0.1:11434/v1 # 依赖本地 Ollama 运行
context_length: 1000000
api_mode: chat_completions痛点很直接:Agent 依赖本地 Ollama 进程,机器关机或重启后 cron 任务全部挂掉,本地算力也有限。迁移目标有三条:主对话走云端 API,不依赖本地进程;所有模型统一管理;利用已有的代金券与订阅额度,做到零额外成本。
二、主模型切换:接入 z.ai 的 Anthropic 端点
z.ai 提供两种协议端点:
/api/anthropic:Anthropic Messages 协议,订阅制,配合 Claude Code 使用。本次接入用的就是订阅制 key,对应这个端点。/api/v1:OpenAI 兼容协议,按量计费,走GLM_API_KEY。
Hermes 对 Anthropic 端点有自动协议识别逻辑,源码 agent/auxiliary_client.py 里的 _endpoint_speaks_anthropic_messages 函数:
def _endpoint_speaks_anthropic_messages(base_url: str) -> bool:
normalized = (base_url or "").strip().lower().rstrip("/")
if normalized.endswith("/anthropic"):
return True # 任何 /anthropic 结尾的 URL 自动走 Anthropic 协议
...代码注释里专门点名了 Zhipu GLM(z.ai),所以 https://api.z.ai/api/anthropic 会被自动正确识别。最终写入的配置:
model:
default: glm-5-turbo
provider: custom
base_url: https://api.z.ai/api/anthropic
api_key: xxxx...xxxx
api_mode: anthropic_messages
context_length: 128000环境变量的坑
最初想走环境变量:
export ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic
export ANTHROPIC_AUTH_TOKEN=xxx # Hermes 不识别这个变量名
export ANTHROPIC_MODEL=glm-5.1model # Hermes 不读这个变量对照源码逐一核查后的结论:
| 变量 | Hermes 是否识别 |
|---|---|
ANTHROPIC_BASE_URL | 识别 |
ANTHROPIC_API_KEY / ANTHROPIC_TOKEN | 识别 |
ANTHROPIC_AUTH_TOKEN | 不识别(注意是 AUTH_TOKEN,不是 API_KEY) |
ANTHROPIC_MODEL | 不读取 |
环境变量策略不可靠,直接写 config.yaml 才稳。用 curl 验证端点连通性:
curl -X POST "https://api.z.ai/api/anthropic/v1/messages" \
-H "x-api-key: xxxx" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"model":"glm-5-turbo","max_tokens":20,"messages":[{"role":"user","content":"hi"}]}'
# 返回 HTTP 200三、最关键的一坑:auxiliary 全线 403
主对话配置正确,curl 测试全部通过,但 Hermes 运行时的 auxiliary 任务(compression 等)反复报错:
403 model_access_denied: No permission to access model: glm-5-turbo
误导性诊断过程
| 阶段 | 当时的判断 | 事后复盘 |
|---|---|---|
| 1 | Python 3.9.6 导致 | 不成立,cron 全程用 venv 3.11 |
| 2 | 升级后没重启 gateway | 部分成立,cron ImportError 确实是这个原因 |
| 3 | z.ai 账户限流(1313 Fair Usage) | 不成立,限流是概率性的,不是主因 |
| 4 | User-Agent 不对 | 不成立,换 UA 测试都返回 200 |
真正的根因:URL 被改写
agent.log 里的关键一行暴露了问题:
Auxiliary compression: using custom (glm-5-turbo) at https://api.z.ai/api/v1/
配置写的是 /api/anthropic,Hermes 实际请求的却是 /api/v1/。定位到 agent/auxiliary_client.py 的 _to_openai_base_url 函数:
def _to_openai_base_url(base_url: str) -> str:
"""Normalize an Anthropic-style base URL to OpenAI-compatible format."""
url = str(base_url or "").strip().rstrip("/")
if url.endswith("/anthropic"):
# ZAI (open.bigmodel.cn) 用 /api/paas/v4
if "open.bigmodel.cn" in url or "bigmodel" in url:
rewritten = url[: -len("/anthropic")] + "/paas/v4"
return rewritten
# 其它 /anthropic 端点一律改写成 /v1,问题就出在这里
rewritten = url[: -len("/anthropic")] + "/v1"
return rewritten
return urlauxiliary client 用的是 OpenAI SDK,它假设所有 /anthropic 端点都有对应的 /v1 OpenAI 端点,于是自动改写 URL。但 z.ai 的订阅 key 在 /api/v1 上没有模型权限,403 由此而来。双端点对照验证:
# /api/anthropic(Anthropic 协议),订阅 key 有效
curl ... https://api.z.ai/api/anthropic/v1/messages 返回 HTTP 200
# /api/v1(OpenAI 协议),订阅 key 无权限
curl ... https://api.z.ai/api/v1/chat/completions 返回 HTTP 403
解决方案:auxiliary 改用硅基流动
z.ai 订阅 key 只能走 /api/anthropic(留给主模型,这条路径不会被改写),auxiliary 必须另找 OpenAI 兼容端点。硅基流动(siliconflow.cn)是最合适的选择:协议兼容,代金券余额充足且有效期到 2099 年,支持 GLM 系列、DeepSeek、Qwen 等几十个模型。
四、auxiliary 分档:把免费额度用在刀刃上
实测代金券清单里适合 auxiliary 的模型:
| 模型 | 速度 | 特点 | 适合任务 |
|---|---|---|---|
zai-org/GLM-4.5-Air | 0.45s | 极快 | 高频轻量 |
inclusionAI/Ling-flash-2.0 | 0.55s | 蚂蚁百灵 | 轻量分类 |
deepseek-ai/DeepSeek-V3.1-Terminus | 1.66s | 强模型 | 总结理解 |
deepseek-ai/DeepSeek-V3.2 | 4.06s | 最强文本 | 复杂理解 |
zai-org/GLM-4.5V | 1.43s | 视觉 | 图像理解 |
Qwen/Qwen3-VL-32B-Instruct | 1.15s | 最强视觉 | 复杂图像 |
分档设计三条原则:按负载分档,高频轻量任务用快模型,重理解任务用强模型;视觉任务用专用模型,纯文本模型处理不了图像;全部选代金券清单内的模型,零成本。
最终 13 项 auxiliary 的分档结果:
| 档位 | 模型 | 任务 | 数量 |
|---|---|---|---|
| A 档 快速 | zai-org/GLM-4.5-Air | approval, mcp, title_generation, triage_specifier, kanban_decomposer, profile_describer, flush_memories, skills_hub, session_search | 9 |
| B 档 强理解 | deepseek-ai/DeepSeek-V3.1-Terminus | compression, curator, web_extract | 3 |
| C 档 视觉 | Qwen/Qwen3-VL-32B-Instruct | vision | 1 |
auxiliary:
vision:
provider: custom
model: Qwen/Qwen3-VL-32B-Instruct
base_url: https://api.siliconflow.cn/v1
api_key: xxxx
compression:
provider: custom
model: deepseek-ai/DeepSeek-V3.1-Terminus
base_url: https://api.siliconflow.cn/v1
api_key: xxxx
approval:
provider: custom
model: zai-org/GLM-4.5-Air
base_url: https://api.siliconflow.cn/v1
api_key: xxxx
# 其余各项同理,按档位配置五、升级 v0.15.1 到 v0.18.0:必须重启 gateway
升级流程本身很顺:
hermes version # 升级前确认
hermes update --backup # 升级并备份
hermes config migrate # 迁移配置版本
hermes config check # 验证升级后处理了三件事:配置版本自动从 v23 迁移到 v33;新增的 auxiliary 子任务 kanban_decomposer、profile_describer 补上硅基流动配置;从 platform_toolsets 移除已废弃的 messaging、moa toolset。
踩坑:升级后 cron 报 ImportError
ImportError: cannot import name 'PARALLEL_TOOL_CALL_GUIDANCE' from 'agent.prompt_builder'
根因:升级写入了新代码,但 gateway 进程内存里还是旧代码的模块快照。修复只要一条 hermes gateway restart。教训:升级 Hermes 后必须重启 gateway,否则 cron(gateway 内嵌线程池任务)会继续用陈旧的模块快照。
六、平台清理与 Telegram 调优
QQBot 在升级后报 is_reconnect 参数不兼容,因为不用 QQ,直接从 .env 删掉相关 4 行配置(QQ_APP_ID、QQ_CLIENT_SECRET、QQ_ALLOW_ALL_USERS、QQ_ALLOWED_USERS);又从 config.yaml 的 custom_providers 删除 mimo-anthropic 条目,只保留 zai。
Telegram 侧做了两项调整:
| 项 | 旧 | 新 | 效果 |
|---|---|---|---|
reactions | true | false | 不再显示处理中、完成等表情反应 |
extra.rich_messages | 未设 | true | 富文本消息,Markdown 渲染更好 |
telegram.reactions 开启时,收到消息会打处理中反应,回复完成换成完成反应,失败换成错误反应。这些表情写死在源码 plugins/platforms/telegram/adapter.py,没有配置项可改,所以直接关闭。
代理来源排查
现象:.env 里 TELEGRAM_PROXY 已注释,但 Hermes 启动仍报 Proxy detected; passing explicitly to HTTPXRequest: http://127.0.0.1:10808。逐层排查:
- shell 环境变量(
env | grep proxy):无 launchctl getenv HTTP_PROXY:无- gateway plist:无 proxy
.zshrc:无- macOS 系统代理:命中
根因是 Hermes 的 resolve_proxy_url 函数(gateway/platforms/base.py)会调用 _detect_macos_system_proxy(),通过 scutil --proxy 读取 macOS 系统设置里的代理:
$ scutil --proxy
HTTPEnable : 1
HTTPPort : 10808
HTTPProxy : 127.0.0.1
HTTPSEnable : 1
SOCKSEnable : 1在中国大陆访问 api.telegram.org 确实需要代理,保持现状即可,系统代理继续工作。
七、用量统计:一条长会话烧掉 392 万 token
日常观测主要靠几条命令:
| 命令 | 用途 |
|---|---|
hermes insights --days 7 | 7 天用量(token/会话/工具/skill) |
hermes insights --days 7 --source telegram | 按平台过滤 |
hermes sessions stats | 会话总数、消息数、DB 大小 |
hermes status --all | API keys 与平台完整状态 |
hermes dump | 完整配置快照(脱敏) |
hermes doctor | 健康检查 |
迁移当天的关键数据:25 个会话、540 条消息、584 万 token。其中一条 79k 上下文的 Telegram 长会话烧掉 392 万 token,原因是 compression 反复失败重试。教训:长会话必须定期 /new,否则上下文膨胀叠加 compression 失败,会指数级烧 token。
八、最终架构与命令速查

配置管理、gateway、用量、cron、升级的常用命令:
# 配置管理
hermes config # 查看摘要
hermes config edit # 编辑 config.yaml
hermes config set KEY VALUE # 设置单项
hermes config check # 检查
hermes config migrate # 迁移到最新版本
cp ~/.hermes/config.yaml ~/.hermes/config.yaml.bak.$(date +%Y%m%d_%H%M%S) # 备份
# Gateway
hermes gateway restart # 重启(改配置或升级后必做)
hermes gateway status # 状态
tail -f ~/.hermes/logs/gateway.log # 实时日志
tail -f ~/.hermes/logs/agent.log # agent 日志(消息处理)
# 用量
hermes insights --days 7 # 用量分析
hermes sessions stats # 会话统计
hermes dump # 完整快照
# Cron
hermes cron list # 任务列表
hermes cron run <job_id> # 手动触发
hermes cron edit <job_id> --prompt "..." # 编辑
# 升级
hermes update --backup # 升级并备份
hermes version # 当前版本九、踩坑清单
- 环境变量 vs config.yaml:Hermes 对环境变量名挑剔(
ANTHROPIC_AUTH_TOKEN不认),优先用 config.yaml。 - Anthropic 端点的 URL 改写:auxiliary client 会自动把
/anthropic改写成/v1,订阅 key 在/v1没权限,于是 403。 - 升级后必须重启 gateway:否则 cron 用陈旧模块快照,报 ImportError。
- 误导性错误信息:z.ai 把账户限流(1313)包装成
403 model_access_denied,看起来像权限问题。 - macOS 系统代理:Hermes 会读
scutil --proxy,即使.env没配代理也会用系统代理。 - 长会话烧 token:79k 上下文叠加 compression 失败,单会话烧掉 392 万 token,记得定期
/new。
如果你也在跑一个依赖本地 Ollama 的 Agent,这套订阅制主模型加免费代金券辅助任务的组合值得一试:成本为零,稳定性却完全不同。
本文基于 2026-07-04 的实际配置操作整理,敏感信息已脱敏。



