ByteNoteByteNote
Hermes Agent 模型迁移与调优实录
字

字节笔记本

2026年10月5日 · 约 23 分钟读完

Hermes Agent 模型迁移与调优实录

API中转
¥120

把 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 @ 本地 Ollamaglm-5-turbo @ z.ai /api/anthropic
Auxiliaryprovider: auto(11 项)分档接入硅基流动免费模型(13 项)
版本v0.15.1v0.18.0
平台Telegram + QQBot仅 Telegram(QQBot 因不兼容已删)
Reactions开启关闭
Rich messages关闭开启

初始配置里,主模型依赖本地 Ollama:

yaml
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 函数:

python
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 会被自动正确识别。最终写入的配置:

yaml
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

环境变量的坑

最初想走环境变量:

bash
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 验证端点连通性:

bash
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

误导性诊断过程

阶段当时的判断事后复盘
1Python 3.9.6 导致不成立,cron 全程用 venv 3.11
2升级后没重启 gateway部分成立,cron ImportError 确实是这个原因
3z.ai 账户限流(1313 Fair Usage)不成立,限流是概率性的,不是主因
4User-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 函数:

python
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 url

auxiliary client 用的是 OpenAI SDK,它假设所有 /anthropic 端点都有对应的 /v1 OpenAI 端点,于是自动改写 URL。但 z.ai 的订阅 key 在 /api/v1 上没有模型权限,403 由此而来。双端点对照验证:

bash
# /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 403 根因链路:anthropic 端点被自动改写成 v1

解决方案:auxiliary 改用硅基流动

z.ai 订阅 key 只能走 /api/anthropic(留给主模型,这条路径不会被改写),auxiliary 必须另找 OpenAI 兼容端点。硅基流动(siliconflow.cn)是最合适的选择:协议兼容,代金券余额充足且有效期到 2099 年,支持 GLM 系列、DeepSeek、Qwen 等几十个模型。

四、auxiliary 分档:把免费额度用在刀刃上

实测代金券清单里适合 auxiliary 的模型:

模型速度特点适合任务
zai-org/GLM-4.5-Air0.45s极快高频轻量
inclusionAI/Ling-flash-2.00.55s蚂蚁百灵轻量分类
deepseek-ai/DeepSeek-V3.1-Terminus1.66s强模型总结理解
deepseek-ai/DeepSeek-V3.24.06s最强文本复杂理解
zai-org/GLM-4.5V1.43s视觉图像理解
Qwen/Qwen3-VL-32B-Instruct1.15s最强视觉复杂图像

分档设计三条原则:按负载分档,高频轻量任务用快模型,重理解任务用强模型;视觉任务用专用模型,纯文本模型处理不了图像;全部选代金券清单内的模型,零成本。

最终 13 项 auxiliary 的分档结果:

档位模型任务数量
A 档 快速zai-org/GLM-4.5-Airapproval, mcp, title_generation, triage_specifier, kanban_decomposer, profile_describer, flush_memories, skills_hub, session_search9
B 档 强理解deepseek-ai/DeepSeek-V3.1-Terminuscompression, curator, web_extract3
C 档 视觉Qwen/Qwen3-VL-32B-Instructvision1
yaml
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

升级流程本身很顺:

bash
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 侧做了两项调整:

项旧新效果
reactionstruefalse不再显示处理中、完成等表情反应
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。逐层排查:

  1. shell 环境变量(env | grep proxy):无
  2. launchctl getenv HTTP_PROXY:无
  3. gateway plist:无 proxy
  4. .zshrc:无
  5. macOS 系统代理:命中

根因是 Hermes 的 resolve_proxy_url 函数(gateway/platforms/base.py)会调用 _detect_macos_system_proxy(),通过 scutil --proxy 读取 macOS 系统设置里的代理:

bash
$ scutil --proxy
  HTTPEnable : 1
  HTTPPort : 10808
  HTTPProxy : 127.0.0.1
  HTTPSEnable : 1
  SOCKSEnable : 1

在中国大陆访问 api.telegram.org 确实需要代理,保持现状即可,系统代理继续工作。

七、用量统计:一条长会话烧掉 392 万 token

日常观测主要靠几条命令:

命令用途
hermes insights --days 77 天用量(token/会话/工具/skill)
hermes insights --days 7 --source telegram按平台过滤
hermes sessions stats会话总数、消息数、DB 大小
hermes status --allAPI keys 与平台完整状态
hermes dump完整配置快照(脱敏)
hermes doctor健康检查

迁移当天的关键数据:25 个会话、540 条消息、584 万 token。其中一条 79k 上下文的 Telegram 长会话烧掉 392 万 token,原因是 compression 反复失败重试。教训:长会话必须定期 /new,否则上下文膨胀叠加 compression 失败,会指数级烧 token。

八、最终架构与命令速查

Hermes Agent 最终配置架构:一主多辅,云上双端点

配置管理、gateway、用量、cron、升级的常用命令:

bash
# 配置管理
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               # 当前版本

九、踩坑清单

  1. 环境变量 vs config.yaml:Hermes 对环境变量名挑剔(ANTHROPIC_AUTH_TOKEN 不认),优先用 config.yaml。
  2. Anthropic 端点的 URL 改写:auxiliary client 会自动把 /anthropic 改写成 /v1,订阅 key 在 /v1 没权限,于是 403。
  3. 升级后必须重启 gateway:否则 cron 用陈旧模块快照,报 ImportError。
  4. 误导性错误信息:z.ai 把账户限流(1313)包装成 403 model_access_denied,看起来像权限问题。
  5. macOS 系统代理:Hermes 会读 scutil --proxy,即使 .env 没配代理也会用系统代理。
  6. 长会话烧 token:79k 上下文叠加 compression 失败,单会话烧掉 392 万 token,记得定期 /new。

如果你也在跑一个依赖本地 Ollama 的 Agent,这套订阅制主模型加免费代金券辅助任务的组合值得一试:成本为零,稳定性却完全不同。

本文基于 2026-07-04 的实际配置操作整理,敏感信息已脱敏。

相关文章

分享: