The model
A task that raises is logged and retried on the next tick. It does not take the schedule down. That is how cron behaves, and it is the only sensible default for something meant to run unattended.Earlier versions did the opposite: one exception set
is_running = False and killed the scheduler thread, while run() returned a job object as though nothing had happened. A single transient failure permanently stopped the job, and the caller was handed a plausible return value and a dead schedule.Error budgets
Retrying forever is right for transient failures and wrong for a misconfigured job hammering a dead endpoint.max_consecutive_errors draws the line.
None(default): never give up. Every failure is logged, every tick retried.- An integer: after that many failures in a row, the job stops and
run()raisesCronJobExecutionErrornaming the count and the last error.
stop() returns, a job that gave up raises. You can tell them apart.
Monitoring while it runs
get_execution_stats() is safe to poll from another thread.
What to watch
error_count on its own is a poor signal: a job running every two seconds for a day will accumulate failures and be perfectly healthy. consecutive_errors is the one that distinguishes noise from breakage.
A complete example
Runs without API keys, sinceFlakyAgent stands in for an unreliable upstream.
Budgets across a fleet
Withrun_many, budgets are per agent. One agent giving up does not stop its siblings:
run_many raises once blocking ends, naming which job gave up.
Next steps
Multiple Agents
Fleets on mixed cadences
CronJob Quickstart
Start with a single agent
CronJob Reference
Full parameter and method documentation
Runnable Examples
The example files in the repository