
背景
最近在使用 Hermes Agent 时,所有请求突然全部失败,Gateway 日志反复报出:
1 | Error code: 401 - Authentication Fails, Your api key: ****OcWp is invalid |
伴随 Transient agent failure 错误。API key 明明刚换过新的,为什么一直 401?
环境
- Hermes Agent(最新版)
- Provider: DeepSeek(官方 API)
- 认证方式:
DEEPSEEK_API_KEY环境变量
排查过程
1. 配置结构分析
Hermes 的凭证体系有两层:
~/.hermes/.env — 环境变量文件
1 | DEEPSEEK_API_KEY=*** |
~/.hermes/config.yaml — 主配置,包含:
providers.deepseek-official— 官方 provider,通过key_env: DEEPSEEK_API_KEY引用上述变量custom_providers— 自定义 provider 列表,每个独立配置了api_key
看起来没什么问题:环境变量是最新的 key,官方 provider 正确引用它。
2. 发现冲突
深入检查 custom_providers,发现一个叫 muapi 的 provider:
1 | - api_key: sk-old...-key |
关键线索:muapi 和 deepseek-official 使用了完全相同的 base URL。
3. 凭证池机制
Hermes 内部维护一个凭证池(credential pool),以 base URL 为 key 缓存 provider 到 API key 的映射。当请求发往 https://api.deepseek.com 时:
- 凭证池查找 base URL → 匹配到
muapi(而非deepseek-official) - 使用
muapi缓存的旧密钥 - 旧密钥已过期 → 401
日志中已有明确信号:
1 | run_agent: Credential pool provider mismatch: |
凭证池已经被 muapi 的旧密钥锁定,即使切换 provider 也无法刷新。
修复步骤
Step 1: 更新环境变量
1 | # ~/.hermes/.env |
Step 2: 同步更新冲突 provider
在 config.yaml 中找到 muapi 条目,将其 api_key 更新为与 DEEPSEEK_API_KEY 相同的新密钥。
**为什么?**凭证池缓存的是 base URL → key 的映射,不更新的话即使 .env 正确,请求仍然走旧密钥。
Step 3: 清除凭证池缓存
1 | rm -f ~/.hermes/state.db ~/.hermes/state.db-shm ~/.hermes/state.db-wal |
Hermes 将凭证映射缓存在 SQLite state.db 中,删除后强制重建。
Step 4: 重启 Gateway
1 | hermes gateway restart |
验证
1 | # 直测 API |
经验教训
- 避免同一 base URL 对应多个 provider — 凭证池以 URL 为 key,同名端点会导致路由混乱
- 轮换密钥后务必清除
state.db— 旧的凭证缓存是静默杀手 - 留意
Credential pool provider mismatch警告 — 这是凭证路由异常的直接信号,不要忽视
当多个 provider 指向同一 API endpoint 时,凭证池的行为不是「按 provider 隔离」而是「按 URL 共享」—— 谁先注册谁占位。这个行为细节在文档中不容易注意到,但踩过一次以后就很清晰了。