TL;DR
- Hermes cron runs the same
AIAgentharness from Part 1 on a schedule — each job fires in a fresh session, executes a self-contained prompt (optionally with attached skills), and delivers the final response through the gateway (Telegram, Discord, Slack, email, local files, and more). - Three authoring surfaces: natural-language job creation in gateway chat (
cronjobtool),hermes cronCLI, and/api/jobson the API server. Jobs persist in~/.hermes/cron/jobs.json. - The gateway must be running for the built-in 60-second scheduler (
hermes gateway install). Unattended ops are not a CLI-only pattern. - Best channels for proactive digests: Telegram and Discord first. WhatsApp Cloud proactive cron fails outside Meta’s 24-hour customer service window (Graph error
131047) until Hermes ships template support. - Cost levers:
no_agentscript jobs (zero LLM tokens),wakeAgentscript gates,[SILENT]when nothing changed, pinned cheaper models, and per-jobenabled_toolsets.
What You Will Learn Here
- How Hermes cron fits the agent harness and differs from OS cron +
curl - How to create scheduled digests, monitors, and multi-stage pipelines
- Delivery targets, skills attachment, and provider/model pinning
- Proactive messaging constraints — especially WhatsApp vs Telegram
- Token governance and
write_approvalrisks for unattended jobs - An operational checklist and common failure modes
This is Part 3 of the Hermes Agent series. Part 1 covers harness architecture; Part 2 covers reactive WhatsApp support. Part 3 adds outbound scheduled ops.
How Cron Fits the Harness
Part 1 described Hermes as a long-running agent harness. Cron is how you run that harness unattended:
┌─────────────────────────────────────────┐
│ Job authoring surfaces │
│ Gateway chat → cronjob tool │
│ CLI → /cron + hermes cron │
│ API → /api/jobs │
└────────────────────┬────────────────────┘
│ create/update
▼
┌──────────────────────┐
│ ~/.hermes/cron/ │
│ jobs.json │
└──────────┬───────────┘
│
┌───────────────────────────────────┼───────────────────────────────────┐
│ Hermes Gateway │
│ CronScheduler ──► tick every 60s ──► due jobs + file lock │
│ │ │
│ ▼ per job │
│ optional pre-run script (wakeAgent gate) │
│ │ │
│ ▼ │
│ Fresh AIAgent session (skills injected, cronjob tool DISABLED) │
│ │ │
│ ▼ │
│ Delivery router → Telegram / Discord / Slack / WhatsApp* / local │
└──────────────────────────────────────────────────────────────────────┘
* proactive WhatsApp Cloud delivery fails outside 24h window (131047)
Editorial judgment: Cron is not a separate product. It is scheduled execution of the same runtime that powers CLI, gateway, and API-server turns — with delivery handled by the gateway, not by the agent calling messaging tools directly.
Creating Scheduled Jobs
Schedule formats
Per the Scheduled Tasks (Cron) docs:
| Type | Examples | Repeat default |
|---|---|---|
| Relative one-shot | 30m, 2h, 1d | once |
| Interval | every 30m, every 2h | forever |
| Cron expression | 0 9 * * *, 0 9 * * 1-5 | forever |
| ISO timestamp | 2026-03-15T09:00:00 | once |
Natural language like “daily at 9am” is not parsed as a schedule string in the CLI, Jobs API, or cronjob tool — use 0 9 * * *. In gateway chat (Telegram, Discord, etc.), you can still describe the schedule in plain English; Hermes translates that into a cronjob create call internally.
Surface A: Gateway chat (natural language)
In Telegram, Discord, or another connected channel:
Every morning at 9am, search the web for top AI agent news from the past 24 hours
and send me a summary on Telegram.
Hermes calls the cronjob tool internally. The /cron slash command is CLI-only — not available on gateway channels (slash commands reference).
Surface B: hermes cron CLI
Install and verify the scheduler:
hermes gateway install
hermes cron status # gateway PID, ticker heartbeat, next run
Create a daily digest:
hermes cron create "0 8 * * *" \
"Search the web for top AI agent news from the past 24 hours. Summarize the 3 most important stories: headline, 2-sentence summary, source URL. Use emoji bullets." \
--name "Morning AI digest" \
--deliver telegram
Common flags (CLI commands reference):
| Flag | Purpose |
|---|---|
--name | Human-friendly job name |
--deliver | telegram, discord, local, origin, telegram:CHAT_ID, etc. |
--skill (repeatable) | Attach skills in order |
--script | Pre-run script under ~/.hermes/scripts/ |
--no-agent | Script-only; zero LLM tokens |
--workdir | Inject project AGENTS.md / context files |
Test before waiting for the schedule:
hermes cron list
hermes cron run <job_id>
Surface C: Jobs API
With API_SERVER_ENABLED=true and the gateway running:
curl -X POST http://127.0.0.1:8642/api/jobs \
-H "Authorization: Bearer $API_SERVER_KEY" \
-H "Content-Type: application/json" \
-d '{
"schedule": "0 9 * * 1",
"prompt": "Weekly AI digest: top 5 stories with links, under 500 words.",
"name": "Weekly AI digest",
"deliver": "telegram"
}'
Pin provider and model for unattended jobs
Unpinned jobs snapshot the global default at creation time. If you later change hermes model, unpinned jobs fail closed and alert you to pin explicitly — a drift guard against surprise cost or behavior changes.
For production digests, pin a cheaper model via the cronjob tool or Jobs API:
cronjob(
action="update",
job_id="morning-ai-digest",
model={"provider": "openrouter", "model": "google/gemini-3-flash-preview"},
)
Delivery Targets
The agent writes its answer as the final response. Hermes delivers it — do not instruct the agent to call Telegram or WhatsApp tools for cron output.
| Target | Meaning |
|---|---|
origin | Channel where the job was created (default on messaging) |
local | ~/.hermes/cron/output/ only (default on CLI) |
telegram, discord, slack, email, … | Platform home channel |
telegram:123456 | Specific chat ID |
all | Fan-out to every connected home channel |
Configure home channels via env vars such as TELEGRAM_HOME_CHANNEL, DISCORD_HOME_CHANNEL, and WHATSAPP_CLOUD_HOME_CHANNEL (environment variables).
Delivery extras:
[SILENT]in the agent response suppresses delivery on successful no-op runs (monitoring jobs).cron.wrap_response: falseinconfig.yamlsends raw output without header/footer.- Continuable jobs (
attach_to_session=Trueorcron.mirror_delivery: true) let users reply into the brief on supported platforms.
Implementation Patterns
Pattern A: Daily briefing (LLM + web)
Official tutorial: Daily Briefing Bot
hermes cron create "0 8 * * *" \
"Search the web for latest AI agent and open-source LLM news from the past 24 hours. Summarize top 3: headline, 2-sentence summary, URL." \
--name "Morning AI digest" \
--deliver telegram
Pattern B: Silent monitor (only alert on change)
In the Hermes CLI interactive session (not Telegram/Discord — /cron is CLI-only):
/cron add "every 1h" \
"If script output says CHANGE DETECTED, summarize what changed. If NO_CHANGE, respond with only [SILENT]." \
--script watch-pricing.sh \
--name "Pricing monitor" \
--deliver telegram
Script lives under ~/.hermes/scripts/. Hermes rejects paths outside that directory.
Pattern C: Zero-token metrics ping (no_agent)
cat > ~/.hermes/scripts/memory-watchdog.sh <<'EOF'
#!/usr/bin/env bash
ram_pct=$(free | awk '/^Mem:/ {printf "%d", $3 * 100 / $2}')
if [ "$ram_pct" -ge 85 ]; then
echo "RAM ${ram_pct}% on $(hostname)"
fi
EOF
chmod +x ~/.hermes/scripts/memory-watchdog.sh
hermes cron create "every 5m" \
--no-agent --script memory-watchdog.sh \
--deliver telegram --name "memory-watchdog"
Pattern D: Multi-stage pipeline (context_from)
Chain collector → triage → deliver jobs. Each stage reads upstream output via context_from on the cronjob tool (Automate with Cron guide):
07:00 Collector → raw brief file
07:30 Triage → ranked brief (context_from: collector)
08:00 Deliver → formatted digest to Telegram (context_from: triage)
Pattern E: Skills-attached digest
hermes cron create "0 8 * * *" \
"Search arXiv for 3 best 'language model reasoning' papers from the past day." \
--skill arxiv --skill obsidian \
--name "Paper digest" \
--deliver local
Skills inject in order; keep the cron prompt as the task instruction, not a copy of the skill body.
Pattern F: CI one-shot (hermes send)
For deploy notifications without the Hermes scheduler:
echo "Deploy finished: $(git rev-parse --short HEAD)" | hermes send --to telegram
Use OS cron or CI for the trigger; hermes send bypasses the LLM entirely.
Proactive Messaging and WhatsApp
Part 2 built reactive WhatsApp support (customer messages → bot reply). Cron adds proactive outbound ops — where platform policy matters.
| Channel | Proactive cron digests | Notes |
|---|---|---|
| Telegram | ✅ Recommended | Use TELEGRAM_CRON_THREAD_ID to isolate cron in a forum topic |
| Discord / Slack | ✅ | Named channels and threads |
| Email / SMS | ✅ | Different policy surfaces |
| WhatsApp Cloud | ⚠️ Only inside 24h window | Graph error 131047 outside window |
Per Hermes WhatsApp Cloud docs, free-form messages require the user to have messaged within the last 24 hours. Template message support for cron is not yet implemented in Hermes (as of July 2026). Plan Telegram or email for morning digests; use WhatsApp cron only for users with an active session.
Token Governance and Learning Risks
Cron sessions still pay baseline harness cost — tiered system prompt, skills index, bounded memory snapshots (Part 1) — even for short prompts. Budget accordingly.
| Lever | Effect |
|---|---|
no_agent=True | Zero LLM tokens |
Script + {"wakeAgent": false} | Skip agent when nothing changed |
[SILENT] | Suppress delivery (agent may still run unless gated) |
enabled_toolsets per job | Smaller tool schemas on frequent jobs |
| Pinned cheaper model | Predictable cost per digest |
| Avoid browser/delegation on hourly jobs | Prevents runaway spend |
Governance: memory.write_approval and skills.write_approval default to false. If you enable them, unattended cron jobs may stage pending writes that never get approved. For ops digests, use read-only prompts or keep gates off unless a human reviews /memory pending and /skills pending regularly (Persistent Memory).
Cron also disables the cronjob tool inside cron runs to prevent recursive scheduling loops.
Operational Checklist
[ ] Gateway installed and running (hermes gateway install && hermes cron status)
[ ] Provider/model credentials valid; per-job model pinned for unattended jobs
[ ] Prompt is fully self-contained (URLs, format rules, [SILENT] when applicable)
[ ] Delivery target configured (HOME_CHANNEL env vars or explicit chat ID)
[ ] Minimal toolsets for digest jobs (hermes tools → cron platform)
[ ] Test with hermes cron run <job_id> before relying on schedule
[ ] For WhatsApp proactive: confirm 24h window or use Telegram/email instead
[ ] Backup jobs.json before bulk edits
[ ] Review ~/.hermes/cron/output/ for audit trail
Common Failure Modes
| Symptom | Likely cause | Fix |
|---|---|---|
| Jobs never fire | Gateway not running | hermes gateway install; hermes cron status |
| Job skipped + alert | Global model changed | Pin provider/model on the job |
| Empty delivery | Agent returned [SILENT] | Expected for monitors; check cron output dir |
last_delivery_error | Bad chat ID / channel not discovered | Use raw IDs; ensure gateway saw the channel |
WhatsApp 131047 | Outside 24h window | User must DM first; use Telegram for digests |
| Runaway token spend | Full toolsets on frequent jobs | enabled_toolsets, no_agent watchdogs |
| Prompt blocked at create | Security scanner tripped | Rephrase; no exfil patterns in prompt |
Bottom Line
Hermes cron turns the harness into an ops layer: scheduled reasoning, attached skills, and gateway delivery without a separate automation product. The implementation details that matter in production are gateway uptime, self-contained prompts, pinned models, and choosing the right channel for proactive messaging.
Telegram and Discord are the happy path for digests. WhatsApp is the sharp edge where harness capability meets Meta policy — the same lesson from Part 2, applied to outbound schedules.
Sources
Primary sources consulted on July 3, 2026:
- Hermes Agent — Scheduled Tasks (Cron) — job model, schedules, delivery, skills,
[SILENT]. hermes-agent.nousresearch.com/docs/user-guide/features/cron - Hermes Agent — Automate Anything with Cron — five job patterns including pipelines. hermes-agent.nousresearch.com/docs/guides/automate-with-cron
- Hermes Agent — Script-Only Cron (No LLM) —
no_agent, script delivery. hermes-agent.nousresearch.com/docs/guides/cron-script-only - Hermes Agent — Daily Briefing Bot — end-to-end digest tutorial. hermes-agent.nousresearch.com/docs/guides/daily-briefing-bot
- Hermes Agent — Cron Internals — scheduler, delivery model, Chronos provider. hermes-agent.nousresearch.com/docs/developer-guide/cron-internals
- Hermes Agent — CLI Commands —
hermes cron,hermes send. hermes-agent.nousresearch.com/docs/reference/cli-commands - Hermes Agent — Slash Commands —
/cronCLI-only. hermes-agent.nousresearch.com/docs/reference/slash-commands - Hermes Agent — Tools Reference —
cronjobtoolset. hermes-agent.nousresearch.com/docs/reference/tools-reference - Hermes Agent — API Server — Jobs API CRUD. hermes-agent.nousresearch.com/docs/user-guide/features/api-server
- Hermes Agent — Fallback Providers — cron inherits failover chain. hermes-agent.nousresearch.com/docs/user-guide/features/fallback-providers
- Hermes Agent — Environment Variables — home channel env vars. hermes-agent.nousresearch.com/docs/reference/environment-variables
- Hermes Agent — WhatsApp Cloud — 24h window,
131047, template gap. hermes-agent.nousresearch.com/docs/user-guide/messaging/whatsapp-cloud - Hermes Agent — Persistent Memory —
write_approval, background review. hermes-agent.nousresearch.com/docs/user-guide/features/memory - Nous Research — Hermes Agent GitHub —
cron/jobs.py,hermes_cli/subcommands/cron.py. github.com/NousResearch/hermes-agent
Series: