如果你在 Hermes Agent 里主模型调用正常,但启动新会话时看到类似提示:
Auxiliary title generation failed: HTTP 401: Missing Authentication header
或者日志里出现:
Auxiliary title_generation: using custom (...)
明明你已经设置了 OPENROUTER_API_KEY,主对话也能走 OpenRouter / OpenAI-compatible endpoint,为什么偏偏标题生成、摘要、辅助任务会 401?
这类问题很可能不是 API Key 真的没配置,而是 auxiliary.<task> 配置里同时写了 provider: auto 或 provider: openrouter,又写了 base_url,但 api_key 为空,导致 Hermes Agent 把这个辅助任务误判成 custom provider,并跳过了环境变量里的 provider credential lookup。
这篇文章基于 NousResearch/hermes-agent issue #16829,整理一个面向搜索和实战排错的配置问题:
auxiliary.{task} with provider:auto + base_url set falls into custom path with empty api_key, returns 401
适合搜索关键词:Hermes Agent Auxiliary title generation failed 401、Missing Authentication header Hermes Agent、provider auto base_url api_key empty、Hermes auxiliary custom api_key None、OpenRouter 401 Missing Authentication header Hermes。
先给结论:主模型能用,不代表 auxiliary 也继承了同一套凭证
这个问题的关键不是“OpenRouter 不可用”,也不是“模型名写错”,而是 Hermes Agent 的辅助任务解析逻辑曾经可能走到这条路径:
if cfg_base_url:
return "custom", resolved_model, cfg_base_url, cfg_api_key, resolved_api_mode
只要 base_url 存在,它就直接返回 provider="custom"。
如果此时你的 YAML 里是:
auxiliary:
title_generation:
provider: auto
model: minimax/minimax-m2.7
base_url: https://openrouter.ai/api/v1
api_key: ''
那就会变成:
provider = custom
api_key = None / empty
下游 OpenAI-compatible client 发请求时没有 Authorization header,于是上游返回:
401 Missing Authentication header
用户最容易误判的地方在于:环境变量里明明有 OPENROUTER_API_KEY,主模型也能用。但 auxiliary 任务已经被锁进 custom 分支,未必再走 OpenRouter 的环境变量解析链路。
典型报错现象
你可能会看到下面几类提示:
Auxiliary title generation failed: HTTP 401: Missing Authentication header
API call failed after 3 retries: 401 Missing Authentication header
Auxiliary title_generation: using custom (...)
provider=custom api_key=None
如果日志里显示 auxiliary 使用的是 custom,但你本来期望它使用 openrouter 或 auto,就非常符合这个问题。
为什么只影响 auxiliary,不影响主对话?
Hermes Agent 里主模型和辅助任务可能不是完全同一条配置解析路径。
主模型通常会根据:
providermodel- provider 专用 API Key 环境变量
- 全局配置
- OpenAI-compatible endpoint
来选择 client。
但 auxiliary.title_generation、auxiliary.summarization 等任务可以有自己的 per-task override。issue #16829 指出的就是:在 _resolve_task_provider_model() 里,只要任务级配置有 base_url,就优先进入了 custom 分支。
这导致一个很微妙的差异:
| 场景 | 可能结果 |
| 主模型 provider=openrouter,环境变量有 key | 正常 |
| auxiliary provider=auto/openrouter,没有 base_url | 可能正常走 provider lookup |
| auxiliary provider=auto/openrouter,有 base_url,但 api_key 为空 | 可能误走 custom,401 |
所以看到 401 时,不要只检查全局 API Key,还要检查 auxiliary block 里是否写了空 api_key 和 base_url。
最常见的错误配置
下面这种配置看起来很自然,但正是风险点:
auxiliary:
title_generation:
provider: openrouter
model: minimax/minimax-m2.7
base_url: https://openrouter.ai/api/v1
api_key: ''
timeout: 30
extra_body: {}
很多用户的直觉是:
provider: openrouter告诉 Hermes 用 OpenRouter;base_url只是补充 endpoint;api_key: ''表示从环境变量OPENROUTER_API_KEY读取。
但在问题版本里,base_url 的优先级更高,导致它不再按 OpenRouter provider 处理,而是按 custom 处理。
立即可用 workaround:删掉 auxiliary 里的 base_url 和空 api_key
如果你希望 auxiliary 任务和主 provider 一样走自动识别,可以先把任务级的 base_url 和空 api_key 删除。
例如改成:
auxiliary:
title_generation:
provider: auto
model: minimax/minimax-m2.7
timeout: 30
extra_body: {}
然后确认环境变量存在:
export OPENROUTER_API_KEY="sk-or-..."
重启 Hermes gateway / agent 后,再看日志是否从:
Auxiliary title_generation: using custom (...)
变成:
Auxiliary title_generation: using auto (...)
如果 401 消失,就基本坐实是 auxiliary provider resolution 的问题。
什么时候应该保留 base_url?
不是说 base_url 永远不能写。
如果你真的要让某个 auxiliary task 使用一个自定义 OpenAI-compatible endpoint,而且不想走 provider 自动识别,那么应该同时明确提供 api_key:
auxiliary:
title_generation:
provider: custom
model: your-model-name
base_url: https://your-endpoint.example.com/v1
api_key: ${YOUR_CUSTOM_API_KEY}
核心区别是:
base_url + api_key:明确 custom endpoint;provider:auto/openrouter + base_url + 空 api_key:容易造成歧义;provider:auto/openrouter + 无 base_url + 环境变量:更适合走 provider credential lookup。
修复方向:只有 base_url 和 api_key 都存在时才走 custom
issue 和相关 PR #16950 指向的修复思路很直接:
if cfg_base_url and cfg_api_key:
return "custom", resolved_model, cfg_base_url, cfg_api_key, resolved_api_mode
也就是说,只有当用户同时显式配置了 base_url 和 api_key,才把它当作 custom provider。
如果有 base_url 但没有 api_key,则应继续走:
- 显式 provider,例如
openrouter; - 或
provider: auto的自动识别; - 再从环境变量中读取
OPENROUTER_API_KEY等 provider 专用 key。
需要注意的是,GitHub 上 #16829 已 closed/completed,评论中也写到 “Fixed in #16950”;但 PR API 显示 #16950 的 merged_at 为 null。因此排错时建议你以当前安装版本的实际代码和日志为准:
- 升级到较新的 Hermes Agent;
- 检查
_resolve_task_provider_model()是否仍是if cfg_base_url:; - 如果仍旧如此,先用配置 workaround;
- 如果已变成
if cfg_base_url and cfg_api_key:,再排查其他 401 原因。
和 DeepAI API 中转站怎么配合?
这个问题和 DeepAI API 中转站的关系要说清楚:它不是 DeepAI 或 OpenAI-compatible 网关本身导致的,而是客户端 auxiliary 配置解析的问题。
如果你的工具支持 OpenAI Compatible API,DeepAI API 中转站可以帮助你统一:
- Base URL;
- API Key;
- 模型列表;
- 团队配置;
- Cherry Studio、Cline、Dify、Open WebUI 等工具里的多模型接入。
但如果 Hermes Agent 的某个辅助任务把 provider:auto + base_url + 空 api_key 解析成 custom + api_key=None,中转站也无法替客户端补上已经被跳过的 Authorization header。
更稳的配置思路是:
auxiliary:
title_generation:
provider: auto
model: your-model
timeout: 30
extra_body: {}
然后在支持 OpenAI-compatible 的工具或主配置中统一设置 DeepAI 的 Base URL 和 Key。对于 Hermes auxiliary 这种 per-task override,尽量避免“写了 base_url 但 api_key 为空”的半自定义状态。
排错清单
遇到 Auxiliary title generation failed: HTTP 401 时,可以按这个顺序查:
1. 确认主模型是否正常; 2. 打开 ~/.hermes/config.yaml; 3. 找到 auxiliary.title_generation 或其他 auxiliary.<task>; 4. 检查是否同时有 provider: auto/openrouter、base_url、api_key: ''; 5. 查看日志里 auxiliary 是否显示 using custom; 6. 临时删除 auxiliary block 里的 base_url 和空 api_key; 7. 重启 gateway / agent; 8. 确认环境变量如 OPENROUTER_API_KEY 对 gateway 进程可见; 9. 再次观察是否仍然 401; 10. 如果仍然失败,再检查模型名、额度、endpoint path、provider 是否支持该模型。
401、404 和 provider 配置问题怎么区分?
很多 OpenAI-compatible 配置问题都会表现成 HTTP 错误,但含义不同:
| 错误 | 常见含义 | 优先检查 |
| 401 Missing Authentication header | 请求没带 Authorization | api_key 是否为空、是否走错 custom path |
| 401 Invalid API key | 带了 key,但 key 不对 | key 是否过期、前缀是否正确、环境变量是否污染 |
| 404 Not Found | endpoint path 或模型路径错误 | base_url 是否多/少了 /v1,api_mode 是否匹配 |
| 400 Bad Request | payload 或模型协议不兼容 | messages、tools、reasoning/thinking 字段 |
#16829 这一类问题属于第一种:请求根本没有正确带上认证头。
FAQ
为什么我设置了 OPENROUTER_API_KEY,还是 401?
因为 auxiliary task 可能被 base_url 锁进了 custom provider 分支,导致它没有继续走 OpenRouter 的环境变量读取逻辑。
api_key: '' 不就是表示从环境变量读取吗?
很多人会这么理解,但具体取决于客户端实现。这个 issue 里,空 api_key 搭配 base_url 会导致 custom client 没有 Authorization header。
删除 auxiliary 里的 base_url 会不会影响主模型?
通常不会。你删除的是 auxiliary.<task> 的 per-task override,让它回到 provider auto-detection 或全局 provider 路径。
如果我必须使用自定义中转站怎么办?
那就不要半配置。明确写 provider: custom、base_url 和非空 api_key,并确认该 endpoint 是 OpenAI-compatible。
DeepAI API 中转站能解决这个 401 吗?
DeepAI 可以提供统一的 OpenAI-compatible Base URL 和 Key,但不能修复客户端把 auxiliary task 解析成 custom + api_key=None 的问题。你仍然需要修正 Hermes 配置或升级到修复版本。
总结
Hermes Agent auxiliary 任务报 401 Missing Authentication header,尤其是 title_generation 失败时,不要只盯着全局 API Key。
如果你的配置里同时出现:
provider: auto
base_url: https://...
api_key: ''
就要怀疑 auxiliary 被误判成 custom provider,并且没有带 Authorization header。
最稳的临时修复是:删除 auxiliary task 里的 base_url 和空 api_key,让它回到 provider 自动识别;如果你确实要自定义 endpoint,就同时显式提供非空 api_key。
一句话总结:provider:auto 负责自动识别,custom 负责显式 endpoint;不要把 base_url 写成 custom,但把 api_key 留空。