Skip to content
Conduit

mcp server

agent-scheduler

Task scheduling MCP server for autonomous agents — cron, intervals, priority queues, dependencies, retry policies.

nyx-builds/agent-schedulercommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • uv (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "agent-scheduler": {
      "command": "uvx",
      "args": [
        "agent-scheduler"
      ]
    }
  }
}

same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12

Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs

README

synced Oct 23, 2026

Agent Scheduler

Task scheduling engine for autonomous AI agents

Python 3.10+ License: MIT CI Tests: 1204 MCP Version: 0.10.0


Task scheduling engine for autonomous agents — cron jobs, interval triggers, business-day calendars, maintenance mode, priority queues, retry logic, webhooks, templates, job groups, API key auth, SLA engine, workflow DAGs, backfill engine, SQLite backend, MCP server (98 tools), and REST API.

Features

Backfill Engine (v0.10.0) — NEW

Replay missed schedule windows retroactively. When the scheduler has been down, a job was misconfigured, or data arrived late, the backfill engine reconstructs the schedule timeline and generates synthetic execution requests for each missed window.

  • Three policies: exact (fire every missed window), coalesce (collapse consecutive windows into one catch-up run), sample (evenly-spaced preview runs)
  • Catch-up mode: each run's payload is enriched with _backfill: {scheduled_time, run_index, total_runs, original_payload} so handlers behave as if they ran at the intended time
  • Dry-run preview: inspect the timeline before executing anything
  • Stale-job detection: find jobs that missed windows while the scheduler was down, with backfill_all_stale to recover the whole fleet in one call
  • Async execution with configurable max parallelism, plus run history and result inspection

SLA Engine & Workflow DAGs (v0.9.0)

  • SLA tiers — per-job completion-time SLOs with escalation ladders (notify → reassign → cancel), breach tracking, and uptime-style SLA compliance reporting
  • Workflow DAG engine — multi-job dependencies with parallel branches, gate conditions, and workflow-level rollback

Interval Triggers (v0.8.0)

  • Fixed-rate scheduling — Run jobs every N seconds without cron expressions (interval=60 = every minute)
  • No cron math needed — Simpler than cron for fixed-rate jobs (every 90 seconds, every 45 minutes)
  • Anti-burst protection — If the scheduler falls behind, it snaps forward to now + interval instead of firing a burst of catch-up runs
  • Priority over cron — When both interval and cron are set, interval takes precedence
  • Composes with all constraints — Works with time windows, business calendars, concurrency control, and max_instances

Business Calendar (v0.8.0) — NEW

  • Weekend policies — sat_sun (default), fri_sat (Middle East), sun_only (parts of Asia), or none
  • Holiday calendars — Declare explicit non-working days via ISO date strings or Python date objects
  • US federal holidays — Built-in us_federal_holidays(year) with proper observed-date rules (Sat→Fri, Sun→Mon)
  • UK bank holidays — Built-in uk_bank_holidays(year) with computus-based Easter calculation
  • Custom working days — Override the weekend policy with an explicit allow-list of weekdays
  • Working-day math — next_working_day, previous_working_day, add_working_days(n), count_working_days(start, end)
  • Rolling conventions — next, previous, modified_following (with month-boundary protection), none
  • JSON serialization — Calendar configs serialize cleanly for storage and MCP transport
  • Job integration — Set calendar={"weekend_policy": "sat_sun", "holidays": [...]} on any job to constrain it to working days

Maintenance Mode (v0.8.0) — NEW

  • Graceful drain — Block new job dispatch during deploys, migrations, or incidents without killing in-flight jobs
  • Two modes — active (block) and draining (block + signal waiting for in-flight jobs)
  • Auto-reschedule — Due jobs are deferred to their next scheduled tick, not lost
  • Blocked counter — Track how many dispatches were prevented during maintenance
  • Thread-safe — Concurrent-safe state management
  • MCP tools — scheduler_maintenance_activate, scheduler_maintenance_deactivate, scheduler_maintenance_status

Core Scheduling

  • Cron jobs — Recurring jobs via standard cron expressions (0 9 * * MON-FRI)
  • One-time tasks — Delayed (--delay 3600) or scheduled at specific time (--run-at)
  • Immediate execution — Jobs that run right away
  • Priority queues — Low / Normal / High with ordered execution
  • Retry with backoff — Exponential backoff, error-specific retry rules, max retries
  • Job dependencies — Chain jobs with on_status conditions (success/failed/timeout)
  • Tags — Filter and organize jobs with tags
  • Max runs — Limit total executions per job
  • Timeout — Per-job execution timeout

Webhook Notifications (v0.2.0)

  • HTTP callbacks — Fire POST requests on job events (created, completed, failed, timeout, retry, etc.)
  • HMAC signatures — SHA-256 signing for payload verification
  • Tag filtering — Only fire webhooks for jobs with specific tags
  • Custom headers — Add authentication or custom HTTP headers
  • Delivery retry — Configurable retry on failed deliveries
  • Delivery history — Track all webhook delivery attempts

Job Templates (v0.2.0)

  • 6 built-in templates — Health check, daily backup, weekly report, data pipeline, cleanup, notification
  • Custom templates — Create reusable job blueprints
  • Required fields — Enforce mandatory configuration when instantiating
  • Default overrides — Pre-configured priority, retry, timeout, payload defaults
  • Categories — Organize templates by type (monitoring, backup, reporting, etc.)

SQLite Persistence (v0.3.0)

  • Production backend — SQLite with WAL mode for atomic transactions
  • Efficient queries — Indexed lookups by status, priority, next run, name
  • Scalable — Handles millions of records with proper pagination
  • Better concurrency — WAL mode allows concurrent reads during writes
  • Drop-in replacement — Same JobStore interface, just use SQLiteJobStore

API Key Authentication (v0.3.0)

  • Bearer token auth — Authorization: Bearer ask_... or X-API-Key header
  • Scoped permissions — 9 scopes (jobs:read/write, executions:read/write, webhooks:read/write, templates:read/write, admin, *)
  • Rate limiting — Configurable per-key request limits (default: 100/min)
  • Key management — Create, list, revoke, enable/disable keys via API or CLI
  • Usage tracking — Last used timestamp and request count per key

Job Groups (v0.3.0)

  • Multi-tenant — Organize jobs by agent, project, or team
  • Quotas — Per-group job limits and concurrent execution caps
  • Bulk operations — Pause/resume all jobs in a group
  • Group stats — Track job counts, execution stats, and quota usage per group
  • Auto-tagging — Jobs automatically tagged with group ID and group defaults

Execution Analytics (v0.4.0)

  • Health scoring — Composite 0-100 score per job (success rate, trend, recency, failure trend)
  • Letter grades — A-F health grades for quick at-a-glance assessment
  • Duration statistics — Min, max, avg, median, p95, p99 percentiles
  • Failure pattern analysis — Groups and ranks common errors across jobs
  • Scheduler dashboard — Aggregate health, execution counts (24h/7d/all-time), top failures
  • At-risk detection — Automatically flags jobs with health score < 50
  • Stale job detection — Identifies scheduled jobs that haven't run in 24h+

Cron Expression Toolkit (v0.4.0)

  • Validation — Validate cron expressions with detailed error messages
  • Human-readable descriptions — Translate cron to English ("Every Monday at 9:00 AM")
  • Run preview — Show the next N scheduled run times
  • Expression builder — Construct cron from natural parameters (daily, weekly, weekdays, etc.)
  • Field parser — Extract field meanings from any cron expression

Notification Channels (v0.4.0)

  • Slack — Rich Block Kit messages via Incoming Webhooks
  • Discord — Formatted embeds with color-coded severity
  • Email — HTML + plain text via SMTP with TLS/SSL support
  • Generic HTTP — JSON POST to any endpoint with optional HMAC signing
  • Channel manager — Register multiple channels, filter by severity level
  • Config factory — Create channels from config dicts for easy setup

Dead Letter Queue (v0.5.0)

  • Automatic dead-lettering — Jobs that exhaust retries are moved to the DLQ instead of being silently lost
  • Full context preserved — Original payload, error message, retry count, and job snapshot stored for debugging
  • Replay — Resubmit dead-lettered jobs with optional payload overrides
  • Discard — Mark entries as resolved without replaying
  • Bulk operations — Replay all or discard all entries, optionally filtered by reason
  • Statistics — Track total/unresolved counts, breakdown by reason, oldest entry age
  • Persistence — DLQ entries survive restarts via JSON file storage
  • CLI access — Full CLI with dlq list, dlq show, dlq replay, dlq discard, dlq stats, dlq purge

Result Chaining & Pipelines (v0.5.0)

  • Automatic result passing — When Job A triggers Job B via dependency, A's result data flows into B's payload
  • Merge strategies — merge (parent wins), child_first (child wins), replace (parent replaces), prefix (prefixed keys)
  • Selective key passing — Pass only specific result keys from parent to child
  • Key wrapping — Nest parent result under a specific key in child payload
  • Pipeline definitions — Define named multi-step pipelines with per-step result configuration
  • Pipeline tracking — Start pipelines, record step results, track progress percentage
  • CLI access — chain link, chain list, chain unlink, pipeline create, pipeline list, pipeline show, pipeline add-step, pipeline delete

Integration

  • MCP server — 43+ tools for agent integration via Model Context Protocol
  • REST API — 28+ HTTP endpoints for remote integration (Starlette + raw ASGI fallback)
  • CLI — 30+ commands with Rich formatting
  • JSON or SQLite persistence — Zero-config JSON or production-grade SQLite

Quick Start

Install

pip install agent-scheduler
# Optional: for REST API support
pip install agent-scheduler[api]

CLI Usage

# Create a recurring job
agent-scheduler add --name "daily-report" --handler report.generate \
  --cron "0 9 * * MON-FRI" --priority high --tags reporting,daily

# Create a one-time delayed job
agent-scheduler add --name "cleanup-temp" --handler cleanup.run \
  --delay 3600 --tags maintenance

# Create a job with retry policy
agent-scheduler add --name "api-poll" --handler poll.endpoint \
  --cron "*/5 * * * *" --max-retries 3 --timeout 30

# List all jobs
agent-scheduler list

# Show job details
agent-scheduler show daily-report

# Manually run a job
agent-scheduler run daily-report

# Run all due jobs
agent-scheduler run-due

# View execution history
agent-scheduler history daily-report --limit 20

# View statistics
agent-scheduler stats

# Pause/resume a job
agent-scheduler pause daily-report
agent-scheduler resume daily-report

# Delete a job
agent-scheduler delete daily-report --force

Webhook Management

# Create a webhook for job completion events
agent-scheduler webhook add \
  --name "slack-notify" \
  --url "https://hooks.slack.com/services/XXX" \
  --events job.completed,job.failed \
  --tags monitoring \
  --secret "my-signing-secret"

# List webhooks
agent-scheduler webhook list

# View delivery history
agent-scheduler webhook deliveries

# Delete a webhook
agent-scheduler webhook delete <webhook-id> --force

Template Usage

# List available templates
agent-scheduler template list

# Show template details
agent-scheduler template show health-check

# Create a job from a template
agent-scheduler template use health-check \
  --name "api-health" \
  --payload '{"endpoint": "https://api.example.com/health"}'

# Create a custom template
agent-scheduler template add \
  --name "my-pipeline" \
  --handler pipeline.run \
  --description "My data pipeline" \
  --category data-pipeline \
  --cron "0 */4 * * *" \
  --tags pipeline \
  --max-retries 2 \
  --required-fields "payload.pipeline_id"

Analytics & Health (v0.4.0)

# Show the full analytics dashboard
agent-scheduler analytics

# Health report for a specific job
agent-scheduler health daily-report

Cron Toolkit (v0.4.0)

# Validate a cron expression
agent-scheduler cron validate "0 9 * * MON-FRI"

# Describe a cron expression in plain English
agent-scheduler cron describe "*/15 * * * *"
# => Every 15 minutes

# Preview the next 10 runs
agent-scheduler cron preview "0 9 * * *" --count 10

# Build a cron expression from parameters
agent-scheduler cron build --frequency daily --hour 9 --minute 30
# => 30 9 * * *
agent-scheduler cron build --frequency weekly --day monday --hour 9
# => 0 9 * * 0
agent-scheduler cron build --frequency every-n-minutes --n 15
# => */15 * * * *

REST API

# Start the REST API server
agent-scheduler api --host 0.0.0.0 --port 8080

# Or start the scheduler daemon (poll loop + MCP)
agent-scheduler start

# Or start the MCP server
agent-scheduler serve --port 8080

API Endpoints

MethodPathDescription
GET/healthHealth check
GET/api/v1/jobsList jobs
POST/api/v1/jobsCreate job
GET/api/v1/jobs/{id}Get job
PATCH/api/v1/jobs/{id}Update job
DELETE/api/v1/jobs/{id}Delete job
POST/api/v1/jobs/{id}/pausePause job
POST/api/v1/jobs/{id}/resumeResume job
POST/api/v1/jobs/{id}/runRun job
GET/api/v1/jobs/{id}/next-runGet next run time
GET/api/v1/jobs/{id}/dependenciesGet dependencies
GET/api/v1/historyExecution history
GET/api/v1/statsScheduler statistics
GET/api/v1/tagsList tags
GET/api/v1/tags/{tag}Jobs by tag
POST/api/v1/dependenciesCreate dependency
POST/api/v1/run-dueRun all due jobs
GET/api/v1/webhooksList webhooks
POST/api/v1/webhooksCreate webhook
DELETE/api/v1/webhooks/{id}Delete webhook
GET/api/v1/webhook-deliveriesDelivery history

MCP Tools (98 tools)

ToolDescription
scheduler_create_jobCreate a scheduled job
scheduler_list_jobsList jobs with filters
scheduler_get_jobGet job details
scheduler_update_jobUpdate job config
scheduler_delete_jobDelete a job
scheduler_pause_jobPause a job
scheduler_resume_jobResume a job
scheduler_run_jobManually trigger execution
scheduler_get_historyExecution history
scheduler_get_next_runNext scheduled run
scheduler_get_statsScheduler statistics
scheduler_list_tagsList all tags
scheduler_get_jobs_by_tagJobs by tag
scheduler_create_dependencyChain jobs
scheduler_get_dependenciesJob dependencies
scheduler_create_webhookCreate webhook subscription
scheduler_list_webhooksList webhooks
scheduler_delete_webhookDelete webhook
scheduler_get_webhook_deliveriesWebhook delivery history
scheduler_list_templatesList job templates
scheduler_get_templateGet template details
scheduler_instantiate_templateCreate job from template
scheduler_create_templateCreate custom template
scheduler_create_groupCreate a job group
scheduler_list_groupsList job groups
scheduler_get_groupGet group details
scheduler_pause_groupPause all jobs in group
scheduler_resume_groupResume all jobs in group
scheduler_analytics_dashboardFull analytics dashboard (v0.4.0)
scheduler_job_healthPer-job health report (v0.4.0)
scheduler_validate_cronValidate cron expression (v0.4.0)
scheduler_describe_cronDescribe cron in English (v0.4.0)
scheduler_preview_cronPreview upcoming runs (v0.4.0)
scheduler_build_cronBuild cron from parameters (v0.4.0)
scheduler_sla_register_policyRegister an SLA policy with tiers & escalations (v0.9.0)
scheduler_sla_list_policiesList SLA policies
scheduler_sla_delete_policyDelete an SLA policy
scheduler_sla_compliance_reportUptime-style SLA compliance report
scheduler_sla_list_assignmentsList job→policy assignments
scheduler_sla_list_breachesList SLA breaches with filters
scheduler_sla_waiveWaive a breach with reason
scheduler_sla_escalation_logEscalation audit log
scheduler_sla_tickAdvance SLA evaluation (breach detection + escalation)
scheduler_workflow_createCreate a multi-job workflow DAG (v0.9.0)
scheduler_workflow_getGet workflow details
scheduler_workflow_listList workflows
scheduler_workflow_deleteDelete a workflow
scheduler_workflow_validateValidate DAG (cycles, dangling refs)
scheduler_workflow_planCompute execution plan
scheduler_workflow_runExecute a workflow
scheduler_workflow_visualizeASCII visualization of the DAG
scheduler_workflow_statsWorkflow success/failure statistics
scheduler_workflow_executionsWorkflow execution history
scheduler_backfill_previewDry-run: preview missed windows for a job (v0.10.0)
scheduler_backfill_runBackfill missed windows synchronously
scheduler_backfill_asyncStart async backfill with max parallelism
scheduler_backfill_detect_staleFind jobs that missed runs while scheduler was down
scheduler_backfill_all_staleRecover all stale jobs in one call
scheduler_backfill_historyPast backfill runs for a job
scheduler_backfill_resultInspect a completed backfill result

Built-in Templates

TemplateHandlerDefault ScheduleCategory
health-checkhealth.checkEvery 5 minMonitoring
daily-backupbackup.runDaily 2 AMBackup
weekly-reportreport.generateMonday 9 AMReporting
data-pipelinepipeline.runEvery 6 hoursData Pipeline
cleanupcleanup.runDaily 3 AMMaintenance
notificationnotify.sendOn demandNotification

Webhook Events

EventWhen
job.createdJob is created
job.completedJob executes successfully
job.failedJob execution fails
job.timeoutJob execution times out
job.retryJob is being retried
job.pausedJob is paused
job.resumedJob is resumed
job.cancelledJob is cancelled
job.deletedJob is deleted

Python API

from agent_scheduler import Scheduler, Job, Priority, RetryPolicy
from agent_scheduler.webhook import Webhook, WebhookEvent

# Create scheduler
scheduler = Scheduler()

# Add a job
job = Job(
    name="daily-report",
    handler="report.generate",
    cron="0 9 * * MON-FRI",
    priority=Priority.HIGH,
    retry_policy=RetryPolicy(max_retries=3, backoff_seconds=60),
    tags=["reporting"],
    payload={"format": "pdf", "recipients": ["team@example.com"]},
)
scheduler.add_job(job)

# Add a webhook
webhook = Webhook(
    name="slack-notify",
    url="https://hooks.slack.com/services/XXX",
    events=[WebhookEvent.JOB_COMPLETED, WebhookEvent.JOB_FAILED],
    tags=["reporting"],
    secret="my-signing-secret",
)
scheduler.webhooks.create_webhook(webhook)

# Use a template
from agent_scheduler.templates import TemplateManager
manager = TemplateManager(store=scheduler.store)
job = manager.instantiate("health-check", payload={"endpoint": "https://api.example.com/health"})
scheduler.add_job(job)

# Run due jobs (async)
import asyncio
executions = asyncio.run(scheduler.run_due_jobs())

# Get stats
stats = scheduler.get_stats()
print(f"Active: {stats.active_jobs}, Failed: {stats.failed_jobs}")

Analytics API (v0.4.0)

from agent_scheduler.analytics import AnalyticsEngine

engine = AnalyticsEngine(scheduler=scheduler)

# Full dashboard
dashboard = engine.dashboard()
print(f"Health: {dashboard.overall_health_grade} ({dashboard.overall_health_score}/100)")
print(f"At-risk jobs: {dashboard.at_risk_jobs}")

# Single job health
job = scheduler.get_job_by_name("daily-report")
report = engine.job_report(job)
print(f"{report.job_name}: {report.health_grade} ({report.health_score}/100)")

Cron Toolkit API (v0.4.0)

from agent_scheduler.cron_helper import (
    validate_cron, describe_cron, preview_runs, suggest_cron, CronBuilder
)

# Validate
result = validate_cron("0 9 * * MON-FRI")
assert result.is_valid

# Describe
print(describe_cron("*/15 * * * *"))  # => "Every 15 minutes"

# Preview next runs
runs = preview_runs("0 9 * * *", n=5)

# Build from parameters
expr = suggest_cron("daily", hour=9, minute=30)  # => "30 9 * * *"
expr = suggest_cron("weekdays", hour=9)           # => "0 9 * * 0-4"

Notification Channels API (v0.4.0)

from agent_scheduler.notifications import (
    Notification, NotificationLevel, ChannelManager,
    SlackChannel, DiscordChannel, EmailChannel, HttpChannel,
)

# Set up channels
mgr = ChannelManager()
mgr.add_channel(SlackChannel(
    webhook_url="https://hooks.slack.com/services/XXX",
    name="ops-slack",
))
mgr.add_channel(DiscordChannel(
    webhook_url="https://discord.com/api/webhooks/XXX",
), levels=[NotificationLevel.ERROR])  # Only errors to Discord

# Send a notification
notif = Notification(
    title="Job Failed",
    message="daily-report failed after 3 retries",
    level=NotificationLevel.ERROR,
    job_name="daily-report",
    event_type="job.failed",
    metadata={"retry_count": 3},
)
results = asyncio.run(mgr.send(notif))

# Or create from config dict
from agent_scheduler.notifications import create_channel_from_config
ch = create_channel_from_config({
    "type": "slack",
    "webhook_url": "https://hooks.slack.com/services/XXX",
    "channel": "#alerts",
})

Handler Registration

Register custom handlers for real job execution:

from agent_scheduler import Scheduler, Job, HandlerRegistry

registry = HandlerRegistry()

# Sync handler
def my_handler(payload):
    # Do work
    return {"status": "done", "processed": len(payload)}

registry.register("my.handler", my_handler)

# Async handler
async def async_handler(payload):
    await some_async_work()
    return {"async": True}

registry.register("my.async_handler", async_handler)

scheduler = Scheduler(handler_registry=registry)

Configuration

Environment VariableDefaultDescription
SCHEDULER_DATA_DIR~/.agent-schedulerData storage directory

License

MIT

↑↓ navigate openesc close