在前一篇文章中,我们全面掌握了 Hermes Agent 的 Slash 命令与 TUI 交互体系。你学会了如何高效地管理会话、控制 Agent 行为、调整运行时配置。这让你的**交互式使用体验**达到了一个全新的高度。

Cron 定时任务 —— 调度表达式、Job 配置、脚本模式、自动跑任务

简介

在前一篇文章中,我们全面掌握了 Hermes Agent 的 Slash 命令与 TUI 交互体系。你学会了如何高效地管理会话、控制 Agent 行为、调整运行时配置。这让你的交互式使用体验达到了一个全新的高度。

但今天我们要讨论一个更重要的问题:

当你在睡觉的时候,Agent 在做什么?

想象以下场景:

  • 每天早晨 8 点,你希望 Hermes 自动检查 GitHub 上的 PR,生成一份代码审查摘要,发送到你的 Telegram
  • 每小时,你希望它扫描服务器的错误日志,发现异常模式后第一时间通知你
  • 每周五下午 5 点,你希望它自动生成一份本周的项目进度报告
  • 每 30 分钟,你希望它检查 API 的健康状态,发现问题立即告警

这些都不是"对话"能解决的问题。这是自动化的需求。

这就是 Hermes Agent 的 Cron 定时任务系统 存在的意义。

Cron 定时任务让 Hermes 从一个"你问它答"的被动工具,升级为一个自主运行的智能代理。它可以在指定的时间自动触发,执行预定义的任务,并将结果发送到你指定的平台。

本文将带你全面掌握 Hermes Agent 的 Cron 系统:

  • 调度表达式:从标准 Cron 到 Hermes 的扩展语法
  • Job 配置:如何定义任务、设置触发条件、处理输出
  • 脚本模式:让 Agent 执行复杂的自动化工作流
  • 自动跑任务实战:从简单到复杂的真实场景

读完本文后,你将能够让 Hermes Agent 成为你 24/7 的自动化工友。

目录

Cron 系统架构概述

为什么需要 Cron?

Hermes Agent 的核心能力在于其智能推理和工具执行。但这些能力默认是被动触发的——你发送消息,Agent 响应。

Cron 系统补上了最后一块拼图:主动触发

text
┌────────────────────────────────────────────────────────┐
│              Hermes Agent 触发模式                       │
│                                                        │
│  ┌──────────────┐          ┌──────────────────────┐    │
│  │  被动触发     │          │     主动触发          │    │
│  │  (Reactive)  │          │     (Proactive)       │    │
│  │              │          │                       │    │
│  │  • 用户消息   │          │  • Cron 定时任务      │    │
│  │  • API 调用   │          │  • Webhook 事件      │    │
│  │  • Webhook   │          │  • 事件订阅           │    │
│  │              │          │                       │    │
│  │  "你问它答"   │          │  "它主动工作"         │    │
│  └──────────────┘          └──────────────────────┘    │
│                                                        │
└────────────────────────────────────────────────────────┘

Cron 架构组件

text
┌─────────────────────────────────────────────────────┐
│                  Cron 调度引擎                        │
│                                                     │
│  ┌───────────────────────────────────────────────┐  │
│  │               调度器 (Scheduler)               │  │
│  │                                               │  │
│  │  • 解析 Cron 表达式                            │  │
│  │  • 计算下次触发时间                             │  │
│  │  • 管理触发队列                                 │  │
│  │  • 处理时区和夏令时                             │  │
│  └───────────────────┬───────────────────────────┘  │
│                      │                              │
│         ┌────────────┼────────────┐                 │
│         ▼            ▼            ▼                 │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐            │
│  │  Job 1   │ │  Job 2   │ │  Job 3   │  ...       │
│  │ 代码审查  │ │ 日志分析  │ │ 报告生成  │            │
│  └────┬─────┘ └────┬─────┘ └────┬─────┘            │
│       │            │            │                   │
│       └────────────┼────────────┘                   │
│                    ▼                                │
│  ┌───────────────────────────────────────────┐     │
│  │           执行引擎 (Executor)              │     │
│  │                                           │     │
│  │  • 创建 Agent 实例                         │     │
│  │  • 注入上下文和参数                        │     │
│  │  • 执行 Prompt                             │     │
│  │  • 处理工具调用                            │     │
│  │  • 收集输出                                │     │
│  └───────────────────┬───────────────────────┘     │
│                      │                              │
│         ┌────────────┼────────────┐                 │
│         ▼            ▼            ▼                 │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐            │
│  │  输出到   │ │  输出到   │ │  输出到   │            │
│  │  Telegram │ │  文件    │ │  Webhook │            │
│  └──────────┘ └──────────┘ └──────────┘            │
│                                                     │
└─────────────────────────────────────────────────────┘

Cron 与 Gateway 的关系

Cron 系统运行在 Gateway 进程内部,是 Gateway 的一个子模块:

bash
# 查看 Gateway 状态(包含 Cron 信息)
hermes gateway status
# → Gateway Status: running
#   PID: 12345
#   Uptime: 3d 14h 22m
#   Active Platforms: wechat, telegram, discord
#   Active Sessions: 12
#   Cron Jobs: 5 (3 active, 2 paused)
#   Next Trigger: "daily-pr-review" in 4h 32m

调度表达式详解

标准 Cron 语法

Hermes 完全兼容标准 Cron 表达式:

text
┌───────────── 分钟 (0 - 59)
│ ┌───────────── 小时 (0 - 23)
│ │ ┌───────────── 日 (1 - 31)
│ │ │ ┌───────────── 月 (1 - 12)
│ │ │ │ ┌───────────── 星期 (0 - 6, 0=周日)
│ │ │ │ │
* * * * *

常用表达式速查

bash
# 每分钟执行
* * * * *

# 每 5 分钟执行
*/5 * * * *

# 每小时执行
0 * * * *

# 每天凌晨 2 点执行
0 2 * * *

# 每周一上午 9 点执行
0 9 * * 1

# 每月 1 号凌晨执行
0 0 1 * *

# 工作日(周一到周五)每天上午 9 点执行
0 9 * * 1-5

# 每天早上 9 点和下午 5 点执行
0 9,17 * * *

# 工作日每 30 分钟执行
*/30 9-17 * * 1-5

# 每季度第一天执行
0 0 1 1,4,7,10 *

预定义快捷表达式

yaml
# 快捷表达式(@开头)
@hourly      # 等同于 0 * * * *
@daily       # 等同于 0 0 * * *(每天午夜)
@weekly      # 等同于 0 0 * * 0(每周日午夜)
@monthly     # 等同于 0 0 1 * *(每月 1 号午夜)
@yearly      # 等同于 0 0 1 1 *(每年 1 月 1 日午夜)
@every_5m    # 每 5 分钟
@every_15m   # 每 15 分钟
@every_30m   # 每 30 分钟
@every_1h    # 每小时
@every_6h    # 每 6 小时

Hermes 扩展语法

标准 Cron 在某些场景下不够用。Hermes 在此基础上做了扩展:

1. 秒级精度

yaml
# 标准 Cron 只支持分钟级精度
# Hermes 扩展:6 字段格式支持秒级

# 每 30 秒执行一次
*/30 * * * * *

# 每天 8:30:00 执行
0 30 8 * * *

2. 特殊时间修饰符

yaml
# 工作日(周一到周五)
0 9 * * WORKDAY

# 周末(周六和周日)
0 10 * * WEEKEND

# 交易日(排除节假日)
0 9 * * TRADING_DAY

# 自定义排除日期
0 9 * * * EXCLUDE:2025-01-01,2025-05-01,2025-10-01

3. 区间和步进

yaml
# 9 点到 18 点之间,每 2 小时执行
0 9-18/2 * * *

# 每月 1-15 号,每天执行
0 0 1-15 * *

# 每 3 个月执行(1月、4月、7月、10月)
0 0 1 1-12/3 *

4. 随机延迟

对于大批量定时任务,Hermes 支持随机延迟以避免同时触发:

yaml
# 每天午夜执行,随机延迟 0-300 秒
0 0 * * * RANDOM:0-300

# 每小时执行,随机延迟 0-60 秒
0 * * * * RANDOM:0-60

5. 条件触发

yaml
# 仅在文件存在时触发
0 9 * * * IF_FILE:/tmp/trigger.flag

# 仅在环境变量为 true 时触发
0 9 * * * IF_ENV:ENABLED=true

# 仅在 API 返回 200 时触发
0 9 * * * IF_HTTP:https://api.example.com/health=200

Job 配置详解

基础 Job 配置

Cron Job 的配置文件位于 ~/.config/hermes/cron-jobs.yaml

yaml
# ~/.config/hermes/cron-jobs.yaml
cron:
  timezone: "Asia/Shanghai"    # 全局时区设置

  jobs:
    # ─────────────────────────────────────
    # Job 1: 每日 PR 审查摘要
    # ─────────────────────────────────────
    - name: "daily-pr-review"
      description: "每天审查 GitHub 上的 PR 并生成摘要"

      # 调度配置
      schedule:
        cron: "0 8 * * 1-5"           # 工作日早上 8 点
        timezone: "Asia/Shanghai"

      # 执行配置
      execution:
        provider: "openai"
        model: "gpt-4o"
        max_tokens: 4096
        temperature: 0.3

        # Prompt 模板
        prompt: |
          请执行以下任务:

          1. 使用 terminal 工具运行: git fetch origin
          2. 列出最近 24 小时内创建或更新的所有 PR:
             gh pr list --state open --json number,title,author,createdAt,updatedAt
          3. 对每个 PR,获取详细信息:
             gh pr view <number> --json body,files,commits
          4. 审查代码变更,关注以下方面:
             - 代码质量和最佳实践
             - 潜在的安全问题
             - 测试覆盖情况
             - 性能影响
          5. 生成一份结构化的审查报告,包含:
             - PR 概览
             - 每个 PR 的审查意见
             - 优先级排序的建议
             - 需要人工复核的项目

          报告格式使用 Markdown,保持简洁明了。

      # 输出配置
      output:
        # 发送到 Telegram
        - type: "telegram"
          chat_id: "-100987654321"
          parse_mode: "MarkdownV2"

        # 同时保存到文件
        - type: "file"
          path: "~/reports/pr-review/{{date('%Y-%m-%d')}}.md"

      # 通知配置
      notification:
        on_success: true       # 成功时通知
        on_failure: true       # 失败时通知
        on_empty: false        # 无结果时不通知

      # 启用状态
      enabled: true

    # ─────────────────────────────────────
    # Job 2: 错误日志扫描
    # ─────────────────────────────────────
    - name: "error-log-scan"
      description: "每小时扫描应用错误日志"

      schedule:
        cron: "0 * * * *"
        timezone: "Asia/Shanghai"

      execution:
        provider: "anthropic"
        model: "claude-sonnet-4"
        max_tokens: 2048
        temperature: 0.1

        prompt: |
          执行以下任务:

          1. 读取最近 1 小时的应用日志:
             tail -n 5000 /var/log/app/production.log | grep "$(date -d '1 hour ago' '+%Y-%m-%d %H')"
          2. 分析日志中的 ERROR  WARN 级别的条目
          3. 识别以下模式:
             - 重复出现的错误(频率 > 10 次/小时)
             - 新增的错误类型(之前未出现过)
             - 关键路径上的错误(支付、认证等)
          4. 对每个识别到的问题,给出:
             - 错误类型和频率
             - 可能的原因分析
             - 建议的修复方案
             - 严重程度(P0/P1/P2/P3)

          如果发现 P0  P1 级别的问题,在报告开头用 ⚠️ 标注。
          如果没有严重问题,回复 "✅ 系统运行正常" 即可。

      output:
        - type: "telegram"
          chat_id: "-100987654321"
        - type: "webhook"
          url: "https://hooks.slack.com/services/T00/B00/XXX"
          format: "slack"

      enabled: true

    # ─────────────────────────────────────
    # Job 3: 周报生成
    # ─────────────────────────────────────
    - name: "weekly-report"
      description: "每周五生成项目周报"

      schedule:
        cron: "0 17 * * 5"
        timezone: "Asia/Shanghai"

      execution:
        provider: "openai"
        model: "gpt-4o"
        max_tokens: 8192
        temperature: 0.5

        # 使用脚本模式(详见下文)
        mode: "script"
        script: "~/.hermes/scripts/weekly-report.py"

      output:
        - type: "telegram"
          chat_id: "-100987654321"
        - type: "file"
          path: "~/reports/weekly/{{date('%Y-W%V')}}.md"
        - type: "email"
          to: "team@example.com"
          subject: "项目周报 - {{date('%Y-%m-%d')}}"

      enabled: true

Job 配置项详解

yaml
# 完整的 Job 配置项
jobs:
  - name: "job-name"                  # 唯一标识符
    description: "Job 描述"           # 人类可读的描述

    # 调度配置
    schedule:
      cron: "0 8 * * 1-5"            # Cron 表达式(必填)
      timezone: "Asia/Shanghai"       # 时区(可选,默认取全局)

    # 执行配置
    execution:
      provider: "openai"              # 使用的 Provider
      model: "gpt-4o"                # 使用的模型
      max_tokens: 4096               # 最大输出 Token 数
      temperature: 0.3               # 温度(0-1)
      timeout: 300                   # 执行超时(秒)
      retry:                         # 重试配置
        max_attempts: 3              # 最大重试次数
        backoff: "exponential"       # exponential | linear | fixed
        delay: 60                    # 初始延迟(秒)

      # Prompt 或脚本(二选一)
      prompt: |                      # 直接指定 Prompt
        请执行以下任务...
      # 或
      mode: "script"                 # 使用脚本模式
      script: "path/to/script.py"    # 脚本路径

    # 输出配置
    output:
      - type: "telegram"             # 输出目标
        chat_id: "..."
        parse_mode: "MarkdownV2"
      - type: "file"
        path: "path/to/output.md"
      - type: "webhook"
        url: "https://..."

    # 通知配置
    notification:
      on_success: true
      on_failure: true
      on_empty: false

    # 上下文注入
    context:
      env_vars:                      # 注入的环境变量
        GITHUB_TOKEN: "${GITHUB_TOKEN}"
        DATABASE_URL: "${DATABASE_URL}"
      files:                         # 注入的文件内容
        config.yaml: "~/.config/app/config.yaml"

    # 启用状态
    enabled: true                    # 是否启用

管理 Cron Job

bash
# 列出所有 Job
hermes cron list
# → ┌────┬──────────────────┬────────────┬────────┬───────────────────┐
#   │ #  │ 名称             │ 调度表达式  │ 状态   │ 下次执行          │
#   ├────┼──────────────────┼────────────┼────────┼───────────────────┤
#   │  1 │ daily-pr-review  │ 0 8 * * 1-5│ ✅ 活跃│ 明天 08:00        │
#   │  2 │ error-log-scan   │ 0 * * * *  │ ✅ 活跃│ 下一小时整点      │
#   │  3 │ weekly-report    │ 0 17 * * 5 │ ⏸️ 暂停│ 周五 17:00        │
#   └────┴──────────────────┴────────────┴────────┴───────────────────┘

# 启用/暂停 Job
hermes cron enable daily-pr-review
hermes cron pause weekly-report

# 手动触发 Job
hermes cron run error-log-scan
# → 正在执行 error-log-scan...
# → 执行完成 ✅
# → 输出已发送到 telegram

# 查看 Job 历史
hermes cron history error-log-scan --limit 10
# → ┌────┬─────────────────────┬─────────┬─────────────────────────┐
#   │ #  │ 执行时间            │ 状态    │ 详情                    │
#   ├────┼─────────────────────┼─────────┼─────────────────────────┤
#   │  1 │ 2025-05-22 15:00:00 │ ✅ 成功 │ Token: 2,340 | 耗时: 12s│
#   │  2 │ 2025-05-22 14:00:00 │ ✅ 成功 │ Token: 1,890 | 耗时: 8s │
#   │  3 │ 2025-05-22 13:00:00 │ ❌ 失败 │ Timeout after 300s      │
#   │  4 │ 2025-05-22 12:00:00 │ ✅ 成功 │ Token: 3,120 | 耗时: 18s│
#   └────┴─────────────────────┴─────────┴─────────────────────────┘

# 删除 Job
hermes cron delete old-job-name

# 添加 Job
hermes cron add --file ./my-job.yaml

脚本模式

简单的 Prompt 模板适合线性任务,但复杂的工作流需要更灵活的控制。Hermes 的脚本模式允许你用 Python 脚本定义完整的自动化工作流。

脚本模式基础

python
# ~/.hermes/scripts/weekly-report.py
"""
每周项目报告生成脚本
每周五 17:00 自动执行
"""

from hermes.cron import CronScript
import subprocess
from datetime import datetime, timedelta

class WeeklyReportScript(CronScript):
    """周报生成脚本"""

    def setup(self):
        """初始化配置"""
        self.report_date = datetime.now()
        self.week_start = self.report_date - timedelta(days=self.report_date.weekday())
        self.week_end = self.week_start + timedelta(days=6)

        # 设置 Agent 配置
        self.agent_config = {
            "provider": "openai",
            "model": "gpt-4o",
            "temperature": 0.5,
            "max_tokens": 8192,
        }

    def run(self):
        """主执行逻辑"""
        # 步骤 1: 收集 Git 数据
        git_commits = self.get_git_commits()
        git_stats = self.get_git_stats()

        # 步骤 2: 收集 Jira/Issue 数据
        issues = self.get_open_issues()
        completed = self.get_completed_issues()

        # 步骤 3: 收集 CI/CD 数据
        build_status = self.get_build_status()
        deployment_status = self.get_deployment_status()

        # 步骤 4: 构建 Prompt
        prompt = self.build_prompt(
            git_commits=git_commits,
            git_stats=git_stats,
            issues=issues,
            completed=completed,
            build_status=build_status,
            deployment_status=deployment_status,
        )

        # 步骤 5: 调用 Agent 生成报告
        report = self.agent.generate(prompt, **self.agent_config)

        # 步骤 6: 后处理
        report = self.post_process(report)

        return report

    def get_git_commits(self):
        """获取本周的 Git 提交记录"""
        result = subprocess.run(
            ["git", "log",
             f"--since={self.week_start.strftime('%Y-%m-%d')}",
             f"--until={self.week_end.strftime('%Y-%m-%d')}",
             "--oneline", "--all"],
            capture_output=True, text=True
        )
        return result.stdout

    def get_git_stats(self):
        """获取 Git 统计信息"""
        result = subprocess.run(
            ["git", "shortlog", "-sn",
             f"--since={self.week_start.strftime('%Y-%m-%d')}"],
            capture_output=True, text=True
        )
        return result.stdout

    def get_open_issues(self):
        """获取未关闭的 Issue"""
        result = subprocess.run(
            ["gh", "issue", "list", "--state", "open",
             "--json", "number,title,assignees,labels"],
            capture_output=True, text=True
        )
        return result.stdout

    def get_completed_issues(self):
        """获取本周关闭的 Issue"""
        result = subprocess.run(
            ["gh", "issue", "list", "--state", "closed",
             "--json", "number,title,closedAt",
             "--search", f"closed:>{self.week_start.strftime('%Y-%m-%d')}"],
            capture_output=True, text=True
        )
        return result.stdout

    def get_build_status(self):
        """获取构建状态"""
        result = subprocess.run(
            ["gh", "run", "list", "--limit", "10",
             "--json", "conclusion,name,createdAt"],
            capture_output=True, text=True
        )
        return result.stdout

    def get_deployment_status(self):
        """获取部署状态"""
        # 实现部署状态获取逻辑
        pass

    def build_prompt(self, **kwargs):
        """构建生成报告的 Prompt"""
        return f"""你是项目管理助手,请根据以下数据生成本周项目报告({self.week_start.strftime('%m/%d')} - {self.week_end.strftime('%m/%d')}):

## Git 提交统计
{kwargs['git_stats']}

## 最近提交
{kwargs['git_commits']}

## 未关闭 Issue
{kwargs['issues']}

## 本周关闭 Issue
{kwargs['completed']}

## 构建状态
{kwargs['build_status']}

请生成一份结构化的周报,包含:
1. **本周概述**:2-3 句话总结本周进展
2. **完成的工作**:按模块分类列出完成的事项
3. **进行中的工作**:当前正在进行的工作和预计完成时间
4. **问题和风险**:需要关注的潜在问题
5. **下周计划**:基于当前进度的下周工作计划
6. **关键指标**:提交数、关闭 Issue 数、构建成功率等

格式使用 Markdown,保持简洁专业。"""

    def post_process(self, report):
        """后处理报告内容"""
        # 添加报告头
        header = f"# 项目周报\n\n**周期**: {self.week_start.strftime('%Y-%m-%d')}{self.week_end.strftime('%Y-%m-%d')}\n"
        header += f"**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n---\n\n"
        return header + report

# 注册脚本
script = WeeklyReportScript()

脚本模式的配置文件

yaml
# ~/.hermes/cron-jobs.yaml 中的脚本模式 Job
jobs:
  - name: "weekly-report"
    schedule:
      cron: "0 17 * * 5"

    execution:
      mode: "script"
      script: "~/.hermes/scripts/weekly-report.py"

      # 脚本参数
      args:
        --project: "my-project"
        --format: "markdown"

      # 环境变量
      env:
        GITHUB_TOKEN: "${GITHUB_TOKEN}"
        DATABASE_URL: "${DATABASE_URL}"
        WORKSPACE: "/path/to/project"

      # 工作目录
      workdir: "/path/to/project"

      # 超时
      timeout: 600

    output:
      - type: "telegram"
        chat_id: "-100987654321"
      - type: "file"
        path: "~/reports/weekly/{{date('%Y-W%V')}}.md"

脚本 API 参考

python
from hermes.cron import CronScript

class MyScript(CronScript):
    def run(self):
        # ── Agent 调用 ──
        # 简单的 Prompt 调用
        result = self.agent.generate("分析这段代码...", model="gpt-4o")

        # 带工具的调用
        result = self.agent.generate(
            "查看当前目录的文件结构",
            tools=["terminal", "read_file", "search_files"],
            model="claude-sonnet-4"
        )

        # 多轮对话
        messages = [
            {"role": "system", "content": "你是一个资深的代码审查员"},
            {"role": "user", "content": "审查这个 PR..."},
        ]
        result = self.agent.chat(messages)

        # ── 工具调用 ──
        # 直接调用工具
        files = self.tools.search_files(pattern="*.py")
        content = self.tools.read_file("main.py")
        output = self.tools.terminal("git status")

        # ── 文件操作 ──
        self.files.write("output.md", result)
        content = self.files.read("output.md")

        # ── HTTP 请求 ──
        response = self.http.get("https://api.example.com/data")
        response = self.http.post("https://api.example.com/notify", json={"message": "done"})

        # ── 日志 ──
        self.logger.info("任务开始")
        self.logger.warning("发现潜在问题")
        self.logger.error("执行失败", exc_info=True)

        # ── 返回值 ──
        return result  # 返回值会作为 Job 输出

任务执行与输出处理

执行流程

text
Cron 触发
    │
    ▼
┌──────────────┐
│  加载 Job 配置 │
└──────┬───────┘
       │
       ▼
┌──────────────┐     否
│  检查 enabled? │──────→ 跳过(记录日志)
└──────┬───────┘
       │ 是
       ▼
┌──────────────┐     否
│  检查条件?    │──────→ 跳过(记录日志)
│ (IF_FILE 等)  │
└──────┬───────┘
       │ 是
       ▼
┌──────────────┐
│  创建 Agent   │
│  实例         │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  注入上下文   │
│ (env, files) │
└──────┬───────┘
       │
       ▼
┌──────────────┐     ┌──────────────┐
│  执行 Prompt  │────▶│  工具调用循环 │
│  / 脚本       │     │  (Agent Loop) │
└──────┬───────┘     └──────────────┘
       │
       ▼
┌──────────────┐
│  后处理输出   │
│ (format)     │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  分发输出     │
│ (多目标)     │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  记录执行历史 │
│  & 发送通知   │
└──────────────┘

输出目标详解

yaml
output:
  # ── 发送到消息平台 ──
  - type: "telegram"
    chat_id: "-100987654321"
    parse_mode: "MarkdownV2"
    disable_web_page_preview: true

  - type: "wechat"
    chat_id: "room_xyz789"

  - type: "discord"
    channel_id: "123456789"
    thread_name: "自动化报告"  # 可选:创建线程

  # ── 发送到文件 ──
  - type: "file"
    path: "~/reports/{{name}}-{{date('%Y-%m-%d')}}.md"
    # 路径模板变量:
    #   {{name}}      - Job 名称
    #   {{date('%Y-%m-%d')}} - 当前日期
    #   {{timestamp}} - Unix 时间戳

  # ── 发送到 Webhook ──
  - type: "webhook"
    url: "https://hooks.slack.com/services/T00/B00/XXX"
    method: "POST"
    headers:
      Content-Type: "application/json"
    format: "slack"  # slack | generic | custom
    # generic 格式:
    #   {"content": "<输出内容>"}
    # custom 格式:
    body_template: '{"text": "{{output}}", "channel": "#reports"}'

  # ── 发送到邮箱 ──
  - type: "email"
    to: "team@example.com"
    cc: "manager@example.com"
    subject: "日报 - {{date('%Y-%m-%d')}}"
    format: "html"  # html | text

  # ── 保存到数据库 ──
  - type: "database"
    connection: "postgresql://user:pass@localhost/reports"
    table: "cron_outputs"
    columns:
      job_name: "{{name}}"
      executed_at: "{{timestamp}}"
      content: "{{output}}"
      status: "{{status}}"

自动跑任务实战

实战 1:每日构建检查

yaml
# 每天早上 9 点检查最近的 CI 构建状态
jobs:
  - name: "daily-build-check"
    description: "每日构建状态检查"
    schedule:
      cron: "0 9 * * 1-5"
      timezone: "Asia/Shanghai"

    execution:
      provider: "openai"
      model: "gpt-4o-mini"
      max_tokens: 2048
      temperature: 0.1

      prompt: |
        执行以下 CI/CD 检查任务:

        1. 检查最近 24 小时内的所有 GitHub Actions 运行:
           gh run list --limit 20 --json conclusion,name,createdAt,databaseId
        2. 识别失败的构建:
           gh run list --status failure --limit 5
        3. 对每个失败的构建,获取失败日志的摘要:
           gh run view <id> --log-failed
        4. 分析失败原因,分类为:
           - 测试失败
           - 编译错误
           - 部署失败
           - 超时/基础设施问题
        5. 生成报告

        如果所有构建都通过了,只回复 "✅ 所有构建正常通过"
        如果有失败,列出失败构建、原因分析和建议修复步骤。

    output:
      - type: "telegram"
        chat_id: "-100987654321"

    notification:
      on_success: false    # 正常时不打扰
      on_failure: true     # 失败时通知
      on_empty: false

实战 2:定期安全扫描

yaml
jobs:
  - name: "security-scan"
    description: "每日安全扫描"
    schedule:
      cron: "0 3 * * *"
      timezone: "Asia/Shanghai"

    execution:
      provider: "anthropic"
      model: "claude-sonnet-4"
      max_tokens: 4096
      temperature: 0.1

      prompt: |
        执行安全扫描任务:

        1. 运行依赖安全检查:
           npm audit --json
           pip-audit --format json
        2. 运行代码安全扫描:
           bandit -r src/ -f json
           semgrep --config=auto src/ --json
        3. 检查 Docker 镜像漏洞:
           trivy image myapp:latest --format json
        4. 汇总所有扫描结果
        5. 按严重程度排序发现的问题
        6. 对每个问题提供:
           - 漏洞描述
           - CVSS 评分
           - 影响的组件
           - 修复建议
           - 修复优先级

        生成一份安全报告,包含:
        - 总览(高危/中危/低危数量)
        - 详细问题列表
        - 修复行动计划

        ⚠️ 如果发现高危漏洞(CVSS  9.0),在报告开头用醒目标注。

    output:
      - type: "telegram"
        chat_id: "-100987654321"
      - type: "file"
        path: "~/reports/security/{{date('%Y-%m-%d')}}.md"
      - type: "webhook"
        url: "https://hooks.slack.com/services/T00/B00/SECURITY"
        format: "slack"

    notification:
      on_success: true
      on_failure: true
      on_empty: false

实战 3:自动化数据报告

yaml
jobs:
  - name: "daily-metrics-report"
    description: "每日业务指标报告"
    schedule:
      cron: "0 10 * * *"
      timezone: "Asia/Shanghai"

    execution:
      mode: "script"
      script: "~/.hermes/scripts/metrics-report.py"
      env:
        DATABASE_URL: "${DATABASE_URL}"
        API_KEY: "${ANALYTICS_API_KEY}"

    output:
      - type: "telegram"
        chat_id: "-100987654321"
      - type: "email"
        to: "management@example.com"
        subject: "日报 - {{date('%Y-%m-%d')}}"

    notification:
      on_success: true
      on_failure: true
python
# ~/.hermes/scripts/metrics-report.py
"""
每日业务指标报告生成
"""
from hermes.cron import CronScript
import subprocess
import json
from datetime import datetime, timedelta

class MetricsReportScript(CronScript):
    def run(self):
        yesterday = datetime.now() - timedelta(days=1)

        # 获取数据库指标
        metrics = self.get_db_metrics(yesterday)

        # 获取 API 指标
        api_metrics = self.get_api_metrics(yesterday)

        # 让 Agent 分析趋势并生成报告
        prompt = f"""你是数据分析助手,请分析以下昨日({yesterday.strftime('%Y-%m-%d')})业务指标:

## 核心指标
- 活跃用户: {metrics['active_users']} (环比 {metrics['active_users_change']:+.1f}%)
- 新增用户: {metrics['new_users']} (环比 {metrics['new_users_change']:+.1f}%)
- 订单数: {metrics['orders']} (环比 {metrics['orders_change']:+.1f}%)
- 营收: ¥{metrics['revenue']:,.2f} (环比 {metrics['revenue_change']:+.1f}%)

## API 指标
- 请求总量: {api_metrics['total_requests']:,}
- 平均响应时间: {api_metrics['avg_response_time']:.0f}ms
- 错误率: {api_metrics['error_rate']:.2f}%
- P99 延迟: {api_metrics['p99_latency']:.0f}ms

请生成一份简洁的日报,包含:
1. 一句话总结昨日表现
2. 关键指标的环比变化
3. 异常波动分析(如有)
4. 需要关注的趋势
5. 建议的跟进行动"""

        return self.agent.generate(prompt, model="gpt-4o")

    def get_db_metrics(self, date):
        """从数据库获取指标"""
        # 实现数据库查询逻辑
        pass

    def get_api_metrics(self, date):
        """从 Analytics API 获取指标"""
        # 实现 API 调用逻辑
        pass

script = MetricsReportScript()

任务监控与调试

实时查看任务输出

bash
# 跟随查看任务实时输出
hermes cron logs error-log-scan --follow
# → [2025-05-22 15:00:01] Job started: error-log-scan
# → [2025-05-22 15:00:01] Creating agent instance...
# → [2025-05-22 15:00:02] Injecting context...
# → [2025-05-22 15:00:02] Executing prompt...
# → [2025-05-22 15:00:02] [Tool] terminal: tail -n 5000 /var/log/app/production.log...
# → [2025-05-22 15:00:05] [Tool] terminal: completed (3s)
# → [2025-05-22 15:00:05] [Agent] Analyzing logs...
# → [2025-05-22 15:00:12] [Agent] Generating report...
# → [2025-05-22 15:00:18] Job completed successfully
# → [2025-05-22 15:00:18] Output sent to: telegram, webhook
# → [2025-05-22 15:00:18] Token usage: 2,340
# → [2025-05-22 15:00:18] Duration: 17s

调试模式

bash
# 调试模式运行(不发送输出,只显示)
hermes cron run error-log-scan --dry-run
# → [Dry Run] 正在执行 error-log-scan...
# → [Dry Run] 调度: 0 * * * *
# → [Dry Run] 模型: claude-sonnet-4
# → [Dry Run] 预期输出目标: telegram (-100987654321), webhook
# → [Dry Run] 模拟执行...
# → [Dry Run] 输出预览:
#   ✅ 系统运行正常
#   最近 1 小时未发现严重错误
#   ERROR 级别日志: 3 条(均为已知的超时问题)
#   WARN 级别日志: 12 条

任务健康检查

bash
# 查看所有任务的健康状态
hermes cron health
# → ┌──────────────────┬────────┬────────────┬────────────┬──────────┐
#   │ Job              │ 状态   │ 最近执行   │ 成功率     │ 下次执行  │
#   ├──────────────────┼────────┼────────────┼────────────┼──────────┤
#   │ daily-pr-review  │ ✅ 健康│ 2 小时前   │ 98% (49/50)│ 明天 8:00 │
#   │ error-log-scan   │ ✅ 健康│ 15 分钟前  │ 95% (285/300)│ 11:00  │
#   │ weekly-report    │ ⚠️ 警告│ 上周五     │ 80% (4/5)  │ 周五 17:00│
#   │ security-scan    │ ❌ 异常│ 昨天       │ 60% (3/5)  │ 明天 3:00 │
#   └──────────────────┴────────┴────────────┴────────────┴──────────┘
#
#   ⚠️ weekly-report: 最近一次执行超时 (600s > 300s limit)
#   ❌ security-scan: 最近两次执行失败,检查脚本依赖

总结与下篇预告

总结

本文全面介绍了 Hermes Agent 的 Cron 定时任务系统:

核心要点:

  1. Cron 让 Agent 从被动变主动 —— 不再只是"你问它答",而是"它主动工作"。定时任务让 Hermes 成为你 24/7 的自动化工友。

  2. 标准 Cron + Hermes 扩展 —— 完全兼容标准 Cron 语法,同时支持秒级精度、特殊时间修饰符、随机延迟、条件触发等扩展功能。

  3. 三种执行模式

    • Prompt 模式:适合简单的线性任务,直接在 YAML 中定义 Prompt
    • 脚本模式:适合复杂工作流,用 Python 脚本控制完整的数据收集→处理→报告流程
    • 混合模式:脚本收集数据 + Agent 分析生成
  4. 多目标输出 —— 一条任务的输出可以同时发送到 Telegram、文件、Webhook、邮箱等多个目标。

  5. 完善的监控体系 —— hermes cron logshermes cron health--dry-run 等工具让你随时掌握任务状态。

实战建议:

  • 从简单的定时任务开始(如每日构建检查),逐步扩展到复杂工作流
  • 使用 --dry-run 验证任务配置,避免误操作
  • 为重要任务配置失败通知,确保问题及时发现
  • 合理设置超时和重试,避免任务卡死
  • 用脚本模式处理需要多步骤数据收集的场景

下篇预告

多 Agent 编排 —— Spawn 实例与 Tmux 协调、单发模式、PTY 模式、多 Agent 协作

在下一篇文章中,我们将探索 Hermes Agent 最强大的能力之一:多 Agent 协作

  • Spawn 实例:如何在运行时动态创建多个 Agent 实例
  • Tmux 协调:利用 Tmux 管理多 Agent 终端会话
  • 单发模式:Fire-and-forget 式的任务分发
  • PTY 模式:交互式多 Agent 协作
  • 多 Agent 协作模式:主从模式、并行模式、流水线模式、辩论模式

当单个 Agent 不够用时,让多个 Agent 协同工作——这才是 AI Agent 的真正威力。

敬请期待!