Major changes across 20 documentation pages: Staleness fixes: - Fix FAQ: wrong import path (hermes.agent → run_agent) - Fix FAQ: stale Gemini 2.0 model → Gemini 3 Flash - Fix integrations/index: missing MiniMax TTS provider - Fix integrations/index: web_crawl is not a registered tool - Fix sessions: add all 19 session sources (was only 5) - Fix cron: add all 18 delivery targets (was only telegram/discord) - Fix webhooks: add all delivery targets - Fix overview: add missing MCP, memory providers, credential pools - Fix all line-number references → use function name searches instead - Update file size estimates (run_agent ~9200, gateway ~7200, cli ~8500) Expanded thin pages (< 150 lines → substantial depth): - honcho.md: 43 → 108 lines — added feature comparison, tools, config, CLI - overview.md: 49 → 55 lines — added MCP, memory providers, credential pools - toolsets-reference.md: 57 → 175 lines — added explanations, config examples, custom toolsets, wildcards, platform differences table - optional-skills-catalog.md: 74 → 153 lines — added 25+ missing skills across communication, devops, mlops (18!), productivity, research categories - integrations/index.md: 82 → 115 lines — added messaging, HA, plugins sections - cron-internals.md: 90 → 195 lines — added job JSON example, lifecycle states, tick cycle, delivery targets, script-backed jobs, CLI interface - gateway-internals.md: 111 → 250 lines — added architecture diagram, message flow, two-level guard, platform adapters, token locks, process management - agent-loop.md: 112 → 235 lines — added entry points, API mode resolution, turn lifecycle detail, message alternation rules, tool execution flow, callback table, budget tracking, compression details - architecture.md: 152 → 295 lines — added system overview diagram, data flow diagrams, design principles table, dependency chain Other depth additions: - context-references.md: added platform availability, compression interaction, common patterns sections - slash-commands.md: added quick commands config example, alias resolution - image-generation.md: added platform delivery table - tools-reference.md: added tool counts, MCP tools note - index.md: updated platform count (5 → 14+), tool count (40+ → 47)
332 lines
9.8 KiB
Markdown
332 lines
9.8 KiB
Markdown
---
|
|
sidebar_position: 5
|
|
title: "Scheduled Tasks (Cron)"
|
|
description: "Schedule automated tasks with natural language, manage them with one cron tool, and attach one or more skills"
|
|
---
|
|
|
|
# Scheduled Tasks (Cron)
|
|
|
|
Schedule tasks to run automatically with natural language or cron expressions. Hermes exposes cron management through a single `cronjob` tool with action-style operations instead of separate schedule/list/remove tools.
|
|
|
|
## What cron can do now
|
|
|
|
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
|
|
|
|
:::warning
|
|
Cron-run sessions cannot recursively create more cron jobs. Hermes disables cron management tools inside cron executions to prevent runaway scheduling loops.
|
|
:::
|
|
|
|
## Creating scheduled tasks
|
|
|
|
### In chat with `/cron`
|
|
|
|
```bash
|
|
/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 find-nearby
|
|
```
|
|
|
|
### From the standalone CLI
|
|
|
|
```bash
|
|
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 find-nearby \
|
|
--name "Skill combo"
|
|
```
|
|
|
|
### Through natural conversation
|
|
|
|
Ask Hermes normally:
|
|
|
|
```text
|
|
Every morning at 9am, check Hacker News for AI news and send me a summary on Telegram.
|
|
```
|
|
|
|
Hermes will use the unified `cronjob` tool internally.
|
|
|
|
## Skill-backed cron jobs
|
|
|
|
A cron job can load one or more skills before it runs the prompt.
|
|
|
|
### Single skill
|
|
|
|
```python
|
|
cronjob(
|
|
action="create",
|
|
skill="blogwatcher",
|
|
prompt="Check the configured feeds and summarize anything new.",
|
|
schedule="0 9 * * *",
|
|
name="Morning feeds",
|
|
)
|
|
```
|
|
|
|
### Multiple skills
|
|
|
|
Skills are loaded in order. The prompt becomes the task instruction layered on top of those skills.
|
|
|
|
```python
|
|
cronjob(
|
|
action="create",
|
|
skills=["blogwatcher", "find-nearby"],
|
|
prompt="Look for new local events and interesting nearby places, then combine them into one short brief.",
|
|
schedule="every 6h",
|
|
name="Local brief",
|
|
)
|
|
```
|
|
|
|
This is useful when you want a scheduled agent to inherit reusable workflows without stuffing the full skill text into the cron prompt itself.
|
|
|
|
## Editing jobs
|
|
|
|
You do not need to delete and recreate jobs just to change them.
|
|
|
|
### Chat
|
|
|
|
```bash
|
|
/cron edit <job_id> --schedule "every 4h"
|
|
/cron edit <job_id> --prompt "Use the revised task"
|
|
/cron edit <job_id> --skill blogwatcher --skill find-nearby
|
|
/cron edit <job_id> --remove-skill blogwatcher
|
|
/cron edit <job_id> --clear-skills
|
|
```
|
|
|
|
### Standalone CLI
|
|
|
|
```bash
|
|
hermes cron edit <job_id> --schedule "every 4h"
|
|
hermes cron edit <job_id> --prompt "Use the revised task"
|
|
hermes cron edit <job_id> --skill blogwatcher --skill find-nearby
|
|
hermes cron edit <job_id> --add-skill find-nearby
|
|
hermes cron edit <job_id> --remove-skill blogwatcher
|
|
hermes cron edit <job_id> --clear-skills
|
|
```
|
|
|
|
Notes:
|
|
|
|
- repeated `--skill` replaces the job's attached skill list
|
|
- `--add-skill` appends to the existing list without replacing it
|
|
- `--remove-skill` removes specific attached skills
|
|
- `--clear-skills` removes all attached skills
|
|
|
|
## Lifecycle actions
|
|
|
|
Cron jobs now have a fuller lifecycle than just create/remove.
|
|
|
|
### Chat
|
|
|
|
```bash
|
|
/cron list
|
|
/cron pause <job_id>
|
|
/cron resume <job_id>
|
|
/cron run <job_id>
|
|
/cron remove <job_id>
|
|
```
|
|
|
|
### Standalone CLI
|
|
|
|
```bash
|
|
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
|
|
|
|
## How it works
|
|
|
|
**Cron execution is handled by the gateway daemon.** The gateway ticks the scheduler every 60 seconds, running any due jobs in isolated agent sessions.
|
|
|
|
```bash
|
|
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
|
|
```
|
|
|
|
### Gateway scheduler behavior
|
|
|
|
On each tick Hermes:
|
|
|
|
1. loads jobs from `~/.hermes/cron/jobs.json`
|
|
2. checks `next_run_at` against the current time
|
|
3. starts a fresh `AIAgent` session for each due job
|
|
4. optionally injects one or more attached skills into that fresh session
|
|
5. runs the prompt to completion
|
|
6. delivers the final response
|
|
7. updates run metadata and the next scheduled time
|
|
|
|
A file lock at `~/.hermes/cron/.tick.lock` prevents overlapping scheduler ticks from double-running the same job batch.
|
|
|
|
## Delivery options
|
|
|
|
When scheduling jobs, you specify where the output goes:
|
|
|
|
| Option | Description | Example |
|
|
|--------|-------------|---------|
|
|
| `"origin"` | Back to where the job was created | Default on messaging platforms |
|
|
| `"local"` | Save to local files only (`~/.hermes/cron/output/`) | Default on CLI |
|
|
| `"telegram"` | Telegram home channel | Uses `TELEGRAM_HOME_CHANNEL` |
|
|
| `"telegram:123456"` | Specific Telegram chat by ID | Direct delivery |
|
|
| `"telegram:-100123:17585"` | Specific Telegram topic | `chat_id:thread_id` format |
|
|
| `"discord"` | Discord home channel | Uses `DISCORD_HOME_CHANNEL` |
|
|
| `"discord:#engineering"` | Specific Discord channel | By channel name |
|
|
| `"slack"` | Slack home channel | |
|
|
| `"whatsapp"` | WhatsApp home | |
|
|
| `"signal"` | Signal | |
|
|
| `"matrix"` | Matrix home room | |
|
|
| `"mattermost"` | Mattermost home channel | |
|
|
| `"email"` | Email | |
|
|
| `"sms"` | SMS via Twilio | |
|
|
| `"homeassistant"` | Home Assistant | |
|
|
| `"dingtalk"` | DingTalk | |
|
|
| `"feishu"` | Feishu/Lark | |
|
|
| `"wecom"` | WeCom | |
|
|
|
|
The agent's final response is automatically delivered. You do not need to call `send_message` in the cron prompt.
|
|
|
|
### Response wrapping
|
|
|
|
By default, delivered cron output is wrapped with a header and footer so the recipient knows it came from a scheduled task:
|
|
|
|
```
|
|
Cronjob Response: Morning feeds
|
|
-------------
|
|
|
|
<agent output here>
|
|
|
|
Note: The agent cannot see this message, and therefore cannot respond to it.
|
|
```
|
|
|
|
To deliver the raw agent output without the wrapper, set `cron.wrap_response` to `false`:
|
|
|
|
```yaml
|
|
# ~/.hermes/config.yaml
|
|
cron:
|
|
wrap_response: false
|
|
```
|
|
|
|
### Silent suppression
|
|
|
|
If the agent's final response starts with `[SILENT]`, delivery is suppressed entirely. The output is still saved locally for audit (in `~/.hermes/cron/output/`), but no message is sent to the delivery target.
|
|
|
|
This is useful for monitoring jobs that should only report when something is wrong:
|
|
|
|
```text
|
|
Check if nginx is running. If everything is healthy, respond with only [SILENT].
|
|
Otherwise, report the issue.
|
|
```
|
|
|
|
Failed jobs always deliver regardless of the `[SILENT]` marker — only successful runs can be silenced.
|
|
|
|
## Schedule formats
|
|
|
|
The agent's final response is automatically delivered — you do **not** need to include `send_message` in the cron prompt for that same destination. If a cron run calls `send_message` to the exact target the scheduler will already deliver to, Hermes skips that duplicate send and tells the model to put the user-facing content in the final response instead. Use `send_message` only for additional or different targets.
|
|
|
|
### Relative delays (one-shot)
|
|
|
|
```text
|
|
30m → Run once in 30 minutes
|
|
2h → Run once in 2 hours
|
|
1d → Run once in 1 day
|
|
```
|
|
|
|
### Intervals (recurring)
|
|
|
|
```text
|
|
every 30m → Every 30 minutes
|
|
every 2h → Every 2 hours
|
|
every 1d → Every day
|
|
```
|
|
|
|
### Cron expressions
|
|
|
|
```text
|
|
0 9 * * * → Daily at 9:00 AM
|
|
0 9 * * 1-5 → Weekdays at 9:00 AM
|
|
0 */6 * * * → Every 6 hours
|
|
30 8 1 * * → First of every month at 8:30 AM
|
|
0 0 * * 0 → Every Sunday at midnight
|
|
```
|
|
|
|
### ISO timestamps
|
|
|
|
```text
|
|
2026-03-15T09:00:00 → One-time at March 15, 2026 9:00 AM
|
|
```
|
|
|
|
## Repeat behavior
|
|
|
|
| Schedule type | Default repeat | Behavior |
|
|
|--------------|----------------|----------|
|
|
| One-shot (`30m`, timestamp) | 1 | Runs once |
|
|
| Interval (`every 2h`) | forever | Runs until removed |
|
|
| Cron expression | forever | Runs until removed |
|
|
|
|
You can override it:
|
|
|
|
```python
|
|
cronjob(
|
|
action="create",
|
|
prompt="...",
|
|
schedule="every 2h",
|
|
repeat=5,
|
|
)
|
|
```
|
|
|
|
## Managing jobs programmatically
|
|
|
|
The agent-facing API is one tool:
|
|
|
|
```python
|
|
cronjob(action="create", ...)
|
|
cronjob(action="list")
|
|
cronjob(action="update", job_id="...")
|
|
cronjob(action="pause", job_id="...")
|
|
cronjob(action="resume", job_id="...")
|
|
cronjob(action="run", job_id="...")
|
|
cronjob(action="remove", job_id="...")
|
|
```
|
|
|
|
For `update`, pass `skills=[]` to remove all attached skills.
|
|
|
|
## Job storage
|
|
|
|
Jobs are stored in `~/.hermes/cron/jobs.json`. Output from job runs is saved to `~/.hermes/cron/output/{job_id}/{timestamp}.md`.
|
|
|
|
The storage uses atomic file writes so interrupted writes do not leave a partially written job file behind.
|
|
|
|
## Self-contained prompts still matter
|
|
|
|
:::warning Important
|
|
Cron jobs run in a completely fresh agent session. The prompt must contain everything the agent needs that is not already provided by attached skills.
|
|
:::
|
|
|
|
**BAD:** `"Check on that server issue"`
|
|
|
|
**GOOD:** `"SSH into server 192.168.1.100 as user 'deploy', check if nginx is running with 'systemctl status nginx', and verify https://example.com returns HTTP 200."`
|
|
|
|
## Security
|
|
|
|
Scheduled task prompts are scanned for prompt-injection and credential-exfiltration patterns at creation and update time. Prompts containing invisible Unicode tricks, SSH backdoor attempts, or obvious secret-exfiltration payloads are blocked.
|