TokenRhythm 密钥池 + Cron 修复 + QQ 邮箱挂载
触发条件
- 切换 TokenRhythm API key(#2/#3/#4)
- cron job 报 HTTP 402 余额不足 / 502 / 429
- 挂载 QQ 邮箱(读/发邮件)
1. TokenRhythm 多 key 密钥池(官方方案)
铁律:密钥不内联(见 api-key-masking-workaround)。密钥存独立文件,脚本读取。
key 文件约定
| Key | 文件 | 说明 |
|---|---|---|
| #2 | /home/user/backup_api_key.txt | 主备 |
| #3 | /home/user/backup_api_key_3.txt | 备 |
| #4 | /home/user/backup_api_key_4.txt | 备 |
添加密钥池(一次性)
写脚本从文件读 key 再调用,禁止在命令里写明文 key:
KEY=$(cat /home/user/backup_api_key.txt)
/opt/hermes/bin/hermes auth add tokenrhythm --type api-key --label tr-key2 --api-key "$KEY"
# 同理 tr-key3 / tr-key4
验证:/opt/hermes/bin/hermes auth list tokenrhythm
⚠️ Fallback 断链坑(2026-08-15 实测)
症状:cron 报 provider rate limit. Fallback chain was exhausted or unavailable(429 后全链耗尽)。
根因:Hermes 读 API key 的官方路径是 ~/.hermes/.env(不是 /home/user/.env!)。docker-compose 无 env_file,主 key 靠进程环境注入;backup key 从未写入 → fallback 链中 tokenrhythm-backup 无 key → 断链。
修复:
1. 创建 ~/.hermes/.env(即 /home/user/.hermes/.env),格式 KEY=value,chmod 600
2. 写入:TOKENRHYTHM_API_KEY(主)+ TOKENRHYTHM_API_KEY_BACKUP(backup_api_key_4.txt 内容)
3. 验证:/opt/hermes/.venv/bin/python3 -c "import sys; sys.path.insert(0,'/opt/hermes'); from hermes_cli.config import load_env; print([k for k in load_env() if 'TOKEN' in k])" 应显示两个 key
4. Hermes get_env_value_prefer_dotenv 每次调用读 .env(mtime 缓存自动失效)→ 无需重启 gateway
5. 手动验证全链:cronjob action=run 触发,看 execution_success
注意:改 ~/.hermes/.env 不需要重启;改 config.yaml 才需要重启 gateway。
识别限流 vs 服务繁忙:429=key/TPM 限流(可修),503=服务端过载(等恢复即可,无需修)。限流时告知用户"输出会变慢"即可,不做修复动作。
自动轮换原理
池内多 key 自动轮换:当前 key 报错(429/402)→ 自动切下一个。无需改 .env。
维护命令
/opt/hermes/bin/hermes auth list tokenrhythm # 查看池
/opt/hermes/bin/hermes auth remove tokenrhythm N # 删第N个
/opt/hermes/bin/hermes auth reset tokenrhythm # 清耗尽状态
2. Cron 模型固定(修复 402/502/429/跳过执行)
症状
cron 报 HTTP 402: 余额不足 或 HTTP 502 或
Skipped to prevent unintended spend: global inference config drifted since this job was created ... unpinned
根因
- 旧 key 余额耗尽(402)
- 模型配置漂移:job 未固定模型,全局模型变了就跳过执行(防意外花钱机制)
修复(CLI 必须,cronjob 工具无 model 参数)
export PATH=$PATH:/opt/hermes/bin
hermes cron edit <JOB_ID> --model deepseek-v4-flash-0731 --provider tokenrhythm
检查哪些 job 未固定模型
hermes cron list 看 model/provider 字段为 null 的,全部固定。
手动触发验证
hermes cron run <JOB_ID> # 或 cronjob action=run
3. QQ 邮箱挂载(himalaya v2)
安装(v2 语法与 v1 完全不同!)
curl -sSL https://raw.githubusercontent.com/pimalaya/himalaya/master/install.sh | PREFIX=/home/user/himalaya sh
配置位置
HOME 可能是 /home/user,配置放 $HOME/.config/himalaya/config.toml
(确认:himalaya account list 显示 BACKENDS 为 imap,smtp 才算成功)
v2 配置格式(关键!不是 v1 的 backend.type 扁平键)
[accounts.qq]
email = "[EMAIL]@example.com"
display-name = "用户"
default = true
imap.server = "imaps://imap.qq.com:993"
imap.sasl.plain.username = "[EMAIL]@example.com"
imap.sasl.plain.password.command = "cat /home/user/mail_auth.txt"
smtp.server = "smtps://smtp.qq.com:465"
smtp.sasl.plain.username = "[EMAIL]@example.com"
smtp.sasl.plain.password.command = "cat /home/user/mail_auth.txt"
mailbox.alias.inbox = "INBOX"
mailbox.alias.sent = "Sent Messages"
mailbox.alias.drafts = "Drafts"
mailbox.alias.trash = "Deleted Messages"
常见坑
- v1 格式在 v2 不识别:
backend.type扁平键 → BACKENDS 列为空。必须用imap.serverURL 形式 - QQ 邮箱用授权码(16位,非QQ密码):设置→账号→开启 IMAP/SMTP
- 授权码存独立文件(/home/user/mail_auth.txt),配置用
password.command引用
常用命令
export PATH=/home/user/himalaya/bin:$PATH
himalaya envelope list --page-size 10 # 收件箱
himalaya account check # 验证连接
himalaya message read <ID> # 读邮件
himalaya template send # 发邮件(管道输入)
4. 避坑清单
- 密钥绝不内联在命令/文档/消息中 → 文件读取
- cronjob 工具无法设置 model/provider → 用 hermes CLI
- hermes CLI 路径:/opt/hermes/bin/hermes(不在默认 PATH)
- 切换 key 后需验证:
hermes auth list+ 实际调用