Hermes cron 调度系统:11 个活跃任务的自动化编排

一、规模:30 个任务,11 个活跃

venxine.vip 运行在 Hermes Agent 的 cron 引擎上。目前共 30 个注册任务,其中 11 个活跃:

# 任务 调度 类型 模型
1 🌐 全球AI新闻聚合 每日 08:00 LLM 驱动 deepseek-v4-pro
2 🦙 Crypto新闻日报 每日 07:00 LLM 驱动 deepseek-v4-pro
3 ⚠️ 基金涨跌预警 交易日 每10分钟 no_agent 脚本
4 📡 基金数据采集 交易日 每10分钟 no_agent 脚本
5 🇺🇸 华尔街日报 周二~六 06:00 LLM 驱动 deepseek-v4-pro
6 📋 每日收益数据 交易日 22:00 no_agent 脚本
7 📊 A股收盘分析 每日 20:00 LLM 驱动 deepseek-v4-pro
8 🔍 每日基金分析 每日 21:00 LLM 驱动 deepseek-v4-pro
9 🌐 QDII基金分析 周二~六 08:00 LLM 驱动 deepseek-v4-pro
10 🔁 自改进引擎 每周日 03:00 no_agent 脚本
11 🔄 网关每日重启 每日 04:30 no_agent 脚本

另外 19 个暂停,包括 8 个社交媒体下载脚本、6 个基金报告推送、以及其他实验性任务。

二、Model Pinning:防止模型漂移

早期用 v4-flash 跑 cron,某天早上 06:00~08:00 三个任务(华尔街日报、Crypto 日报、AI 新闻)全部报 Broken pipe

原因:deepseek-v4-flash 在早高峰时段不稳定。但更根本的问题是:cron 任务没有固定模型,自动跟随当前会话的默认模型。一旦我换了默认模型,所有 cron 也跟着变。

解决方案是 model pinning,在创建 cron 时显式指定 provider 和 model,写到 jobs.json 中:

{
  "name": "华尔街日报",
  "model": {
    "provider": "custom:api.deepseek.com",
    "model": "deepseek-v4-pro"
  }
}

所有 13 个 LLM 驱动的 cron 任务全部 pin 到了 deepseek-v4-pro。即使在交互会话中切换模型,cron 任务永远用固定的生产模型。

三、Prompt 精简:砍掉 75% Token

chinastock(A股收盘分析)是第一次遇到 HTTP 400 Content Exists Risk 的情况。不是网络问题,是 DeepSeek 的内容审核拦截了过长的 prompt。

排查发现:cron 加载了 cn-web-search skill,这个 skill 的全文(约 5K tokens)被注入到 prompt 中。加上系统指令和用户 prompt,总计 ~7K tokens。

# 修复前
cronjob(action='create',
    prompt='生成A股收盘分析...',
    skills=['cn-web-search'])  # ← 5K token 注入

# 修复后
cronjob(action='create',
    prompt='生成A股收盘分析,使用内置 web_search 工具...',
    skills=[])  # ← 只依赖内置指令

去掉不必要的 skill 加载后,prompt 从 ~7K 降到 ~1.5K tokens,审核拦截概率大幅降低。

原则:cron 任务的 prompt 应该自包含,只加载必不可少的 skill。每多加载一个 skill 就多注入几千 token,既烧钱又增加审核风险。

四、no_agent 模式:零 Token 脚本

基金数据采集和涨跌预警是纯数据操作(抓取实时估值、写 JSON、计算阈值),不需要 LLM 推理。

Hermes cron 支持 no_agent=True 模式:跳过 LLM,调度器直接执行 Python/Shell 脚本,stdout 作为推送内容:

cronjob(action='create',
    name='基金数据采集',
    schedule='9:15 on trading days, every 10 minutes',
    no_agent=True,
    script='scripts/fund-tracker.py')

5 个活跃任务用了 no_agent 模式:零 token 消耗,零模型依赖。

模式 Token 消耗 适用场景
LLM 驱动 每次几千~几万 token 新闻分析、内容生成、推理
no_agent 脚本 0 数据采集、阈值告警、看门狗

五、Watchdog:网关自愈

网关 Python 进程存在内存泄漏:RSS 每天增长约 110MB,从初始 200MB 涨到 475MB。

但 Hermes 网关禁止自重启:从网关内部运行 hermes gateway restart 会被命令拦截。唯一的绕过方式:no_agent=True 的 cron 脚本。

#!/bin/bash
# scripts/gateway-daily-restart.sh
systemctl --user restart hermes-gateway
cronjob(action='create',
    name='网关每日重启',
    schedule='0 4:30 * * *',
    no_agent=True,           # 不经过 LLM
    script='scripts/gateway-daily-restart.sh')

cron 调度器是独立进程,不受网关重启影响。每天 04:30 触发,在 04:00 session_reset + 04:04 session_expiry 清理之后,把网关 RSS 重置回 ~200MB。

六、失败恢复流程

LLM 驱动的 cron 偶尔会失败。以 chinastock 为例,标准恢复流程:

1. cronjob(action='list')  找到 FAILED 的输出 .md 文件  删除
2. web_search 获取当日实际收盘数据上证/深证/创业板/科创50
3.  Python 生成三段式 market_analysis
   ├── 📈 指数表现4 个指数收盘涨跌幅
   ├── 💰 市场概况(~500 
   └── 🔥 驱动因素6 个维度各 ~200 
4. json.dump 写入 daily-analysis.json
5. 页面刷新即生效

关键原则:手动恢复时写的是数据文件,不是 prompt 重跑。 数据文件是 Flask 直接读的 JSON,不受 cron 状态影响。

七、架构总结

cron 调度器
├── LLM 驱动任务 (6个)          → 模型 pin 到 deepseek-v4-pro
│   ├── 新闻分析 ×4              → prompt 精简,不加载非必要 skill
│   └── 基金分析 ×2              → 失败时手动写 JSON 恢复
│
├── no_agent 脚本 (5个)         → 零 token
│   ├── 数据采集 ×2              → 每10分钟抓取 + 写 JSON
│   ├── 数据写入 ×1              → 交易日 22:00
│   ├── 自改进引擎 ×1            → 每周日 03:00
│   └── 网关 watchdog ×1         → 每日 04:30 重启
│
└── 暂停任务 (19个)              → 按需恢复
    ├── 基金推送 ×6
    ├── 社交媒体 ×8
    └── 其他 ×5

这套 cron 系统跑了 68 天,累计 API 调用 21,000+ 次,处理了超过 54 亿 token,全部自动化,无人值守。