Cron expressions are one of those things every developer has written and nobody enjoys reading. 0 9 * * 1-5 means “every weekday at 9am” but you had to think about it for a second. Now imagine an agent that takes “run the database backup every weekday at 9am” and does the right thing – parses the schedule, registers the job, monitors execution, and tells you when something breaks.
Here’s the minimal setup to get a scheduled task running with APScheduler:
| |
That handles scheduling, but the interesting part is putting an LLM in front of it so users can manage jobs with plain English instead of memorizing cron syntax.
Parsing Natural Language into Cron Schedules
The first piece you need is a function that converts human-readable schedules into APScheduler trigger parameters. You could write a regex parser, but an LLM handles the ambiguity much better – “every other Tuesday” or “twice a day during business hours” are hard to capture with rules.
| |
The temperature=0 keeps outputs deterministic. You get back a dictionary that plugs directly into CronTrigger(**schedule).
Building the Agent with Tool Calling
Now wire this into an agent loop. The agent needs four tools: add a job, list jobs, remove a job, and check job status. Define them as OpenAI function-calling tools and dispatch based on what the model picks.
| |
Use it like this:
| |
The agent loop keeps calling tools until the model returns a plain text response. This handles multi-step requests too – “schedule a health check every 6 hours and show me all jobs” triggers two tool calls in sequence.
Handling Failures and Retries
Scheduled tasks fail. Networks go down, APIs hit rate limits, disks fill up. APScheduler has built-in retry support through event listeners and job configuration.
| |
For automatic retries, configure the job with misfire_grace_time and wrap the task function:
| |
The misfire_grace_time=60 means if the scheduler was down and missed the 9:00 AM window, it will still fire the job as long as it’s within 60 seconds of the scheduled time. The with_retry wrapper gives you exponential backoff – waits 1s, 2s, then 4s between attempts.
Common Errors and Fixes
ConflictingIdError: Job identifier 'x' conflicts with an existing job
You tried to add a job with an ID that already exists. Pass replace_existing=True to add_job(), or remove the old job first with scheduler.remove_job("x").
KeyError when the LLM returns unexpected cron keys
The LLM sometimes returns keys like "weekday" instead of "day_of_week". Add validation before passing to CronTrigger:
| |
json.JSONDecodeError from LLM schedule parsing
The model sometimes wraps JSON in markdown fences or adds explanatory text. The parse_schedule function above strips fences, but you should also wrap the parse call in a try/except and retry once:
| |
Scheduler stops after the main thread exits
BackgroundScheduler runs in a daemon thread, so it dies when your main script ends. For a long-running agent, either use BlockingScheduler or add a keep-alive loop:
| |
Jobs silently fail with no error output
APScheduler swallows exceptions by default. Always attach the event listener from the retry section above. You can also set jitter on jobs to prevent thundering herd problems when multiple jobs share the same schedule:
| |
This gives you a production-ready pattern: an LLM that understands natural language schedules, APScheduler handling the execution timing, tool-calling for management operations, and proper error handling with retries. The agent loop is stateless between requests, so you can drop it behind a REST API or a chat interface without any changes to the core logic.
Related Guides
- How to Build a ReAct Agent from Scratch with Python
- How to Build a Code Review Agent with LLMs and Git Integration
- How to Build a Slack Bot Agent with LLMs and Bolt
- How to Build a Tool-Calling Agent with Claude and MCP
- How to Build an API Testing Agent with LLMs and Requests
- How to Build a SQL Query Agent with LLMs and Tool Calling
- How to Build a Web Research Agent with LLMs and Search APIs
- How to Build a Code Generation Agent with LLMs
- How to Build a Log Analysis Agent with LLMs and Regex Tools
- How to Build a Contract Analysis Agent with LLMs and PDF Parsing