The cron system in Hermes Agent enables scheduled task automation with natural-language job definitions. Jobs are managed through a unified tool interface or CLI, executed automatically by the gateway daemon, and deliver results to configured platforms. This system provides unattended execution of recurring agent workflows—daily reports, periodic backups, monitoring checks, or any task expressible as an agent prompt.
Cron jobs are stored as JSON objects in ~/.hermes/cron/jobs.json cron/jobs.py71 Execution output is saved locally to ~/.hermes/cron/output/{job_id}/{timestamp}.md cron/jobs.py101
| Field | Type | Description |
|---|---|---|
id | str | Unique UUID for the job. Immutable after creation cron/jobs.py162 |
name | str | Human-readable job name, defaults to prompt excerpt hermes_cli/cron.py118 |
prompt | str | The natural-language instruction given to the agent tools/cronjob_tools.py74 |
schedule | dict | Structured schedule: kind (once/interval/cron) and display cron/jobs.py206-247 |
enabled | bool | Activation state hermes_cli/cron.py145 |
next_run_at | str | ISO 8601 timestamp of next execution cron/jobs.py250-313 |
deliver | str | Delivery target (e.g., "local", "origin", "telegram") cron/scheduler.py234-242 |
skills | list | List of skills to load before execution hermes_cli/cron.py156-157 |
script | str | Path to a script to execute instead of a prompt hermes_cli/cron.py158-160 |
workdir | str | Working directory for script/agent execution cron/scheduler.py488 |
profile | str | Hermes profile to switch into for the run cron/scheduler.py174-180 |
enabled_toolsets | list | List of toolsets to enable for this job cron/scheduler.py138-167 |
The system parses schedules via parse_schedule cron/jobs.py206:
croniter) cron/jobs.py243-247Sources: cron/jobs.py64-313 tools/cronjob_tools.py22-35 hermes_cli/cron.py116-167
The gateway daemon calls tick() every 60 seconds from a background thread cron/scheduler.py4-5 A file-based lock at ~/.hermes/cron/.tick.lock ensures only one process runs the scheduler at a time cron/scheduler.py7-9
Sources: cron/scheduler.py4-45 tools/cronjob_tools.py7-33 cron/jobs.py39-66
When a job is due, run_job cron/scheduler.py456 initializes execution:
_job_profile_context cron/scheduler.py174 temporarily sets HERMES_HOME and environment variables to match the job's pinned profile cron/scheduler.py176-180session_id prefixed with cron_{job_id}_ cron/scheduler.py483_resolve_cron_enabled_toolsets cron/scheduler.py170 determines available tools. It prioritizes per-job overrides, then the cron platform tool config, falling back to full defaults cron/scheduler.py170-185_merge_mcp_into_per_job_toolsets cron/scheduler.py139 layers enabled MCP servers onto the job's toolset allowlist so they are not silently dropped cron/scheduler.py140-153SILENT_MARKER ([SILENT]) cron/scheduler.py426 is used to suppress delivery if the agent includes it in the response cron/scheduler.py426-428workdir or profile run sequentially via _sequential_pool to avoid process-global mutation races cron/scheduler.py169-173 Parallel jobs use _parallel_pool cron/scheduler.py160-164_set_cron_session_title ensures the session has a unique, non-blank title persisted in the database, handling collisions via lineage suffixes cron/scheduler.py51-87Sources: cron/scheduler.py139-185 cron/scheduler.py426-428 cron/scheduler.py456-483 cron/scheduler.py160-173 cron/scheduler.py51-87
For scale-to-zero hosted environments, Hermes supports the Chronos provider plugin. This shifts the trigger responsibility from a local 60-second loop to an external NAS-mediated webhook cron/scheduler_provider.py16-19
Sources: cron/scheduler_provider.py59-61 cron/scheduler_provider.py145-155
| Key | Purpose |
|---|---|
cron.provider | Set to chronos to bypass the built-in ticker cron/scheduler_provider.py137 |
cron.chronos.portal_url | Nous Portal base URL for arming jobs. |
cron.chronos.callback_url | Public URL of the gateway for inbound fire requests. |
Sources: cron/scheduler_provider.py122-160
The _resolve_delivery_target function determines where output goes cron/scheduler.py234:
local: No external delivery; output saved to disk only cron/scheduler.py259-260origin: Routes back to the platform and chat_id that created the job, preserving thread_id cron/scheduler.py262-268origin is missing, it attempts to use environment variables like MATRIX_HOME_ROOM or TELEGRAM_HOME_CHANNEL cron/scheduler.py269-284_summarize_cron_failure_for_delivery cron/scheduler.py90 provides compact one-line failure messages for chat delivery to avoid noise, specifically handling rate limits, timeouts, and auth errors cron/scheduler.py102-140Sources: cron/scheduler.py90-140 cron/scheduler.py234-315 tests/cron/test_scheduler.py139-184
Cron prompts are scanned for critical threats using _scan_cron_prompt tools/cronjob_tools.py173
curl/wget commands that embed environment variables (e.g., $API_KEY) into URLs or POST data tools/cronjob_tools.py105-116A secondary scanner, _scan_cron_skill_assembled tools/cronjob_tools.py98 runs against the fully assembled prompt including loaded skills inside _build_job_prompt cron/scheduler.py355-357 It uses a looser pattern set (_CRON_SKILL_ASSEMBLED_PATTERNS) tools/cronjob_tools.py97-102 to avoid false positives on legitimate security documentation within skills tests/tools/test_cronjob_tools.py157-160 If a violation is detected at runtime, CronPromptInjectionBlocked is raised cron/scheduler.py143
The CLI rejects cron jobs that contain commands capable of restarting or stopping the gateway (e.g., hermes gateway restart, systemctl stop hermes) via contains_gateway_lifecycle_command hermes_cli/cron.py24-26 to prevent agents from creating denial-of-service loops.
Cron-run sessions cannot recursively create more cron jobs. Hermes disables cron management toolsets (cronjob, messaging, clarify) inside cron executions cron/scheduler.py156-176
Sources: tools/cronjob_tools.py79-168 tools/cronjob_tools.py97-102 cron/scheduler.py143-176 hermes_cli/cron.py24-26 tests/tools/test_cronjob_tools.py157-160
The cronjob tool provides a single entry point for agents to manage schedules tools/cronjob_tools.py4-6
| Action | Purpose |
|---|---|
create | Schedules a new job; captures current chat as origin tools/cronjob_tools.py25 |
list | Returns a summary of all jobs tools/cronjob_tools.py27 |
update | Modifies existing job fields (prompt, schedule, skills, etc.) tools/cronjob_tools.py34 |
trigger | Forces immediate execution of a job tools/cronjob_tools.py24 |
hermes cron create "every 1h" "Check status": Manual job creation hermes_cli/cron.py187hermes cron list: Displays status, next run time, and repeat counts hermes_cli/cron.py99-162hermes cron tick: Manually triggers a scheduler check for due jobs hermes_cli/subcommands/cron.py167-171hermes cron status: Shows gateway PID and overall cron execution health via heartbeat files ticker_heartbeat and ticker_last_success cron/jobs.py72-80Sources: tools/cronjob_tools.py22-35 hermes_cli/cron.py99-162 hermes_cli/subcommands/cron.py167-171 cron/jobs.py72-80
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.