How Cron Prompts Evolved After Migrating from OpenClaw to Hermes
A practical comparison of how scheduled AI agent prompts changed after migrating from OpenClaw to Hermes: transport, state, runtime boundaries, and script-first automation.
When I first started running scheduled jobs in OpenClaw, my cron prompts looked like mini runbooks. They carried task instructions, transport details, recovery hints, auth reminders, file paths, and sometimes even git workflow guardrails in one big blob.
After migrating the same system to Hermes, the prompts changed shape.
Not just the words. The architecture underneath them changed. Hermes pushed me toward a cleaner split between what the job should do, where state should live, and how delivery happens.
That difference matters if you run long-lived agent automations. Most cron failures are not model failures. They are plumbing failures: stale paths, ambiguous delivery rules, overstuffed prompts, unbounded runtimes, and tasks that should have been scripts in the first place.
Note: The prompt excerpts below are adapted from my own migration archive. I normalized local paths and redacted private identifiers, but kept the structure faithful.
The Before and After in One Sentence
OpenClaw cron prompts tended to be self-contained operational manuals. Hermes cron prompts increasingly behave like bounded task contracts.
That sounds subtle, but it changes everything.
A more technical way to say it: OpenClaw jobs were often encoded as agent + payload + delivery, while Hermes jobs are easier to reason about as schedule + prompt or script + delivery target + optional state handoff.
In OpenClaw, the prompt frequently absorbed missing structure from the scheduler. In Hermes, more of that structure exists as first-class fields.
What Changed in the Job Schema
The migration was not only a wording change inside message strings. The surrounding job object changed too.
OpenClaw archive shape
{
"agentId": "janitor",
"name": "nightly-build",
"schedule": {
"kind": "cron",
"expr": "30 15 * * *",
"tz": "UTC"
},
"payload": {
"kind": "agentTurn",
"message": "...large prompt body...",
"timeoutSeconds": 1800,
"model": "gpt-5.4"
},
"delivery": {
"mode": "announce",
"channel": "telegram",
"to": "..."
}
}
Hermes registry shape
{
"name": "nightly-build",
"prompt": "...bounded prompt body...",
"script": null,
"no_agent": false,
"schedule": {
"kind": "cron",
"expr": "30 15 * * *",
"display": "30 15 * * *"
},
"deliver": "telegram:...",
"enabled_toolsets": null,
"context_from": null
}
That schema shift has two consequences.
First, Hermes removes a layer of indirection. Instead of digging through payload.message, the task instruction sits in top-level prompt. That makes prompt audits, diffs, and bulk rewrites much simpler.
Second, Hermes makes it easier to express non-agent jobs directly. A script-only job is not a hack anymore. It is part of the scheduler model.
What Changed in My Cron Registry
During the migration audit, I compared my archived OpenClaw cron store with the current Hermes job registry.
A few concrete numbers stood out:
- OpenClaw archive: 123 jobs
- Current Hermes registry: 125 jobs
- OpenClaw prompts referencing
.openclawpaths: 70 - Hermes prompts still referencing
.openclawpaths: 41 - Hermes prompts still referencing
.openclawpaths and enabled: 0 - Hermes jobs using
no_agent: truescript-only execution: 2
That last point is important. The migration was not just about renaming paths. It also introduced a new category of jobs that do not need an LLM loop at all.
There was also a measurable cleanup in control-surface design:
- OpenClaw commonly embedded
timeoutSeconds, auth reminders, transport instructions, and filesystem repair hints inside the prompt body. - Hermes more often pushes those concerns into scheduler fields, stable script paths, or dedicated state files.
- The number of current jobs still carrying legacy
.openclawpath references dropped from 70 archived prompt references to 41 residual references, and all 41 are paused.
That means the remaining drift is registry hygiene, not live operational risk.
Pattern 1: Transport Moved Out of the Prompt
One of the cleanest improvements was separating message delivery from task logic.
OpenClaw style
A simple watcher job used to say this:
Run `blogwatcher scan` to check for new blog posts.
If there are new articles, run `blogwatcher articles` and notify me on Telegram with a brief summary.
If no new articles, stay silent.
The instruction worked, but it mixed two different concerns:
- detect whether anything changed
- decide how to message the user
Hermes style
The Hermes version became more explicit and more decoupled:
Run exactly one command: `blogwatcher scan`.
If output says no blogs are tracked, reply exactly `NO_REPLY`.
If there are no new articles, reply exactly `NO_REPLY`.
If there are new articles, run `blogwatcher articles` and reply with a brief summary only.
Do NOT use the message tool; announce handles delivery.
This is a better contract for a scheduled job.
The prompt no longer needs to know how Telegram delivery works. It only needs to return one of two outcomes:
- nothing to report
- short result to deliver
That sounds like a small rewrite, but it reduces a whole class of failure. When transport is handled by the scheduler, the prompt can stay focused on classification.
Technically, this is a move from side-effectful prompts to return-value prompts.
The OpenClaw version instructs the agent to perform notification as part of the task. The Hermes version tells the agent to classify the result and emit one of two payloads:
NO_REPLY- a short summary string
That is easier to test because the contract is narrow. If the cron misbehaves, I can ask:
- Did
blogwatcher scanreturn new items? - Did the agent return
NO_REPLYor a summary? - Did the scheduler deliver the summary?
Each failure point now has a cleaner boundary.
Pattern 2: State Became Deliberate Instead of Incidental
A lot of OpenClaw prompts treated the workspace as one giant shared memory surface.
OpenClaw daily diary
An older diary job looked like this in practice:
Read ~/.openclaw/workspace/memory/YYYY-MM-DD.md for today's events.
If missing, reconstruct activity from git logs, cron history, and event logs.
Write a narrative diary entry.
Save it to ~/.openclaw/workspace/memory/diary/YYYY-MM-DD.md.
This worked, but it asked one cron prompt to do too much:
- discover source material
- reconstruct missing state
- write the final artifact
- decide whether the day had enough signal
That is powerful, but also brittle. When a daily job has to infer too much, it becomes slower and harder to debug.
Hermes daily diary
The Hermes version is much tighter:
Prefer reading ~/.hermes/state/diary/source/YYYY-MM-DD.md if it exists.
Otherwise reconstruct the day from concise git activity in a few live repos.
Write a creative narrative (200-400 words).
Save it to ~/.hermes/state/diary/YYYY-MM-DD.md.
If nothing meaningful happened, reply NO_REPLY.
The architectural shift is the key point here.
Hermes introduces a dedicated state/ area with narrower responsibility:
state/diary/source/for raw source materialstate/diary/for generated output- separate follow-up jobs for review or publication
The prompt becomes simpler because the system around it is more structured.
The technical win here is state normalization.
In the OpenClaw version, the job mixed three layers of state retrieval:
- canonical daily memory
- opportunistic reconstruction from git and event logs
- final rendered diary output
Hermes turns that into a staged pipeline. One path is treated as upstream source, another as downstream artifact. That means later jobs can depend on a stable filename instead of re-running discovery logic.
This matters for idempotency too. A publish job reading state/diary/YYYY-MM-DD.md is far less ambiguous than a publish job that can silently regenerate content while publishing it.
Pattern 3: Big Operational Runbooks Shrunk into Bounded Checklists
The most dramatic prompt changes showed up in maintenance jobs.
OpenClaw weekly cleanup
The OpenClaw cleanup prompt was basically an ops playbook:
- clean
/tmp - delete old logs
- archive old memory files
- check disk usage
- prune Docker if available
- remove multiple caches
- prune old backups
- delete old session transcripts
- inspect stale
node_modules - inspect stale virtual environments
- write a maintenance log
Useful? Yes.
Focused? Not really.
It also carried extra protective language about secrets, auth, and canonical HOME, because the prompt was expected to survive a messy operational environment.
Hermes weekly cleanup
The Hermes rewrite is more opinionated:
Weekly Hermes cleanup.
Run these steps:
1. bash ~/.hermes/scripts/clean-tmp.sh --log
2. delete old Hermes logs
3. delete old cron outputs
4. check disk usage
5. report backup size
Write a short dated summary to ~/.hermes/state/ops/maintenance-log.md.
Return a concise cleanup report.
Do not use message tool.
This is not just shorter writing. It is better system design.
The cleanup logic that changes often moved into versioned scripts. The prompt is now mostly orchestration:
- call the durable script
- collect a few health checks
- persist a compact summary
That is easier to test, easier to update, and much less likely to drift.
From an operations perspective, this is the difference between prompt-embedded procedures and versioned executables.
If cleanup rules change, I now update clean-tmp.sh instead of patching a long natural-language prompt in several places. The prompt becomes a thin orchestration layer over stable shell entrypoints.
That matters for three reasons:
- diffs are smaller
- behavior is easier to reproduce outside the scheduler
- script changes can be validated directly from the terminal without invoking the LLM loop
Pattern 4: Publishing Pipelines Stopped Doing Everything at Once
OpenClaw-era prompts often tried to include every surrounding concern in a single scheduled task.
That is especially obvious in publishing flows.
OpenClaw-style publishing
An older publishing job carried a lot of baggage in the prompt itself:
- file-write guardrails
- secret handling reminders
- git identity rules
- PII scan instructions
- content transformation steps
- commit and push workflow
This made sense at the time because the prompt was acting as both policy and execution plan.
Hermes-style publishing
The Hermes version splits the pipeline more clearly:
- generate diary
- run a separate PII review
- check a clearance file
- publish only if cleared
The publish prompt now starts with a gate:
Check clearance at ~/.hermes/state/diary/YYYY-MM-DD.clearance.
If BLOCKED, report that publication is blocked.
If missing, report no clearance and stop.
Read the diary from ~/.hermes/state/diary/YYYY-MM-DD.md.
This is the right kind of boring.
A cron prompt should not have to guess whether it is safe to publish. It should read an explicit control file and act accordingly.
That is a much healthier automation boundary.
More technically, Hermes makes the publishing pipeline look closer to a finite-state workflow:
sourceexists or does not existreviewclears or blocks publicationclearancefile is present or absent- publisher reads a single approved artifact path
That is a better fit for cron because the scheduler is polling a series of explicit states rather than asking one prompt to both infer and mutate workflow state on the fly.
Pattern 5: Some Jobs Graduated Out of Prompt Engineering Entirely
Hermes also made a more radical improvement possible: some cron jobs stopped being agent jobs.
In the current registry, I now have script-only jobs using no_agent: true.
One example is a feature collector that looks like this at the registry level:
prompt: "Collect Hermes cron feature-health metrics to local output using the configured script."
script: "hermes-cron-feature-collector.py"
no_agent: true
That is a major evolution in mindset.
In OpenClaw, the default pattern was usually: give the model a task and let it drive. In Hermes, the scheduler can explicitly say: this one does not need an agent at all, just run the script and deliver the output.
That is a big win for:
- deterministic collectors
- health checks
- threshold-based alerts
- low-token monitoring tasks
If a cron job’s output is already well-defined, a prompt is often the wrong abstraction.
This is one of the clearest technical distinctions between the two systems.
In OpenClaw, the fallback move was often: write a smarter prompt. In Hermes, the better question is: should this be one of three job shapes?
- agent job — prompt plus tools, for judgment-heavy work
- script-only job —
scriptplusno_agent: true, for deterministic work - collector + summarizer pair — one job gathers machine output, another agent job interprets it
That job taxonomy is much healthier than forcing everything through one prompt-shaped interface.
What Actually Improved
Looking across the prompt changes, I think the migration produced five real improvements.
1. Better separation of concerns
Delivery moved into scheduler configuration. Prompts focus more on task logic. Scripts hold imperative mechanics. State files define handoff points.
2. Smaller failure surface
Shorter prompts with fewer unrelated responsibilities are easier to reason about. When a job fails, there are fewer places to look.
In practice, that improves observability. I can separate:
- prompt logic bugs
- script/runtime bugs
- delivery bugs
- stale path bugs
- missing-state bugs
OpenClaw prompts often blended those into one failure domain. Hermes does not eliminate the bugs, but it makes them easier to classify.
3. More explicit state handoffs
source, clearance, ops, and other dedicated state paths are much better than “just inspect the workspace and figure it out.”
4. Easier migration auditing
One useful side effect of the migration is that stale references became easy to count. I could literally audit how many jobs still pointed at .openclaw, then verify that none of those stale prompts were still enabled.
That turned the migration audit into a concrete engineering pass instead of a vague cleanup goal. The audit loop was simple:
- export or inspect the archived OpenClaw job set
- enumerate current Hermes jobs
- grep both registries for legacy path prefixes and old command surfaces
- partition hits into enabled versus paused jobs
- treat enabled stale references as safety issues and paused stale references as hygiene debt
That distinction matters. A paused job with a dead path is not an outage, but it is still latent breakage sitting in the registry. If someone resumes it months later, the bug comes back disguised as a fresh incident.
In other words, migration auditing is not only about “did the new system start.” It is about whether the registry reached a stable invariant:
- no enabled jobs with legacy paths
- no enabled jobs depending on historical OpenClaw-only commands
- a shrinking backlog of paused jobs carrying stale references
- enough structure in the new registry to make those counts cheap to recompute
Once you can measure those buckets quickly, the migration stops being folklore and becomes something you can re-check after every cleanup pass.
5. A clearer line between agent work and script work
This may be the most valuable change of all. It is a sign of maturity when your automation stack stops asking the model to do jobs that a script can do more reliably.
What Did Not Change Automatically
Migration alone did not magically clean everything up.
Even after the move, the Hermes registry still contained 41 prompts referencing .openclaw paths. The good news was that all of them were paused. That made the situation operationally safe, but it still mattered as hygiene.
This is worth calling out because it is a common trap in agent migrations:
- active jobs get fixed first
- paused jobs get ignored
- six weeks later someone re-enables an old job and it breaks in a confusing way
So the real standard should be:
- enabled stale references: zero for safety
- total stale references: eventually zero for maintainability
A Practical Heuristic I Use Now
After this migration, I ended up with a simple rule of thumb for cron design:
Use a prompt when the job needs judgment
Good examples:
- summarize new articles
- propose three tools worth learning
- review a generated draft for risk or quality
- decide whether something is notable enough to alert on
Use a script when the job needs certainty
Good examples:
- collect metrics
- run a backup
- export cron state
- check a health endpoint
- append a machine-readable log
Use state files when two jobs depend on each other
Good examples:
sourcefiles for raw materialclearancefiles for publish gates- local output files for collectors feeding summarizers
That triad — prompt, script, state file — is the clearest difference between my OpenClaw cron design and my Hermes cron design.
If You Are Migrating Your Own Agent Cron Stack
Here is the sequence I would recommend now.
- Audit path references first. Count how many prompts still point at legacy directories.
- Separate delivery from task logic. Prefer scheduler-managed delivery over “send this message” instructions inside prompts.
- Move long shell sequences into scripts. Prompts should orchestrate, not impersonate Bash files.
- Introduce explicit handoff files. If one cron depends on another, make the dependency visible.
- Convert deterministic jobs to script-only execution. Save tokens and reduce ambiguity.
- Verify paused jobs too. “Not enabled” is safer than “enabled,” but it is not the same as “fixed.”
The Bigger Lesson
The interesting part of migrating from OpenClaw to Hermes was not that one framework replaced another. It was that the migration forced me to notice what my cron prompts had been compensating for.
A bloated cron prompt is often a signal that the surrounding system is underdesigned.
When the scheduler understands delivery, when state has a proper home, and when deterministic work moves into scripts, the prompt can finally become what it should have been all along:
a small contract for judgment, not a giant survival manual.
Related Posts
- How to Migrate OpenClaw to a New Server (2026) — the broader migration playbook
- OpenClaw Part 3: How My AI Agent’s Memory Evolved Over Two Months — why structured state matters
- How to Make AI Agent Skills Portable and Reusable — portability patterns beyond cron
- Experimenting with OpenClaw: Running a Multi-Agent AI System — early lessons from operating the system