Scheduler Deployment
Deploy scheduled agent and recipe execution for 24/7 autonomous operations in production environments.Overview
The scheduler provides:- Interval-based agent/recipe execution
- PM2-style daemon management
- Cost budgeting and monitoring
- Automatic retry with exponential backoff
- Centralized logging
CLI: praisonai --deploy --schedule
Deploy and schedule with real cloud deployment (no longer a stub):
DeployHandler on the chosen interval, replacing the previous stub implementation.
Quick Start
Start a Scheduler
Manage Schedulers
Python API
Create deployment schedulers with the real cloud deployer:Async API
Use async methods for non-blocking daemon shutdown and retry-with-backoff deployment from async contexts like FastAPI routes or MCP tools.DaemonManager.astop_daemon()
Signature:async def astop_daemon(pid, timeout=10) -> bool
Async variant of stop_daemon. Uses asyncio.sleep (cooperative) instead of time.sleep (blocking). Same SIGTERM → wait → SIGKILL escalation, with timeout seconds between SIGTERM and SIGKILL.
DeploymentScheduler.adeploy_with_retry()
Signature:async def adeploy_with_retry(max_retries=3) -> bool
Async variant of the retry-with-backoff path. Runs each blocking deployer.deploy() call via asyncio.to_thread(...) so it never blocks the event loop, and sleeps 30s between retries via asyncio.sleep.
Quick Start Example
Sequence Diagram
Best Practices
In any async def context, prefer a* variants
In any async def context, prefer a* variants
Sync versions will block the event loop for up to
timeout seconds. Use async variants to keep the event loop responsive.Don't mix
Don't mix
Calling
stop_daemon from inside asyncio.run(...) freezes the loop; calling astop_daemon from sync code requires asyncio.run(...) wrapper.CLI path stays sync
CLI path stays sync
praisonai schedule stop continues to use the sync method, unchanged for backward compatibility.Sequence Diagram:
Python Deployment (Legacy Recipe API)
Docker Deployment
Dockerfile
Docker Compose
Configuration
Schedule Intervals
| Format | Interval | Description |
|---|---|---|
hourly | 3600s | Every hour |
daily | 86400s | Every 24 hours |
*/30m | 1800s | Every 30 minutes |
*/6h | 21600s | Every 6 hours |
*/5s | 5s | Every 5 seconds (testing) |
3600 | 3600s | Custom seconds |
TEMPLATE.yaml Runtime Block
Configure scheduler defaults in your recipe:Safe Defaults
| Setting | Default | Description |
|---|---|---|
interval | hourly | Execution interval |
max_retries | 3 | Retry attempts on failure |
timeout_sec | 300 | Timeout per execution |
max_cost_usd | 1.00 | Budget limit |
Production Considerations
Cost Monitoring
Set budget limits to prevent runaway costs:Logging
Logs are stored in~/.praisonai/logs/:
State Persistence
Scheduler state is persisted in~/.praisonai/schedulers/:
Error Handling
The scheduler automatically retries failed executions with exponential backoff:- Attempt 1: Execute immediately
- Attempt 2: Wait 30s, retry
- Attempt 3: Wait 60s, retry
- Attempt 4: Wait 90s, retry
- Attempt 5: Wait 120s, retry
Monitoring
Kubernetes Deployment
Systemd Service
For Linux deployments, create a systemd service:Security & Hardening
For production deployments, useRunPolicy to add run-scoped guardrails to every scheduled execution:
- Tool scoping — restrict which tools the agent can use per run
- Prompt scanning — detect injection attempts before they reach the model
- Durable audit — persist full output to a reliable path even when delivery fails
- Fail-closed delivery — send failure summaries to operators when a run is blocked

