# 把 Hermes 的 Fallback 模型切换到 Gemini 3.6 Flash：一次真实配置记录

> 本文记录一次 Hermes Agent 主模型回退链调整：保留主模型和第二回退模型，只把第一回退从 `gemini-2.5-pro` 切换为 `gemini-3.6-flash`。重点不只是“改了配置”，而是如何确认模型存在、控制变更范围，并区分配置落盘与运行时生效。

## 一句话结论

最终回退链调整为：

1. 主模型：`openai-codex / gpt-5.6-sol`
2. 第一回退：`gemini / gemini-3.6-flash`
3. 第二回退：`openai-codex / gpt-5.4`

配置校验通过，Hermes 能正确读取新的回退链；但 Gateway 运行时是否已经加载新配置，仍需在独立终端重启后确认。

## 为什么不能只改一个模型名就宣布完成

Hermes 的主模型回退链位于顶层 `fallback_providers` 列表。主模型遇到限流、服务端错误、认证失败或连接异常时，Hermes 才会依次尝试这些候选模型。

这类变更至少包含四个不同层次：

- **候选模型真实存在**：模型名称必须能被当前 Google API 账号识别。
- **配置结构有效**：`fallback_providers` 必须是 YAML 列表，不能意外写成字符串。
- **Hermes 能正确解析**：`hermes config check` 和 `hermes fallback list` 都应通过。
- **运行时已加载**：正在运行的 Gateway 可能仍持有旧配置，需要重启或其他明确的重新加载证据。

只看到文件里出现了新模型名，并不等于切换已经完整落地。

## 变更前先确认模型存在

在写配置前，先通过 Google Generative Language API 的模型列表接口确认当前凭证可见的模型。检查结果中包含精确名称：

```text
gemini-3.6-flash
```

这一步只读取模型目录，不执行推理，也不暴露 API Key。它可以提前排除模型名拼错、模型尚未开放或账号无权访问等问题。

## 建立配置基线

修改前先执行：

```bash
hermes config check
hermes fallback list
```

原始回退链为：

```text
Primary: gpt-5.6-sol (via openai-codex)

1. gemini-2.5-pro (via gemini)
2. gpt-5.4 (via openai-codex)
```

同时确认 Google API 凭证已配置。检查过程中只记录“存在或缺失”，不输出完整密钥。

## 只修改第一回退模型

修改后的目标配置是：

```yaml
fallback_providers:
  - provider: gemini
    model: gemini-3.6-flash
  - provider: openai-codex
    model: gpt-5.4
```

实际差异只有一行：

```diff
 fallback_providers:
   - provider: gemini
-    model: gemini-2.5-pro
+    model: gemini-3.6-flash
   - provider: openai-codex
     model: gpt-5.4
```

这种窄变更有两个好处：

- 不改变主模型和第二回退模型，降低行为漂移。
- 出现问题时可以快速回滚，不需要恢复整份复杂配置。

## 一个容易踩中的坑：结构化列表被写成字符串

在这次操作中，直接执行类似下面的命令：

```bash
hermes config set fallback_providers '[{"provider":"gemini","model":"gemini-3.6-flash"}]'
```

会把整个 JSON 文本保存成一个带引号的 YAML 字符串，而不是 `fallback_providers` 列表。Hermes 随后显示“未配置回退模型”。该命令还触发了 YAML 的整体重排，带来了与目标无关的格式差异。

因此，对于这类列表配置，不能只相信 `config set` 返回的“Set successful”。必须立即执行：

```bash
hermes fallback list
```

如果 CLI 的交互式 `hermes fallback add/remove` 不适合精确保持现有顺序，较稳妥的做法是：

1. 先创建带时间戳的配置备份；
2. 断言目标 YAML 块只出现一次；
3. 只替换目标块；
4. 保留原文件权限；
5. 对备份和当前配置执行差异检查。

本次发现结构错误后，先完整恢复备份，再执行单块替换，最终差异只剩目标模型名这一行。

## 配置验证结果

修改后执行：

```bash
hermes config check
hermes fallback list
```

验证结果：

```text
Configuration Status: Config version 33 ✓

Primary: gpt-5.6-sol (via openai-codex)

Fallback chain:
1. gemini-3.6-flash (via gemini)
2. gpt-5.4 (via openai-codex)
```

这证明：

- YAML 结构有效；
- Hermes 能识别 `gemini-3.6-flash` 为第一回退模型；
- 第二回退模型和主模型没有被改动。

## 配置落盘不等于 Gateway 已经切换

Hermes Gateway 正在处理当前会话时，不能从该 Gateway 内部执行自身重启。系统会明确拒绝该操作，避免 Gateway 杀死正在运行的命令和会话。

因此，应在独立 SSH Shell 中执行：

```bash
hermes gateway restart
hermes gateway status
hermes fallback list
```

预期第一回退显示：

```text
1. gemini-3.6-flash (via gemini)
```

这里要明确区分三种状态：

- **代码或配置已修改**：文件中已经写入新值；
- **配置已验证**：Hermes CLI 能解析并显示新值；
- **生产运行时已切换**：Gateway 已重新加载配置，并完成运行时验证。

本次在当前会话内完成了前两项；第三项需要从 Gateway 外部重启后才能确认。

## 还缺哪一步才算端到端验证

模型目录查询只能证明模型存在、凭证至少能访问模型列表，不能证明推理调用一定成功。

严格的端到端验证还应发送一次最小推理请求，并记录：

- Provider：`gemini`
- Model：`gemini-3.6-flash`
- 较小的输出 token 上限
- 非零的小温度，例如 `0.01`
- 实际返回的助手文本或明确错误类型

由于推理请求可能产生费用或消耗额度，不应在未获得授权时自动执行。若请求失败，也应区分认证失败、配额耗尽、模型不可用和响应超时，而不是统一归类为“配置错误”。

## 回滚策略

变更前保留带时间戳的 `config.yaml` 备份。若新模型出现兼容性、配额或延迟问题，可恢复备份，再从独立终端重启 Gateway。

回滚后的检查仍然是：

```bash
hermes config check
hermes fallback list
hermes gateway status
```

不要仅恢复文件后就宣布回滚完成；运行时同样需要重新加载并验证。

## 这次操作留下的三个经验

1. **先验证模型目录，再写配置。** 这样可以把模型不存在与配置错误分开定位。
2. **结构化配置必须做读回验证。** CLI 返回写入成功，不代表数据类型和语义正确。
3. **始终区分配置、解析和运行时激活。** 只有文件差异、CLI 读回和 Gateway 生效证据全部闭环，才能称为完整切换。

这套方法也适用于其他 Hermes Provider 或回退模型调整：备份、窄改、差异检查、配置验证、运行时重载，以及一次经过授权的真实模型调用。