Skip to content

Cron Jobs

Schedule tasks to run automatically with natural language or cron expressions. Hermes exposes cron management through a single cronjob tool with action-style operations.

Cron-run sessions cannot recursively create more cron jobs. Hermes disables cron management tools inside cron executions to prevent runaway scheduling loops.

Cron jobs can:

  • Schedule one-shot or recurring tasks
  • Pause, resume, edit, trigger, and remove jobs
  • Attach zero, one, or multiple skills to a job
  • Deliver results back to the origin chat, local files, or configured platform targets
  • Run in fresh agent sessions with the normal static tool list
  • Run in no-agent mode — a script on a schedule, its stdout delivered verbatim, zero LLM involvement
Terminal window
/cron add 30m "Remind me to check the build"
/cron add "every 2h" "Check server status"
/cron add "every 1h" "Summarize new feed items" --skill blogwatcher
/cron add "every 1h" "Use both skills and combine the result" --skill blogwatcher --skill maps
Terminal window
hermes cron create "every 2h" "Check server status"
hermes cron create "every 1h" "Summarize new feed items" --skill blogwatcher
hermes cron create "every 1h" "Use both skills and combine the result" \
--skill blogwatcher \
--skill maps \
--name "Skill combo"

Ask Hermes normally:

Every morning at 9am, check Hacker News for AI news and send me a summary on Telegram.

A cron job can load one or more skills before it runs the prompt.

cronjob(
action="create",
skill="blogwatcher",
prompt="Check the configured feeds and summarize anything new.",
schedule="0 9 * * *",
name="Morning feeds",
)

Skills are loaded in order. The prompt becomes the task instruction layered on top of those skills.

cronjob(
action="create",
skills=["blogwatcher", "maps"],
prompt="Look for new local events and interesting nearby places, then combine them into one short brief.",
schedule="every 6h",
name="Local brief",
)
/cron list
/cron pause <job_id>
/cron resume <job_id>
/cron run <job_id>
/cron remove <job_id>
Terminal window
hermes cron list
hermes cron pause <job_id>
hermes cron resume <job_id>
hermes cron run <job_id>
hermes cron remove <job_id>
hermes cron status
hermes cron tick

What they do:

  • pause — keep the job but stop scheduling it
  • resume — re-enable the job and compute the next future run
  • run — trigger the job on the next scheduler tick
  • remove — delete it entirely

Cron execution is handled by the gateway daemon. The gateway ticks the scheduler every 60 seconds, running any due jobs in isolated agent sessions.

Terminal window
hermes gateway install # Install as a user service
sudo hermes gateway install --system # Linux: boot-time system service for servers
hermes gateway # Or run in foreground
hermes cron list
hermes cron status

When scheduling jobs, you specify where the output goes:

OptionDescriptionExample
"origin"Back to where the job was createdDefault on messaging platforms
"local"Save to local files only (~/.hermes/cron/output/)Default on CLI
"telegram"Telegram home channelUses TELEGRAM_HOME_CHANNEL
"discord"Discord home channelUses DISCORD_HOME_CHANNEL
"slack"Slack home channel
"email"Email
"all"Fan out to every connected home channelResolved at fire time

The agent’s final response is automatically delivered. You do not need to call send_message in the cron prompt.

If the agent’s final response starts with [SILENT], delivery is suppressed entirely:

Check if nginx is running. If everything is healthy, respond with only [SILENT].
Otherwise, report the issue.

For recurring jobs that don’t need LLM reasoning — classic watchdogs, disk/memory alerts, heartbeats, CI pings:

Terminal window
hermes cron create "every 5m" \
--no-agent \
--script memory-watchdog.sh \
--deliver telegram \
--name "memory-watchdog"

Semantics:

  • Script stdout (trimmed) → delivered verbatim as the message
  • Empty stdout → silent tick, no delivery
  • Non-zero exit or timeout → an error alert is delivered
  • No tokens, no model, no provider fallback
30m → Run once in 30 minutes
2h → Run once in 2 hours
1d → Run once in 1 day
0 9 * * * → Every day at 9:00 AM
*/30 * * * * → Every 30 minutes
0 */6 * * * → Every 6 hours
every 2 hours
every day at 9am
every Monday at 8am
# In ~/.hermes/config.yaml
cron:
wrap_response: false # Deliver raw agent output without wrapper
script_timeout_seconds: 300 # Pre-run script timeout (default: 120s)