Hi, I'm Lena. I had a cron job set up for about three days before I realized it wasn't actually doing what I thought it was doing.
It looked fine in the list. The schedule was right. The prompt looked clear when I wrote it on a Tuesday afternoon. But the runs were producing results that felt slightly off — not broken, just… not the same kind of output I'd get if I asked the agent the same thing in a normal chat. I paused here. I'd been treating it like Linux cron. The thing is, Hermes Agent cron isn't really Linux cron. It just borrows the schedule syntax.
This is a write-up of what I've slowly come to understand about how cron actually works inside Hermes — and why so many jobs end up looking like they're scheduled correctly but running poorly. It's the kind of thing that probably isn't urgent until it is.
What Hermes Cron really does
The first thing worth saying out loud: a Hermes cron job is not a shell command on a timer. It's an agent session that fires on a schedule.
That distinction matters more than I thought it would. According to the official Hermes cron documentation, every scheduled run starts in a completely fresh agent session. No conversation history. No memory of the last run. No carryover context from your interactive sessions. Whatever the agent needs to do its job, the prompt has to provide — or the attached skills have to.
The second thing: the gateway has to be running. The scheduler isn't a separate daemon you can ignore. In gateway mode the scheduler tick is part of the gateway's main event loop, called roughly every 60 seconds. If the gateway isn't up, your job sits in jobs.json and waits, looking perfectly scheduled and doing nothing. I learned this one by accident — a job that "wasn't running" was actually fine; the gateway had crashed two days earlier.
The third thing is delivery. The agent's final response gets delivered automatically to the configured target. So if you've written a prompt that ends with "and send this to me on Telegram," and the destination is Telegram, Hermes will detect the duplicate and only send once. That part is handled. You don't have to think about it — but you do have to know it's happening.
Schedule formats, repeats, skills, destinations
Hermes accepts both natural-language intervals and standard 5-field POSIX cron expressions. So every 1h, 30m, and 0 9 * * 1-5 all work. The 5-field format is the same one used basically everywhere — Linux crontab, Kubernetes CronJobs, GitHub Actions — and the Wikipedia entry on cron is a surprisingly good reference if you want to confirm exactly how step values and ranges interact in the Vixie dialect, which is what most systems including Hermes follow.
If you're not sure your expression actually means what you think it means, crontab.guru is the tool I keep coming back to. Paste the expression, read the plain-English version, sanity-check the next 5 run times. This is one of those things that takes thirty seconds and saves a debugging afternoon.
You can attach skills with --skill name (one or many), set a destination with --deliver, give the job a name, and override the model on a per-job basis. Job records are stored as JSON in ~/.hermes/cron/jobs.json with atomic writes — meaning if a write gets interrupted you don't end up with a half-corrupted file.
Create jobs that survive real use
The pattern I've ended up using looks something like this:
hermes cron create "0 9 * * 1-5" \
"Pull yesterday's commits from the repo at ~/work/project, \
summarize what changed in 5 bullets, and flag anything that \
looks unusual" \
--skill git-summary \
--name "Weekday standup prep"
Three things I want to call out:
- The schedule is explicit.
0 9 * * 1-5— 9am, weekdays. Notevery day at 9. The cron expression is unambiguous to any reader who knows the syntax, including future me at 11pm trying to debug why something fired on a Saturday. - The prompt is self-contained. It says where the repo is. It says what to summarize. It says how many bullets. It doesn't assume the agent remembers anything from previous runs.
- A skill is attached. The
git-summaryskill (hypothetical here) carries the actual procedure — how to read git log, what format to use, what counts as "unusual." The cron prompt just has to say what to do, not how.
That third point is the one I keep relearning.
Why self-contained prompts matter more than people expect
Here's a prompt I wrote in week one that didn't work the way I wanted:
"Same as last time but for this week's data."
In my interactive session that prompt is fine. The agent has the conversation history. It knows what "last time" was. It knows what data we were looking at. In a cron run none of that exists. Fresh session. No memory. No context. The agent reads "same as last time" and has nothing to compare against.
A version that actually works:
"Read the CSV at ~/data/weekly-signups.csv. Calculate the percentage change in signups versus the previous 7 days. Report the number, the change, and the top 3 referral sources. Format as a Slack message."
Boring. Verbose. Specific. Works every time.
The Hermes docs have a good example of the same idea, where the recommended pattern is essentially: assume the agent is reading your prompt for the first time, in isolation, with no context except the attached skills. If the prompt doesn't make sense as a standalone instruction to a stranger, it won't make sense to a fresh cron session either.
Common cron failures and how to prevent them
A few patterns I've watched go wrong, mostly in my own setup:
The gateway-isn't-running silence. Job is scheduled. List shows it. Status looks correct. Nothing fires. The fix is usually: hermes cron status to confirm the scheduler is alive, then make sure the gateway is installed as a service so it survives reboots and logout. Until you've installed it as a user or system service, every hermes gateway foreground run is one terminal-close away from failure.
Brittle prompts with implicit context. Already covered. The version of this I see most often is "summarize what's new" — new compared to what? When? The agent doesn't know.
Overlapping runs from misjudged frequency. A job set to every 1m that takes 90 seconds to complete creates an interesting question. Hermes uses file-based locking on the scheduler tick to prevent the same due-job batch from being processed twice in parallel, which is good. But the deeper question is whether you actually need 1-minute resolution. Usually no.
Duplicate sends from the prompt asking for delivery. If your prompt ends with send_message(...) to the same destination the scheduler is already going to deliver to, Hermes detects the duplicate and skips the second send. Fine. But if you've reflexively written send_message calls into every prompt, it makes the job's intent harder to read. Cleaner to leave delivery to the scheduler and let the prompt focus on the task.
Prompt injection via the data the job reads. If your cron job fetches a webpage and summarizes it, that webpage can in theory contain instructions that try to redirect what the agent does. Hermes scans cron prompts for prompt-injection patterns at creation and update time, but it doesn't sanitize the external content the job pulls in at runtime. This is the same category of risk that OWASP describes as indirect prompt injection in their LLM Top 10 — and it's worth keeping in mind for any cron job that ingests untrusted input. I haven't fully figured out how to think about this for low-stakes personal jobs, but for anything that touches credentials or external systems, it matters.
Operational patterns worth using
A few setups I've come back to:
- Daily report at a fixed business hour.
0 9 * * 1-5with a skill that pulls the data and a self-contained prompt that says exactly what to summarize. - Periodic health check.
*/15 * * * *— every 15 minutes — running a small script that pings an endpoint and only delivers a message if something is wrong. The script field in a cron job runs before each agent turn, and its stdout becomes context for the agent. Useful for change-detection patterns where you don't want a noisy 96-runs-a-day output. - Multi-skill jobs. Attaching two or three skills lets one job combine a data-collection skill with an analysis skill. The cron prompt becomes "use both skills and report."
- Fallback-aware jobs. Cron jobs inherit the configured fallback providers and credential pool rotation. So if a job runs at 3am and the primary provider returns a rate-limit error, the run can route to a fallback provider rather than failing the whole job. This is one of those features I didn't appreciate until it saved a run I'd have otherwise missed. The Hermes cron internals page is where this is described in more detail if you want to verify exactly how the resolution chain works.
The thing I keep telling myself: a cron job that runs is worth more than a cron job that's elegant. Boring, verbose, self-contained prompts. Explicit schedules. Gateway installed as a service. Skills doing the heavy lifting. That combination is what makes the difference between "I set this up" and "this has been running quietly for three weeks and I forgot it existed."
FAQ
Why does my cron job not have access to my previous chat history?
Each run is a fresh agent session by design. No history, no memory carryover. The prompt and any attached skills are the only context the agent sees.
Do I need to call send_message in the prompt?
No, and ideally don't. The scheduler delivers the agent's final response automatically. If your prompt also calls send_message to the same destination, Hermes detects the duplicate and skips the second send.
My job runs but never fires the schedule. What's wrong?
Most often the gateway isn't running. Try hermes cron status to check the scheduler. Cron jobs only fire when the gateway is up, or in CLI mode when an active session is running.
Can a cron job create more cron jobs?
No. Cron-run sessions have the cronjob toolset disabled to prevent runaway scheduling loops.
How long can a cron job run?
The default timeout is inactivity-based, not wall-clock — a job that's actively making tool calls or streaming tokens can run indefinitely. A job idle for longer than HERMES_CRON_TIMEOUT (default 600s) gets killed.
I'll probably keep refining how I write these prompts. Cron is one of those things where most of what makes it work isn't visible in the schedule field — it's in the prompt, the skill, and whether the system underneath is actually running. Worth checking, every now and then, that all three are still where you left them.
Previous Posts:
- 👉 If you’re setting up multiple scheduled tasks, you might want to understand how Hermes Cron Memory & Context Limits impact your cron jobs.
- 👉 If you're troubleshooting overlapping runs or slow execution, check out this guide on Safe Hermes MCP Setup for Cron Jobs.
- 👉 For a deeper dive into improving agent behavior with clear prompts and instructions:How to Write Effective Hermes Agent Skills
- 👉 Thinking of automating real-time monitoring? This guide will help: Periodic Health Check Cron Jobs with Hermes
- 👉 Need to optimize cron delivery for stable results? Read more on Managing Agent Capabilities and Tool Access




