跳到主要内容
本文尚未翻译

本文暂时显示英文原文,中文翻译正在进行中。翻译完成后将自动更新。

原文链接:English Version

Cron Internals

The cron subsystem provides scheduled task execution — from simple one-shot delays to recurring cron-expression jobs with skill injection and cross-platform delivery.

Key Files

FilePurpose
cron/jobs.pyJob model, storage, atomic read/write to jobs.json
cron/scheduler.pyScheduler loop — due-job detection, execution, repeat tracking
tools/cronjob_tools.pyModel-facing cronjob tool registration and handler
gateway/run.pyGateway integration — cron ticking in the long-running loop
hermes_cli/cron.pyCLI hermes cron subcommands

Scheduling Model

Four schedule formats are supported:

FormatExampleBehavior
Relative delay30m, 2h, 1dOne-shot, fires after the specified duration
Intervalevery 2h, every 30mRecurring, fires at regular intervals
Cron expression0 9 * * *Standard 5-field cron syntax (minute, hour, day, month, weekday)
ISO timestamp2025-01-15T09:00:00One-shot, fires at the exact time

The model-facing surface is a single cronjob tool with action-style operations: create, list, update, pause, resume, run, remove.

Job Storage

Jobs are stored in ~/.hermes/cron/jobs.json with atomic write semantics (write to temp file, then rename). Each job record contains:

{
"id": "job_abc123",
"name": "Daily briefing",
"prompt": "Summarize today's AI news and funding rounds",
"schedule": "0 9 * * *",
"skills": ["ai-funding-daily-report"],
"deliver": "telegram:-1001234567890",
"repeat": null,
"state": "scheduled",
"next_run": "2025-01-16T09:00:00Z",
"run_count": 42,
"created_at": "2025-01-01T00:00:00Z",
"model": null,
"provider": null,
"script": null
}

Job Lifecycle States

StateMeaning
scheduledActive, will fire at next scheduled time
pausedSuspended — won't fire until resumed
completedRepeat count exhausted or one-shot that has fired
runningCurrently executing (transient state)

Backward Compatibility

Older jobs may have a single skill field instead of the skills array. The scheduler normalizes this at load time — single skill is promoted to skills: [skill].

Scheduler Runtime

Tick Cycle

The scheduler runs on a periodic tick (default: every 60 seconds):

tick()
1. Acquire scheduler lock (prevents overlapping ticks)
2. Load all jobs from jobs.json
3. Filter to due jobs (next_run <= now AND state == "scheduled")
4. For each due job:
a. Set state to "running"
b. Create fresh AIAgent session (no conversation history)
c. Load attached skills in order (injected as user messages)
d. Run the job prompt through the agent
e. Deliver the response to the configured target
f. Update run_count, compute next_run
g. If repeat count exhausted → state = "completed"
h. Otherwise → state = "scheduled"
5. Write updated jobs back to jobs.json
6. Release scheduler lock

Gateway Integration

In gateway mode, the scheduler tick is integrated into the gateway's main event loop. The gateway calls scheduler.tick() on its periodic maintenance cycle, which runs alongside message handling.

In CLI mode, cron jobs only fire when hermes cron commands are run or during active CLI sessions.

Fresh Session Isolation

Each cron job runs in a completely fresh agent session:

  • No conversation history from previous runs
  • No memory of previous cron executions (unless persisted to memory/files)
  • The prompt must be self-contained — cron jobs cannot ask clarifying questions
  • The cronjob toolset is disabled (recursion guard)

Skill-Backed Jobs

A cron job can attach one or more skills via the skills field. At execution time:

  1. Skills are loaded in the specified order
  2. Each skill's SKILL.md content is injected as context
  3. The job's prompt is appended as the task instruction
  4. The agent processes the combined skill context + prompt

This enables reusable, tested workflows without pasting full instructions into cron prompts. For example:

Create a daily funding report → attach "ai-funding-daily-report" skill

Script-Backed Jobs

Jobs can also attach a Python script via the script field. The script runs before each agent turn, and its stdout is injected into the prompt as context. This enables data collection and change detection patterns:

# ~/.hermes/scripts/check_competitors.py
import requests, json
# Fetch competitor release notes, diff against last run
# Print summary to stdout — agent analyzes and reports

Delivery Model

Cron job results can be delivered to any supported platform:

TargetSyntaxExample
Origin chatoriginDeliver to the chat where the job was created
Local filelocalSave to ~/.hermes/cron/output/
Telegramtelegram or telegram:<chat_id>telegram:-1001234567890
Discorddiscord or discord:#channeldiscord:#engineering
SlackslackDeliver to Slack home channel
WhatsAppwhatsappDeliver to WhatsApp home
SignalsignalDeliver to Signal
MatrixmatrixDeliver to Matrix home room
MattermostmattermostDeliver to Mattermost home
EmailemailDeliver via email
SMSsmsDeliver via SMS
Home AssistanthomeassistantDeliver to HA conversation
DingTalkdingtalkDeliver to DingTalk
FeishufeishuDeliver to Feishu
WeComwecomDeliver to WeCom

For Telegram topics, use the format telegram:<chat_id>:<thread_id> (e.g., telegram:-1001234567890:17585).

Response Wrapping

By default (cron.wrap_response: true), cron deliveries are wrapped with:

  • A header identifying the cron job name and task
  • A footer noting the agent cannot see the delivered message in conversation

The [SILENT] prefix in a cron response suppresses delivery entirely — useful for jobs that only need to write to files or perform side effects.

Session Isolation

Cron deliveries are NOT mirrored into gateway session conversation history. They exist only in the cron job's own session. This prevents message alternation violations in the target chat's conversation.

Recursion Guard

Cron-run sessions have the cronjob toolset disabled. This prevents:

  • A scheduled job from creating new cron jobs
  • Recursive scheduling that could explode token usage
  • Accidental mutation of the job schedule from within a job

Locking

The scheduler uses file-based locking to prevent overlapping ticks from executing the same due-job batch twice. This is important in gateway mode where multiple maintenance cycles could overlap if a previous tick takes longer than the tick interval.

CLI Interface

The hermes cron CLI provides direct job management:

hermes cron list # Show all jobs
hermes cron create # Interactive job creation (alias: add)
hermes cron edit <job_id> # Edit job configuration
hermes cron pause <job_id> # Pause a running job
hermes cron resume <job_id> # Resume a paused job
hermes cron run <job_id> # Trigger immediate execution
hermes cron remove <job_id> # Delete a job