现在位置: 首页 > Hermes Agent > 正文

Hermes Agent Session 生命周期与定时任务

Session 重置策略

重置策略控制会话何时自动「失忆」——获得一个新的 session_id,旧的上下文被归档。

合理配置重置策略可以避免 Agent 上下文无限膨胀,同时确保用户体验不受影响。

四种重置模式

模式行为适用场景
none永不自动重置,上下文仅由压缩机制管理需要长期连续上下文的场景
idle闲置超过 N 分钟后自动重置偶尔使用的 Agent
daily每天在指定时间自动重置每日例行使用的 Agent
both闲置超时或每日重置,哪个先触发就执行哪个大多数场景(默认推荐)

配置重置策略

实例

# config.yaml - 全局重置策略
session_reset
:
  mode
: both              # none | idle | daily | both
  at_hour
: 4              # 每日重置时间(凌晨 4 点,本地时间)
  idle_minutes
: 1440      # 闲置超时(1440 分钟 = 24 小时)
  notify
: true            # 重置时通知用户

# 按平台自定义重置策略
platforms
:
  telegram
:
    session_reset
:
      mode
: idle
      idle_minutes
: 720   # Telegram 会话 12 小时闲置后重置
  slack
:
    session_reset
:
      mode
: none          # Slack 会话永不自动重置

重置效果

当会话触发重置时,会发生以下事情:

  • 旧会话在 SQLite 中被标记为结束(reason: "session_reset")
  • 生成新的 session_id(格式:YYYYMMDD_HHMMSS_8位随机hex)
  • 新 SessionEntry 的 was_auto_reset 标记为 true
  • 缓存的 Agent 实例被清理
  • 用户在下一条消息中会收到「会话已重置」的提示

有活跃后台进程的会话永远不会被重置。Hermes 会检查 has_active_processes 回调,确保不会中断正在运行的任务。


重启恢复机制

Hermes Gateway 的重启恢复机制确保在意外崩溃或计划内重启后,正在进行的会话不会丢失。

两种恢复标记

标记触发场景行为严重程度
resume_pending崩溃恢复、drain 超时保留 session_id,下次访问时继续对话软恢复
suspended/stop 命令、3 次连续重启失败强制重置,生成新的 session_id硬重置

启动恢复流程

当 Gateway 启动时,恢复流程如下:

第一步:检查 .clean_shutdown 标记。

如果存在,说明上次是正常关闭,跳过恢复流程。

第二步:如果不存在 .clean_shutdown 标记,说明上次是异常退出。

Gateway 调用 suspend_recently_active(),将最近 120 秒内有活动的会话标记为 resume_pending。

第三步:检测 stuck-loop(卡死循环)。

如果某个会话在连续 3 次重启后仍然处于活跃状态,说明它可能陷入了死循环,Gateway 会将其标记为 suspended。

第四步:恢复待处理会话。

Gateway 为每个 resume_pending 的会话合成一条 MessageEvent,触发 Agent 自动继续。

Drain 超时标记

在正常关闭/重启过程中,如果某个会话正在处理中但超过了 drain 等待时间,Gateway 会将其标记为 resume_pending。

不同场景的标记原因:

标记原因含义
restart_timeout重启过程中 drain 超时
shutdown_timeout关闭过程中 drain 超时
restart_interrupted崩溃恢复(从 suspend_recently_active 触发)

resume_pending 标记不会在 get_or_create_session() 时被清除——它会在下一次成功的 Agent 回复后被清除。如果恢复后的会话再次中断,标记保留,允许下次重启时重试。连续 3 次失败后升级为 suspended。


消息队列机制

当用户在 Agent 处理消息期间连续发送多条消息时,Gateway 的消息队列机制确保消息不会丢失。

队列结构

Gateway 使用两级队列设计:

  • 单槽 pending(_pending_messages):每个会话只有一个「下一条」槽位,重复发送会覆盖
  • 溢出队列(_queued_events):当槽位被占用时,后续消息追加到溢出队列尾部

/queue 命令

/queue 命令让你可以批量提交任务,每个任务都会产生一个完整的 Agent 回合。

实例

# 在 Telegram/Discord 中发送
/queue 审查 src/main.py 的代码风格
/queue 为 src/utils.py 编写单元测试
/queue 更新 README.md 中的安装说明

队列中的每个任务按 FIFO 顺序依次执行,每个任务产生一个完整的 Agent 回合,不会合并。

使用 /new 或 /reset 命令可以清空当前会话的消息队列。

在 Agent 处理消息期间连续发送多条消息,中间的会被覆盖(只保留最后一条),/queue 命令中的消息则不会被覆盖——每个 /queue 任务都会按顺序执行。


定时任务(Cron)

Hermes 内置了 first-class 的定时任务支持,让你可以配置 Agent 定期执行特定任务。

定时任务可以绑定 Skill,并将结果投递到指定平台。

配置定时任务

定时任务在 jobs.json 中定义,支持多种调度格式。

{
  "jobs": [
    {
      "id": "daily-news-summary",
      "schedule": "0 8 * * *",
      "description": "每天早上 8 点抓取 AI 行业新闻并生成摘要",
      "skill": "ai-news-summarizer",
      "deliver_to": {
        "platform": "telegram",
        "chat_id": "-1001234567890"
      }
    },
    {
      "id": "weekly-code-review",
      "schedule": "0 10 * * 1",
      "description": "每周一早上 10 点审查项目代码变更",
      "skill": "code-review-assistant",
      "deliver_to": {
        "platform": "discord",
        "chat_id": "123456789"
      }
    },
    {
      "id": "health-check",
      "schedule": "*/30 * * * *",
      "description": "每 30 分钟检查服务器健康状态",
      "skill": "server-health-checker",
      "deliver_to": {
        "platform": "telegram",
        "chat_id": "123456789"
      }
    }
  ]
}

支持的调度格式

格式示例说明
Cron 表达式0 8 * * *标准 5 段 cron 表达式
间隔30m每 30 分钟
相对时间+90s90 秒后执行一次
重复次数repeat.times: 5执行 5 次后自动停止

可以在桌面版配置, 点击左下角的排程:

点击新建定时任务:

创建任务:

定时任务绑定 Skill 后,执行的输出会自动格式化为 Skill 定义的输出格式。这确保了定时任务的结果在投递到消息平台时,呈现方式一致且可读。


Chronos 托管 Cron(进阶)

Chronos 是 Hermes 的托管式定时任务方案,专为 scale-to-zero 部署模式设计。

当你的 Gateway 在空闲时完全停止运行,Chronos 仍然可以确保定时任务按时触发。

为什么需要 Chronos?

内置的 cron ticker 需要 Gateway 进程持续运行——如果 Gateway 缩容到零,定时任务就不会触发。

Chronos 将定时任务的管理委托给 NAS(Nous Account Service),通过外部调度器在任务触发时唤醒 Gateway。

Chronos 工作流程

Chronos 的工作流程分为四个步骤:

第一步:Agent 计算下次触发时间,向 NAS 注册一个 one-shot 定时器。

第二步:NAS 使用外部调度器(如 Fly Machines 的定时触发)在指定时间触发回调。

第三步:外部调度器回调 NAS,NAS 生成一个短时效的 JWT Token。

第四步:NAS 使用 JWT Token 调用 Agent 的 /api/cron/fire 端点,Agent 验证后执行任务并重新注册下一个 one-shot。

At-most-once 保证

Chronos 通过 store 级的 CAS(Compare-And-Set)操作保证每个定时任务只执行一次。

即使调度器因为网络重试发送了重复的触发请求,Agent 也能通过 CAS 去重,确保任务不会重复执行。

配置 Chronos

实例

# config.yaml - Chronos 托管 Cron 配置
cron
:
  provider
: "chronos"                         # 使用 Chronos 代替内置 ticker
  chronos
:
    portal_url
: "https://portal.nousresearch.com"
    callback_url
: "https://my-agent.fly.dev"  # Agent 的公网可访问 URL
    expected_audience
: "agent:inst_abc123"    # JWT 验证的 audience
    nas_jwks_url
: "https://portal.nousresearch.com/.well-known/jwks.json"

Chronos 是托管 Hermes 部署的推荐定时任务方案。如果你使用自托管部署且 Gateway 不会缩容到零,内置的 cron ticker 完全够用。如果 callback_url 为空或 Agent 没有 Nous 登录,系统会自动回退到内置 ticker。