A Different Approach To Agentic Scheduling
I've been playing with Openclaw this week, and it's great, but overly complex for what I want. So I've taken it's principles, and applied them to my own workflo...
Hands up. The Openclaw approach to scheduling makes me shudder. Using an AI to work out out whether something should be scheduled or not is like using a sledgehammer to crack a crontab.
But then, allowing agents free-reign to crontab horrified me even more.
So I had a think. Yes, me, not Claude.
[Take that Claude! I'm a free man!]
How Scheduling Works: From Markdown Files to Running Tasks
There are few things I don't like about setting up scheduling in an agentic framework:
1. I can't be bothered SSHing into my server to set up a schedule.
2. I don't want agents messing with crontab.
3. I like the idea that Openclaw has of using a prompt for the scheduled tasks.
So what's the best way to address those points?
---
Scheduling in my system is file-driven. But it's a frontmatter file created by the agent, one file per schedule.
Each file has two parts: YAML frontmatter for configuration, and a markdown body that becomes the prompt sent to the agent.
A Real Example
A file like sync-kanban-projects.md might contain frontmatter with a schedule set to "0 * * * *" (every hour on the hour), enabled set to true, send_to_user set to false, and a description like:
"Call the project management MCP to get a list of the current projects, and save the response as a pure JSON file at ./projects.json. Don't modify or transform the data in any way. Overwrite any existing data".
Frontmatter Fields
The Frontmatter has a few extra fields for convenience:
- schedule (required): A standard cron expression (5 or 6 fields).
- enabled (optional, defaults to true): Set to false to pause without deleting.
- timeout_seconds (optional, defaults to 120): Max seconds before the task times out.
- on_failure (optional, defaults to "ignore"): What to do on failure -- ignore, retry, or notify.
- max_retries (optional, defaults to 1): Retry count, only used when on_failure is set to retry.
- send_to_user (optional, defaults to false): Sends the agent's response to Telegram.
- description (optional): A human-readable note for logs.
The markdown body below the frontmatter separator is the prompt. It can be as short or long as needed and is sent to the agent verbatim when the cron fires.
That's it. A cron expression, a few options, and the prompt. The scheduler handles the rest.
The Scheduler
The scheduler is a simple nodeJS function that runs in-process as part of the primary server my agentic set up works through.
There are a couple of aspects to this:
Chokidar
Chokidar is a file-monitoring module. It watches the agents workspaces to detect new/edited scheduling frontmatter files, and gets the frontmatter config.
Hint: set ignoreInitial to false to when the server restarts, Chokidar picks up the existing files even though they've not changed.
Croner
Croner is a node function that replaces unix cron. It gets passed the schedule details, and when the job is due to run, it triggers a callback function which fires up Anthropic's Agent SDK, and passes in the prompt from the schedule file.
Main NodeJS Server
When the main server restarts, it forces a scan of the sheduling files
Why Markdown Files?
This approach has a few advantages over a database or API-configured scheduler:
- They're git-friendly: Schedule definitions are version-controlled alongside agent configuration. You get full audit trail, diff, and rollback for free.
- Agent self-management: Since agents have filesystem access to their workspace, they can create, edit, and delete their own schedules at runtime by writing .md files, without impacting other agents' schedules. Chokidar picks up changes automatically.
- No restart required: Hot-reload means the agent can tweak a cron expression or disable a schedule without touching the server process.
- Readable: I can open a schedule file and immediately understand what it does, when it runs, and what prompt it sends.
- No extra infrastructure: No Redis, no database, no separate scheduler service. The files are the state.