# Hermes Gateway 运维手册

## 重启 Gateway

**必须从外部 shell 执行，不能从 agent 内部重启。**

**⚠️ 从 agent 内执行 `systemctl --user restart hermes-gateway` 会被安全机制拦截**（"cannot restart or stop the gateway from inside the gateway process"）。必须告诉用户在另一个终端执行。

```bash
# 从外部 shell 执行
systemctl --user restart hermes-gateway
```

### 安全重启（推荐）
```bash
hermes gateway restart
```
或：
```bash
systemctl --user restart hermes-gateway
```

### 重启流程（有 override 配置时）
1. systemd 发送 SIGTERM 给旧 gateway
2. 旧 gateway 关闭
3. ExecStartPre 脚本运行：等待 35 秒 + 清除旧 Telegram session
4. 新 gateway 启动

总耗时约 40 秒。

### 没有 override 时的手动重启
```bash
systemctl --user stop hermes-gateway
sleep 35
systemctl --user start hermes-gateway
```

## Polling Conflict (409 Conflict)

**症状**：日志中反复出现 `Conflict: terminated by other getUpdates request`

**原因**：Telegram 同一 bot 只允许一个 getUpdates 连接。快速重启时旧 session 未过期（需 30 秒）。

**修复**：配置 ExecStartPre override（见下方 Override 配置）。

## Override 配置（持久化）

**文件位置**：`~/.config/systemd/user/hermes-gateway.service.d/override.conf`

```ini
[Service]
ExecStartPre=
ExecStartPre=/home/openclaw/.hermes/scripts/clear-telegram-session.sh
RestartSec=30
```

**注意**：第一行 `ExecStartPre=` 是清空默认值，第二行才是实际命令。

**应用**：
```bash
systemctl --user daemon-reload
```

**验证**：
```bash
systemctl --user cat hermes-gateway.service | grep -E "RestartSec|ExecStartPre"
```

## ExecStartPre 清除脚本

**文件位置**：`~/.hermes/scripts/clear-telegram-session.sh`

**⚠️ 必须用 Python 写入**，不能用 bash heredoc（`$(...)` 语法会被破坏）：

```python
lines = [
    '#!/bin/bash',
    'TOKEN=$(grep TELEGRAM_BOT_TOKEN ~/.hermes/.env | cut -d= -f2)',
    'PROXY="http://127.0.0.1:7890"',
    # ... rest of script
]
with open('/home/openclaw/.hermes/scripts/clear-telegram-session.sh', 'w') as f:
    f.write('\n'.join(lines) + '\n')
```

## 危险命令审批配置

```yaml
approvals:
  mode: off        # 关闭所有审批（交易自动化必须）
  timeout: 60
  cron_mode: deny
command_allowlist:  # 必须是命令名，不是描述文字
  - hermes
  - docker
  - systemctl
  - python3
  - bash
  - sh
```

**注意**：`command_allowlist` 里的条目必须是实际命令名（如 `docker`），不能是描述（如 `docker restart/stop/kill (container lifecycle)`）。

## Memory 死循环

**症状**：gateway 有 CPU 活动但无新日志输出，群消息不处理。

**原因**：MEMORY.md 接近上限（>95%）时 gateway 的 self-improvement review 反复重试 save。

**诊断**：
```bash
journalctl --user -u hermes-gateway -n 50 --no-pager | grep "memory"
```
看到 `Memory at 2,XXX/2,200 chars` 就是 memory 满了。

**修复**：
```bash
# 清理 memory（从 agent 内执行 memory remove 或 replace）
# 或手动编辑 ~/.hermes/memories/MEMORY.md
wc -c ~/.hermes/memories/MEMORY.md  # 检查大小
```

**预防**：定时任务 `memory-check` 每天 10:00 EDT 自动检查。

## 诊断清单

当群消息不处理时，按顺序检查：

1. **Gateway 是否运行**：`systemctl --user status hermes-gateway`
2. **Telegram 连接**：`journalctl --user -u hermes-gateway -n 100 | grep -i telegram`
3. **Polling 冲突**：看有没有 `409 Conflict`
4. **Memory 满**：看有没有 `Memory at 2,XXX/2,200`
5. **审批阻断**：看有没有 `pending_approval`
6. **转发器是否运行**：`docker ps | grep forward`
7. **转发器关键词过滤**：`docker logs telegram-forwarder --since 2h | grep "未匹配"` — 如果大量"未匹配"说明白名单regex太严格，改成 `.*`
8. **Bot 自测无效**：bot 自己发的消息不通过 getUpdates 返回
9. **Gateway 日志**：`strings ~/.hermes/logs/gateway.log | tail -30`（文件是二进制格式，必须用 `strings` 提取文本）
10. **Gateway 连接状态**：`strings ~/.hermes/logs/gateway.log | grep "Connected to"` 确认各平台连接
11. **Gateway inbound 消息**：`strings ~/.hermes/logs/gateway.log | grep "inbound message" | tail -10` 查看最近收到的消息
