Cron / scheduled jobs¶
Hermes can run the agent on a schedule — a cron job pairs a prompt (or script) with a schedule and delivery target. A native client's "scheduled tasks" panel manages them here. All reads/writes are scoped to the active profile. Verified against api/routes.py.
GET /api/crons — list jobs¶
Optional all-profiles flag. Response { "jobs": [CronJob], "active_profile", "all_profiles", "other_profile_count" }. If the cron package is unavailable → { "jobs": [], "cron_unavailable": true }.
CronJob
{
"id": "…", "name": "…", "prompt": "…",
"schedule": { "kind": "cron|interval|once", "expression": "0 9 * * *" },
"schedule_display": "Daily at 9:00 AM",
"enabled": true, "state": "scheduled",
"next_run_at": 1712000000.0, "last_run_at": 1711900000.0,
"last_status": "ok", "last_error": null, "last_delivery_error": null,
"repeat": { "times": null, "completed": 3 },
"deliver": "local", "skills": [], "model": null, "provider": null,
"profile": "default", "toast_notifications": true
}
profile may be null; toast_notifications defaults true.
Job lifecycle (all POST)¶
| Endpoint | Body | Response |
|---|---|---|
/api/crons/create |
{ prompt, schedule, name?, deliver="local", skills?, model?, provider?, profile?, toast_notifications=true } |
{ ok, job } |
/api/crons/update |
{ job_id, …fields } (only non-null keys applied) |
{ ok, job } |
/api/crons/delete |
{ job_id } |
{ ok, job_id } |
/api/crons/run |
{ job_id } |
{ ok, job_id, status: "running" } — or { ok: false, status: "already_running", elapsed } |
/api/crons/pause |
{ job_id, reason? } |
{ ok, job } |
/api/crons/resume |
{ job_id } |
{ ok, job } |
400 on missing prompt/schedule (create) or job_id; 404 if the job isn't found. /api/crons/run launches the job on a background thread pinned to the profile home.
Status & output¶
GET /api/crons/status¶
Query: job_id (optional).
- With job_id → { "job_id", "running": bool, "elapsed": float }.
- Without → { "running": { "<job_id>": elapsed, … } } (all currently-running jobs).
GET /api/crons/output¶
Query: job_id (req), limit (default 5, clamped 1–500). → { "job_id", "outputs": [ { "filename", "content" } ] } — newest-first run outputs (windowed markdown). 400 on a missing or malformed job_id.
Schedule formats
The schedule field accepts the same forms the agent understands — a cron expression (0 9 * * *), an interval (every 2h, 30m), or a one-shot ISO timestamp. The server normalizes it into the { kind, expression } shape shown above and computes schedule_display for you.