AgentHarness 课程

第十篇:部署与运维

1.8万字·47分钟·
部署方式对比、监控告警、生产Checklist

概述

将 Hermes Agent 从开发环境推向生产环境,需要考虑部署方式选择、日志管理、会话生命周期、监控告警和故障排查等一系列运维问题。与传统的 Web 应用不同,AI Agent 的运维有一些独特的挑战:长时间运行的对话会消耗大量内存,上下文压缩可能在关键时刻失败,API 调用可能因为 rate limit 而被拒绝,Cron 任务可能在无人值守时执行失败。

本篇覆盖从本地开发到生产部署的完整运维体系,提供实际可操作的配置示例和排查方法。每个问题都会给出症状、原因和具体的解决步骤。


1. 部署方式

1.1 本地开发部署

最简单的部署方式,直接从源码运行:

# 克隆仓库
git clone <repo-url> /opt/hermes-agent
cd /opt/hermes-agent

# 安装依赖(推荐使用 uv,比 pip 快 10-100 倍)
uv pip install -e ".[all]"

# 初始化配置(交互式引导)
hermes setup

# 启动 CLI 模式(交互式对话)
hermes chat

# 启动 Gateway 模式(后台服务,支持多平台连接)
hermes gateway run

配置文件位置:

~/.hermes/
├── .env                    # 环境变量(API Key 等,权限 600)
├── config.yaml             # 主配置文件
├── SOUL.md                 # Agent 人格定义(可选)
├── memories/               # 记忆存储
│   ├── MEMORY.md           # Agent 笔记
│   └── USER.md             # 用户画像
├── skills/                 # 技能目录
│   └── software-development/
│       └── code-review/
│           └── SKILL.md
├── sessions/               # 会话数据库(SQLite)
├── logs/                   # 日志目录
│   ├── gateway.log
│   ├── agent.log
│   └── cron.log
├── cron/                   # 定时任务数据
│   ├── jobs.json           # 任务定义
│   ├── outputs/            # 任务输出
│   └── .tick.lock          # 调度锁文件
├── checkpoints/            # 文件系统检查点(Shadow Git)
└── bin/                    # 自动安装的二进制(如 tirith)

环境变量配置(~/.hermes/.env):

# 必需:至少一个 LLM provider 的 API Key
OPENAI_API_KEY=sk-...
# 或
ANTHROPIC_API_KEY=sk-ant-...

# 可选:模型和 provider
HERMES_MODEL=gpt-4o
HERMES_INFERENCE_PROVIDER=openai

# 可选:平台配置
TELEGRAM_BOT_TOKEN=...
DISCORD_BOT_TOKEN=...

1.2 Docker 容器部署

Hermes Agent 支持 Docker 容器化部署,适合需要环境隔离或快速部署的场景:

FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
    python3 python3-pip python3-venv sqlite3 \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY requirements.txt .
RUN pip3 install -r requirements.txt

COPY . .
RUN mkdir -p /data

EXPOSE 5000
ENV FLASK_APP=app.py
ENV DATABASE_PATH=/data/database.db

CMD ["python3", "app.py"]

Docker 部署注意事项:

  • 数据持久化:使用 volume 挂载 ~/.hermes,否则容器重启后所有数据(记忆、技能、会话)丢失
    docker run -v ~/.hermes:/root/.hermes ...
    
  • 自动免审:容器内命令执行自动免审(env_type == "docker"),因为容器本身提供了环境隔离
  • 网络配置:确保容器可以访问 LLM API 端点和消息平台 API
  • 内存限制:根据模型上下文长度设置合理的内存限制(128K context 的模型可能需要 4GB+)

1.3 Systemd 用户服务

生产环境推荐使用 Systemd 用户服务管理 Gateway。这是最稳定的部署方式——自动重启、日志管理、开机自启:

# ~/.config/systemd/user/hermes-gateway.service
[Unit]
Description=Hermes Agent Gateway
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/hermes gateway run
Restart=on-failure
RestartSec=5
Environment=HERMES_GATEWAY_SESSION=1
Environment=HERMES_HOME=%h/.hermes

# 资源限制
LimitNOFILE=65536
MemoryMax=4G

[Install]
WantedBy=default.target

启用用户服务持久化(确保用户注销后服务仍运行):

# 关键步骤:启用 loginctl linger
loginctl enable-linger $(whoami)

# 启用服务
systemctl --user daemon-reload
systemctl --user enable hermes-gateway
systemctl --user start hermes-gateway

# 查看状态
systemctl --user status hermes-gateway

# 查看日志(实时)
journalctl --user -u hermes-gateway -f

# 查看最近的错误
journalctl --user -u hermes-gateway -p err --since "1 hour ago"

loginctl enable-linger 的作用是让 systemd 用户实例在用户注销后继续运行。没有这个设置,用户注销时所有用户服务会被停止。这在 SSH 远程管理场景下特别重要——管理员 SSH 登录启动服务后注销,服务需要继续运行。

1.4 Nginx 反向代理

当需要 HTTPS、自定义域名或负载均衡时,使用 Nginx 作为反向代理:

server {
    listen 443 ssl http2;
    server_name hermes.example.com;

    ssl_certificate /etc/letsencrypt/live/hermes.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hermes.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # 长连接超时——Agent 响应可能需要几分钟
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;

        # 请求体大小限制(用于文件上传)
        client_max_body_size 50M;
    }
}

WebSocket 支持对于实时平台(Telegram long polling、Discord gateway)的连接是必需的。UpgradeConnection 头确保 WebSocket 连接正确代理。


2. 运维实践

2.1 日志管理

Hermes Agent 的日志存储在 ~/.hermes/logs/ 目录下。

日志级别配置

# config.yaml
logging:
  level: INFO              # 全局日志级别
  file_level: DEBUG        # 文件日志级别(更详细,用于事后分析)
  console_level: WARNING   # 控制台日志级别(更简洁,减少干扰)

或通过环境变量:

export HERMES_LOG_LEVEL=DEBUG

日志轮转:推荐使用 logrotate 管理日志文件大小,防止磁盘被日志填满:

# /etc/logrotate.d/hermes
/home/*/.hermes/logs/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}

copytruncate 是关键选项——它复制日志文件内容后截断原文件,不需要重启进程。对于不支持信号重载日志文件的应用(如 Hermes Gateway),这是唯一的选择。

关键日志文件及用途

文件内容典型查询
gateway.logGateway 启动、请求处理、平台事件grep "error" gateway.log
agent.logAgent 迭代、工具调用、压缩事件grep "compression" agent.log
cron.log定时任务执行、投递结果grep "FAILED" cron.log

2.2 会话管理

Hermes Agent 提供多个会话管理命令,用于控制对话生命周期:

命令作用实现细节
/new创建新会话,重置所有状态调用 on_session_reset(),清空压缩计数、token 计数、记忆 nudge 计数
/reset重置当前会话,清空对话历史保留配置,只清空消息列表
/compact [focus]手动触发上下文压缩可选指定聚焦主题,分配 60-70% 摘要预算给聚焦内容
/resume恢复上次中断的会话从 SQLite 会话数据库加载历史消息

会话数据库:会话数据存储在 SQLite 数据库中(~/.hermes/sessions/),支持通过 session_search 工具跨会话检索历史对话。这使得 Agent 可以在当前会话中引用过去会话的内容。

会话超时:Gateway 场景下,会话可能因不活跃而过期。Agent 的活动追踪器(get_activity_summary())监控最后一次活动时间:

activity_summary = {
    "seconds_since_activity": 45.2,       # 距上次活动的秒数
    "last_activity_desc": "terminal: ls -la",  # 上次活动描述
    "current_tool": "terminal",            # 当前正在执行的工具
    "api_call_count": 12,                  # 已执行的 API 调用次数
    "max_iterations": 90,                  # 最大迭代次数
}

2.3 配置热更新

部分配置可以在不重启的情况下更新:

# 重新加载 .env 文件(每次 Cron 任务执行时自动重载)
# Gateway 模式下,新的会话会读取最新配置

# 更新模型配置
hermes setup model

# 更新工具配置
hermes setup tools

# 更新终端配置
hermes setup terminal

配置热更新的边界:

配置项热更新说明
API Key是(新会话).env 文件每个 Cron 任务自动重载
模型是(新会话)config.yaml 中的模型配置
审批模式部分Smart Approval 模式切换需要新会话
技能下次会话自动扫描新技能
记忆下次会话加载最新记忆文件
平台配置需要重启 Gateway
端口需要重启 Gateway

2.4 更新流程

标准更新流程(参考 MEMORY.md 中的项目更新步骤):

# 1. 拉取最新代码
cd /opt/hermes-agent
git pull origin main

# 2. 更新依赖(关键步骤——新版本可能引入新的依赖)
uv pip install -e ".[all]"

# 3. 重启服务
systemctl --user restart hermes-gateway

# 4. 验证版本
hermes --version
hermes status

# 5. 检查日志确认无错误
journalctl --user -u hermes-gateway --since "5 minutes ago"

更新时注意事项:

  • 记忆文件(MEMORY.md/USER.md)不会被更新覆盖(它们在 .hermes/memories/ 目录下,不受 git 影响)
  • config.yaml 不会被覆盖,但新版本可能引入新配置项(需要手动添加)
  • 检查 CHANGELOG 或 release notes 了解破坏性变更
  • 强烈建议更新前备份 ~/.hermes/config.yaml

3. 监控与告警

3.1 Gateway 状态监控

# 查看整体状态(模型、工具、平台连接等)
hermes status

# 查看 Gateway 进程状态
systemctl --user status hermes-gateway

# 实时日志监控(推荐用于排查问题)
journalctl --user -u hermes-gateway -f

# 查看活跃连接
ss -tlnp | grep 5000

# 查看进程资源使用
ps aux | grep hermes

3.2 进度通知

对于长时间运行的任务,可以通过 Gateway 的进度通知机制了解 Agent 状态:

  • 平台适配器回调tool_progress_callback 将工具调用事件推送到聊天界面
  • 心跳机制_touch_activity() 定期更新活跃时间戳
  • 子 Agent 进度_build_child_progress_callback() 批量上报工具调用

3.3 资源监控

关键资源指标和阈值建议:

指标阈值建议检查方式超阈值处理
磁盘空间> 80% 使用告警df -h ~/.hermes清理旧日志和检查点
会话数据库> 100MB 需清理du -sh ~/.hermes/sessions/清理旧会话记录
日志目录> 500MB 需轮转du -sh ~/.hermes/logs/配置 logrotate
检查点数据> 1GB 需清理du -sh ~/.hermes/checkpoints/清理旧检查点
内存使用根据模型上下文调整`ps auxgrep hermes`
CPU 使用长时间 > 80% 需关注top -p $(pgrep -f hermes)检查是否有死循环

3.4 Cron 任务监控

# 查看所有定时任务
hermes cron list

# 查看特定任务的历史执行记录
hermes cron history <job_id>

# 手动触发一次调度(不等待定时)
hermes cron tick

# 查看任务输出文件
cat ~/.hermes/cron/outputs/<job_id>_*.md

# 查看调度锁状态(如果有残留锁)
ls -la ~/.hermes/cron/.tick.lock

4. 生产环境 Checklist

4.1 API Key 安全

  • API Key 存储在 ~/.hermes/.env 中,文件权限设为 600
  • .env 文件不被版本控制(确认 .gitignore 包含 .env
  • 生产环境使用专用 API Key,不与开发环境共享
  • 定期轮换 API Key(建议每 90 天)
  • 使用凭证池(credential pool)分散 rate limit 风险
# 设置正确的文件权限
chmod 600 ~/.hermes/.env
chmod 700 ~/.hermes/

# 验证权限
ls -la ~/.hermes/.env
# 期望输出:-rw------- 1 user user ... .env

4.2 审批模式

  • 生产环境配置 approvals.mode: smartoff
  • 审批超时设为合理值(Gateway 建议 300 秒)
  • command_allowlist 定期审计(检查是否有过于宽泛的永久审批)
  • 了解 YOLO 模式的影响范围(会话级,非全局)
# config.yaml
approvals:
  mode: smart           # 智能审批(推荐)
  timeout: 60
  gateway_timeout: 300

4.3 网络安全

  • Gateway 端口不直接暴露到公网(使用 Nginx 反向代理)
  • 启用 HTTPS(Let's Encrypt 或自签证书)
  • 配置防火墙规则限制入站流量
  • 平台 Webhook URL 使用 HTTPS
  • 考虑 IPv4 强制偏好(某些 LLM API 不支持 IPv6)
# config.yaml
network:
  force_ipv4: true     # 强制 IPv4(解决某些环境的 IPv6 连接问题)

4.4 日志轮转

  • 配置 logrotate 或类似工具
  • 日志保留期限符合合规要求(建议 30 天)
  • 敏感信息不出现在日志中(redact 机制已内置)
  • 日志格式便于 ELK/Grafana 等工具解析

4.5 备份策略

数据备份频率恢复方式
config.yaml每次修改后直接复制回
memories/每日直接复制回
skills/每次修改后直接复制回或 git 同步
sessions/每日SQLite 备份恢复
checkpoints/不需要备份临时性质,可以重建

5. 常见问题排查

5.1 认证失败

症状:Agent 无法启动或 API 调用返回 401/403 错误码

排查步骤

# 1. 检查 API Key 是否配置
cat ~/.hermes/.env | grep API_KEY
# 或使用内置命令
hermes status

# 2. 检查 .env 文件格式(常见格式错误)
# 正确格式:KEY=VALUE(等号两边无空格,值无引号)
#   OPENAI_API_KEY=sk-abc123
# 错误格式:
#   OPENAI_API_KEY="sk-abc123"  (引号会被当作值的一部分)
#   OPENAI_API_KEY = sk-abc123  (等号两边有空格)
#   OPENAI_API_KEY=sk-abc123   (行尾有不可见空格)

# 3. 检查 API Key 是否有效(直接调用 API 验证)
curl -s -o /dev/null -w "%{http_code}" \
     -H "Authorization: Bearer $OPENAI_API_KEY" \
     https://api.openai.com/v1/models
# 期望输出:200

# 4. 检查 provider 配置是否正确
hermes setup model

常见原因及解决方案

原因症状解决方案
API Key 过期或被撤销401 错误重新生成 API Key
.env 文件编码问题启动时报 UnicodeDecodeError使用 UTF-8 无 BOM 编码重新保存
Provider 配置错误连接超时或 404检查 base_url 是否正确
Rate limit429 错误配置凭证池或降低并发

5.2 端口冲突

症状:Gateway 启动失败,报 "Address already in use" 错误

排查步骤

# 1. 检查端口占用
ss -tlnp | grep 5000
# 或
lsof -i :5000

# 2. 查找并终止占用进程
kill -9 <PID>

# 3. 或使用不同端口启动
HERMES_PORT=5001 hermes gateway run

# 4. 如果是僵尸进程(进程已死但端口未释放)
# 等待 60 秒让操作系统回收端口(TCP TIME_WAIT 状态)
# 或设置 SO_REUSEADDR

5.3 上下文溢出

症状:Agent 回复截断、出现 context_length 错误、或行为异常(忘记之前的对话内容、重复提问)

排查步骤

# 1. 检查压缩配置
grep -A 5 "context:" ~/.hermes/config.yaml

# 2. 查看压缩日志(确认压缩是否正常工作)
grep "Context compression" ~/.hermes/logs/agent.log | tail -20

# 3. 手动触发压缩(在当前会话中)
/compact

# 4. 检查系统提示词大小(可能过大)
# 查看日志中的 prompt_tokens 值
grep "prompt_tokens" ~/.hermes/logs/agent.log | tail -5

常见原因及解决方案

原因症状解决方案
系统提示词过大压缩后仍溢出精简 SOUL.md、AGENTS.md 内容
压缩阈值过高压缩触发太晚降低 threshold_percent 到 0.40
工具输出过大read_file 读取了大文件限制单次读取的行数
技能索引过大系统提示词占用过多禁用不需要的技能

调优建议

# config.yaml
context:
  engine: "compressor"
  threshold_percent: 0.40    # 降低触发阈值,更早压缩
  protect_first_n: 3
  summary_target_ratio: 0.20

5.4 Agent 卡死

症状:Agent 长时间无响应,无工具调用也无回复

排查步骤

# 1. 检查进程是否存活
ps aux | grep hermes

# 2. 检查 CPU 和内存使用(内存不足时系统可能 OOM Kill)
top -p $(pgrep -f hermes)

# 3. 查看 Gateway 日志中的活动追踪
grep "activity" ~/.hermes/logs/gateway.log | tail -20

# 4. 检查是否有等待审批的命令
# Gateway 场景:检查是否有 /approve 待处理
# 日志中搜索 "approval_required"

# 5. 检查 API 连接(API 请求可能挂起)
curl -v --max-time 10 https://api.openai.com/v1/models \
     -H "Authorization: Bearer $OPENAI_API_KEY"

常见原因及解决方案

原因症状解决方案
API 请求挂起无日志输出检查网络连接,设置请求超时
工具执行阻塞日志显示长时间在同一工具检查终端命令是否等待输入
审批等待超时日志显示 "approval_required"用户通过 /approve/deny 响应
死循环日志显示重复工具调用检查 max_iterations 设置
内存不足进程消失(OOM Kill)增加内存或使用更小的模型

恢复措施

# Gateway:通过平台发送中断命令
# CLI:Ctrl+C

# 如果完全无响应,强制重启
systemctl --user restart hermes-gateway

# 检查检查点(可以回滚到之前的状态)
ls -lt ~/.hermes/checkpoints/

5.5 Cron 任务执行失败

症状:定时任务不执行或执行失败

排查步骤

# 1. 检查任务列表(确认任务存在且 schedule 正确)
hermes cron list

# 2. 查看任务执行历史
hermes cron history <job_id>

# 3. 查看输出文件(包含详细的错误信息)
cat ~/.hermes/cron/outputs/<job_id>_latest.md

# 4. 手动触发测试
hermes cron tick

# 5. 检查 Cron 日志
grep "cron" ~/.hermes/logs/gateway.log | tail -20

常见原因及解决方案

原因症状解决方案
Cron 表达式格式错误任务不执行验证表达式(使用 hermes cron validate
投递目标错误执行成功但未收到消息检查 deliver 配置和平台连接
脚本路径错误"Script not found" 错误确认脚本在 ~/.hermes/scripts/
API Key 过期"Authentication failed"更新 .env 中的 API Key
不活跃超时"Cron job timed out"增大 HERMES_CRON_TIMEOUT
锁文件残留任务不执行(上次 tick 崩溃)删除 ~/.hermes/cron/.tick.lock
# 清理残留锁(安全的操作)
rm ~/.hermes/cron/.tick.lock

5.6 内存消耗过高

症状:系统内存不足,OOM Killer 终止进程,系统变慢

排查步骤

# 1. 监控内存使用趋势
watch -n 5 'ps aux | grep hermes | head -5'

# 2. 检查上下文大小(代理估算)
grep "prompt_tokens" ~/.hermes/logs/agent.log | tail -5

# 3. 检查并发会话数(Gateway)
grep "active sessions" ~/.hermes/logs/gateway.log | tail -5

# 4. 检查系统内存压力
dmesg | grep -i "oom"

调优建议

  • 限制 max_iterations(默认 90)减少长会话的内存累积
  • 配置更积极的压缩阈值(threshold_percent: 0.40
  • 限制 Gateway 并发会话数
  • 使用较小的模型(减少每 token 的内存开销)
  • 增加系统 swap 空间作为紧急缓冲

6. 多环境配置

6.1 Profile 系统

Hermes Agent 支持 Profile(配置文件隔离),每个 Profile 有独立的:

  • 配置文件(config.yaml)
  • 记忆文件(MEMORY.md / USER.md)
  • 技能目录(skills/)
  • 环境变量(.env)
  • 会话数据库(sessions/)
# 创建新 Profile(用于生产环境)
hermes profile create production

# 切换 Profile
hermes profile switch production

# 查看所有 Profile
hermes profile list

# 在特定 Profile 下运行
hermes --profile production chat

Profile 的实际目录位于 ~/.hermes/profiles/<name>/,切换 Profile 只是改变 HERMES_HOME 环境变量的指向。

6.2 环境变量参考

关键环境变量及其作用:

环境变量作用默认值
HERMES_HOME数据目录路径~/.hermes
HERMES_MODEL默认模型config.yaml 中的值
HERMES_INFERENCE_PROVIDER推理 providerauto(自动检测)
HERMES_YOLO_MODE跳过所有审批未设置(不跳过)
HERMES_LOG_LEVEL日志级别INFO
HERMES_PORTGateway 端口5000
HERMES_CRON_TIMEOUTCron 任务不活跃超时600(10 分钟)
HERMES_CRON_SCRIPT_TIMEOUTCron 脚本执行超时120(2 分钟)
HERMES_GATEWAY_SESSION标记 Gateway 会话模式未设置
HERMES_IPV4强制 IPv4false
HERMES_CHECKPOINT_TIMEOUT检查点 git 操作超时30 秒
TIRITH_ENABLED启用/禁用 Tirith 扫描true
TIRITH_BINTirith 二进制路径tirith(自动查找)
DELEGATION_MAX_CONCURRENT_CHILDREN最大并行子 Agent 数3

调试指南

本节列出部署与运维中最关键的故障排查方法。

Gateway 启动失败

症状hermes gateway run 执行后进程立即退出,或 systemctl --user status hermes-gateway 显示 failed

排查步骤

# 查看服务状态和退出码
systemctl --user status hermes-gateway
# 关注 Active 字段和 Exit Code

# 查看启动失败日志
journalctl --user -u hermes-gateway -n 100 --no-pager

# 检查端口占用(常见原因:5000 端口已被占用)
ss -tlnp | grep 5000
# 或
lsof -i :5000

# 检查配置文件语法
python3 -c "import yaml; yaml.safe_load(open('/root/.hermes/config.yaml'))"

常见原因:端口 5000 被其他进程占用(如 Flask 开发服务器)、config.yaml 语法错误(YAML 缩进问题)、缺少必要的 API Key、Python 依赖未安装完整。对于端口冲突,可使用 HERMES_PORT=5001 hermes gateway run 临时切换端口。

飞书连接断开

症状:飞书平台不再接收和响应消息,Gateway 日志中出现 WebSocket 连接错误。

排查步骤

# 检查飞书配置
grep -E "FEISHU_APP_ID|FEISHU_APP_SECRET" ~/.hermes/.env

# 测试网络连通性(飞书 API 端点)
curl -s -o /dev/null -w "%{http_code}" https://open.feishu.cn/open-apis/bot/v2/hook/

# 查看 WebSocket 重连日志
grep -i "feishu\|websocket\|reconnect" ~/.hermes/logs/gateway.log | tail -30

# 检查 Gateway 进程是否存活
ps aux | grep hermes

常见原因FEISHU_APP_IDFEISHU_APP_SECRET 配置错误或过期、网络防火墙阻断了 WebSocket 长连接、飞书应用权限未正确配置。Gateway 的平台适配器支持自动重连,但如果凭证无效,重连会反复失败。确认飞书开放平台后台的应用状态是否正常。

服务异常退出

症状:Gateway 进程突然消失,没有正常的关闭日志。

排查步骤

# 检查 OOM killer 日志(最常见原因)
dmesg | grep -i "oom\|killed process" | tail -10
# 或
journalctl -k | grep -i "oom" | tail -10

# 检查 coredump
ls -la /var/lib/apport/coredump/ 2>/dev/null
ulimit -c  # 检查 core dump 是否启用

# 查看 systemd 服务退出详情
systemctl --user status hermes-gateway
# 关注 Exit Code:
#   137 = SIGKILL(通常为 OOM killer)
#   139 = SIGSEGV(段错误)
#   1   = 应用层错误

# 检查系统内存使用历史
sar -r 2>/dev/null | tail -20  # 需要 sysstat 包

常见原因:OOM killer 终止(上下文过大的会话消耗过多内存)、段错误(Python C 扩展崩溃)、systemd 因 MemoryMax=4G 限制杀掉进程。解决方案包括增大 MemoryMax 限制、降低 agent.max_turns、配置更积极的压缩阈值。如果频繁 OOM,考虑拆分为多个 Profile 分散负载。

更新后异常

症状:执行 git pullpip install 更新后,Gateway 启动报错或功能异常。

排查步骤

# 检查是否有未提交的本地更改(可能导致合并冲突)
cd /opt/hermes-agent
git status

# 查看更新内容
git log --oneline -10

# 检查依赖冲突
pip check 2>&1 | head -20

# 查看具体错误日志
journalctl --user -u hermes-gateway --since "5 minutes ago"

常见原因:本地有未提交的修改导致 git pull 合并冲突、新版本引入了不兼容的配置格式变更、pip install 依赖冲突(如两个包要求不同版本的同一依赖)。更新前应先 git stash 保存本地更改,更新后用 git stash pop 恢复。如果依赖冲突严重,尝试 uv pip install -e ".[all]" --force-reinstall。更新后务必检查 CHANGELOG 了解破坏性变更。


思考题

  1. Systemd 用户服务 vs 系统服务:为什么推荐使用 Systemd 用户服务(systemctl --user)而非系统级服务(systemctl)?考虑权限隔离(用户服务以当前用户身份运行,可以访问用户文件)、文件访问(.hermes/ 目录的所有权和权限)和用户注销后的行为(linger 机制)。

  2. 日志中的敏感信息:尽管 Hermes Agent 内置了输出脱敏(redact_sensitive_text),哪些信息可能仍然泄露到日志中?考虑工具调用的参数(如 write_file 的文件路径中可能包含用户名)、API 响应中的元数据、以及错误消息中的堆栈跟踪。如何设计一个更完善的日志脱敏策略?

  3. 多实例部署的会话管理:如果部署多个 Gateway 实例(负载均衡场景),会话状态(审批队列、压缩状态、YOLO 模式)如何共享?当前架构中 _session_approved_gateway_queues 是进程内全局变量,不能跨进程共享。考虑使用 Redis 或数据库作为共享状态存储。

  4. Cron 任务的幂等性advance_next_run() 在执行前就推进了 next_run_at。如果任务执行失败,这个设计会导致跳过调度吗?对于"每隔 5 分钟检查一次"这种任务,如果某次执行失败了,下一次执行会在下一个 5 分钟周期正常触发。但对于"每天早上 9 点发送报告"这种任务,如果执行失败,报告会延迟到第二天。如何确保关键任务不丢失?

  5. 配置热更新的边界:哪些配置可以在运行时更新而无需重启?哪些必须重启才能生效?如果需要实现"零停机"配置更新,应该采用什么策略?考虑 Gateway 的滚动重启(启动新实例、等待旧实例处理完当前请求、关闭旧实例)。


本篇涉及的源文件和配置:

  • Dockerfile — Docker 容器构建
  • run_agent.py — Agent 初始化与生命周期管理
  • gateway/run.py — Gateway 启动与配置加载
  • cron/scheduler.py — Cron 调度、文件锁、不活跃超时
  • hermes_constants.py — 环境变量、路径常量、IPv4 偏好
  • hermes_cli/config.py — 配置文件管理、热更新