Skip to content

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
}
Dates are unix timestamps or ISO strings. 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.