Agent Scheduler: Durable Cron Tasks for AI Agents
Your AI agent generated a report at 3 AM. You want it scraped again tomorrow. And the day after. But your agent's chat session ended, the laptop went to sleep, or Claude Desktop is closed for the night.
The Agent Scheduler is a durable task runner that keeps working after your agent goes offline. You create a cron schedule, point it at a URL, and the platform fires POST requests on time — every time — whether your agent is running or not.
Current scope: Scheduler tasks are HTTP calls to public destinations you define. The platform handles timing, retries, and delivery history — it does not execute arbitrary server-side code, manage internal workflow steps, or invoke other Agent Media Tools endpoints directly.
Why your agent needs an offline task runner
AI agents are great at planning multi-step work. They're terrible at staying online. Every time you close Claude Desktop, finish a ChatGPT session, or restart Hermes, anything scheduled to happen next — a daily scrape, a weekly report, a midnight cleanup — simply doesn't run.
The Agent Scheduler solves this by decoupling scheduling from execution:
- You define the schedule with a cron expression, timezone, and target URL.
- The platform runs the task — your agent doesn't need to be online.
- Results are stored in a delivery history you can inspect later.
- Your agent picks up when it comes back online: check the history, read the delivery body, react to failures.
API overview
| Method | Route | Purpose |
|---|---|---|
| POST | /api/agent/schedules | Create a one-time or recurring schedule |
| GET | /api/agent/schedules | List your schedules |
| GET | /api/agent/schedules/:id | Read a single schedule |
| PATCH | /api/agent/schedules/:id | Pause, resume, or update a schedule |
| DELETE | /api/agent/schedules/:id | Delete a schedule |
| POST | /api/agent/schedules/:id/run | Manually trigger a run (outside the cron) |
| GET | /api/agent/schedules/:id/history | Read delivery history for a schedule |
All endpoints require an API key (Bearer token) and authenticate against your account's daily limits. Free accounts get 3 schedules, Pro gets 25, and Builder gets 100.
curl examples
💡 Windows users: Run these commands from Git Bash or WSL. PowerShell aliases curl to Invoke-WebRequest.
1. Create a daily scraping schedule
This schedule fires a POST to your public endpoint every morning at 6 AM Eastern:
curl -X POST https://agentmediatools.com/api/agent/schedules \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"name": "Daily HackerNews Scrape",
"description": "Scrape HN top stories every morning",
"method": "POST",
"url": "https://your-domain.com/hook/scrape-hn",
"headers": {
"X-Auth": "your-hmac-secret",
"Content-Type": "application/json"
},
"body": {
"target": "https://news.ycombinator.com",
"max_articles": 30
},
"schedule": {
"type": "cron",
"expression": "0 6 * * *",
"timezone": "America/New_York"
},
"retry_on_failure": true,
"max_retries": 3
}'
The response returns the created schedule with its ID, the next scheduled run, and status:
{
"id": "sch_a1b2c3d4e5f6",
"name": "Daily HackerNews Scrape",
"status": "active",
"next_run": "2026-07-18T10:00:00Z",
"created_at": "2026-07-17T14:00:00Z"
}
2. Create a one-time delayed task
Sometimes you don't need recurring — just a single future execution. Use type: "one_time" with an ISO datetime:
curl -X POST https://agentmediatools.com/api/agent/schedules \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"name": "Send weekly report at midnight",
"method": "POST",
"url": "https://your-domain.com/hook/send-report",
"body": {"report_type": "weekly", "format": "pdf"},
"schedule": {
"type": "one_time",
"run_at": "2026-07-24T00:00:00Z"
}
}'
One-time tasks auto-delete after their execution. Use the recurring cron type for ongoing work.
3. List all schedules
curl https://agentmediatools.com/api/agent/schedules \ -H "Authorization: Bearer YOUR_API_KEY"
Response includes status (active, paused, completed for one-time), next run time, and the original configuration.
4. Pause and resume
Pausing stops future runs without deleting the schedule. Resume to reactivate:
curl -X PATCH https://agentmediatools.com/api/agent/schedules/sch_a1b2c3d4e5f6 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"status": "paused"}'
curl -X PATCH https://agentmediatools.com/api/agent/schedules/sch_a1b2c3d4e5f6 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"status": "active"}'
5. View delivery history
curl https://agentmediatools.com/api/agent/schedules/sch_a1b2c3d4e5f6/history \ -H "Authorization: Bearer YOUR_API_KEY"
Each history entry shows the run timestamp, HTTP status code returned by your endpoint, response body (truncated if large), and any error message:
{
"schedule_id": "sch_a1b2c3d4e5f6",
"total_runs": 4,
"history": [
{
"run_id": "run_abc123",
"triggered_at": "2026-07-17T10:00:00Z",
"status": 200,
"response_preview": "{\"ok\":true,\"articles_scraped\":30}",
"duration_ms": 1247
},
{
"run_id": "run_def456",
"triggered_at": "2026-07-16T10:00:00Z",
"status": 0,
"error": "Connection refused",
"retry_of": "run_def456",
"retry_count": 2
}
]
}
Python example: agent-managed schedules
Here's a complete Python script that lets an agent create, inspect, and manage schedules programmatically — useful for a coordinator agent or an n8n workflow:
import requests
import json
import sys
API_KEY = "YOUR_API_KEY"
BASE = "https://agentmediatools.com"
HEADERS = {
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}"
}
# ── Create a daily schedule ─────────────────────────────────
def create_daily_scrape(name, target_url, hook_url, cron_expr, tz="UTC"):
"""Create a recurring schedule that POSTs scrape instructions to your hook."""
payload = {
"name": name,
"description": f"Scrape {target_url} on cron",
"method": "POST",
"url": hook_url,
"headers": {"Content-Type": "application/json"},
"body": {"target": target_url},
"schedule": {
"type": "cron",
"expression": cron_expr,
"timezone": tz
},
"retry_on_failure": True,
"max_retries": 3
}
r = requests.post(f"{BASE}/api/agent/schedules",
headers=HEADERS, json=payload)
return r.json()
# ── Create a one-time schedule ──────────────────────────────
def create_one_time_task(name, hook_url, body, run_at_iso):
"""Fire a POST once at a specific future time."""
payload = {
"name": name,
"method": "POST",
"url": hook_url,
"body": body,
"schedule": {
"type": "one_time",
"run_at": run_at_iso
}
}
r = requests.post(f"{BASE}/api/agent/schedules",
headers=HEADERS, json=payload)
return r.json()
# ── List active schedules ──────────────────────────────────
def list_schedules():
r = requests.get(f"{BASE}/api/agent/schedules", headers=HEADERS)
return r.json()
# ── Read schedule history ──────────────────────────────────
def get_history(schedule_id):
r = requests.get(f"{BASE}/api/agent/schedules/{schedule_id}/history",
headers=HEADERS)
return r.json()
# ── Pause / resume ─────────────────────────────────────────
def set_status(schedule_id, new_status):
r = requests.patch(f"{BASE}/api/agent/schedules/{schedule_id}",
headers=HEADERS,
json={"status": new_status})
return r.json()
# ── Manual run ─────────────────────────────────────────────
def trigger_now(schedule_id):
r = requests.post(
f"{BASE}/api/agent/schedules/{schedule_id}/run",
headers=HEADERS)
return r.json()
# ── Delete ─────────────────────────────────────────────────
def delete_schedule(schedule_id):
r = requests.delete(
f"{BASE}/api/agent/schedules/{schedule_id}",
headers=HEADERS)
return r.json()
# ── Demo ───────────────────────────────────────────────────
if __name__ == "__main__":
action = sys.argv[1] if len(sys.argv) > 1 else "create"
if action == "create":
sched = create_daily_scrape(
name="Daily HN Top Stories",
target_url="https://news.ycombinator.com",
hook_url="https://my-worker.example.com/hooks/scrape",
cron_expr="0 8 * * 1-5",
tz="America/New_York"
)
print(f"✅ Created: {sched['name']} (id={sched['id']})")
print(f" Next run: {sched['next_run']}")
elif action == "list":
data = list_schedules()
for s in data.get("schedules", []):
print(f" [{s['status']}] {s['name']} — id={s['id']}")
elif action == "history" and len(sys.argv) > 2:
hist = get_history(sys.argv[2])
for entry in hist.get("history", []):
status = entry.get("status", "N/A")
print(f" {entry['triggered_at']} → HTTP {status}")
elif action == "trigger" and len(sys.argv) > 2:
result = trigger_now(sys.argv[2])
print(f"Triggered: {result}")
else:
print("""Usage:
python scheduler.py create
python scheduler.py list
python scheduler.py history SCHEDULE_ID
python scheduler.py trigger SCHEDULE_ID
python scheduler.py pause SCHEDULE_ID
python scheduler.py resume SCHEDULE_ID
python scheduler.py delete SCHEDULE_ID""")
Via MCP (for Claude Desktop / Hermes)
If you use the Agent Media Tools MCP server, your agent can manage schedules through natural language:
"Create a daily scrape schedule that fires at 6 AM Eastern and POSTs to my webhook"
The MCP server exposes these scheduler tools:
create_schedule— Create a cron or one-time schedulelist_schedules— View all schedulesget_schedule— Read a single schedule by IDupdate_schedule— Pause, resume, or modify a scheduledelete_schedule— Remove a schedule and its historytrigger_schedule— Manually run a schedule nowget_schedule_history— Read past deliveries
💡 Cron expression reference: Standard 5-field UNIX cron (minute hour day month weekday). 0 6 * * * = daily at 6 AM. */15 * * * * = every 15 minutes. 0 9 * * 1-5 = weekdays at 9 AM. TZ defaults to UTC if not specified.
Real-world patterns
1. Daily data ingestion
Your agent sets up a schedule that POSTs to a Vercel Edge Function or Cloudflare Worker every morning. The worker fetches API data, transforms it, and pushes it to your database. Your agent checks the schedule history when it comes online to verify today's ingestion ran.
2. Weekly report generation
A one-time schedule fires every Sunday at midnight, triggering a script that generates a PDF report and emails it to stakeholders. The schedule is re-created each week by the agent with the updated parameters — or you keep a cron schedule pointing at the same endpoint.
3. Heartbeat / uptime monitoring
Set a cron schedule that fires every 5 minutes to a health-check endpoint. If the endpoint fails to respond, the platform's retry mechanism gives you visibility into delivery failures — the history shows exactly which runs failed and when.
4. Midnight cleanup + one-time override
Keep a recurring cron for daily temp-file cleanup. When something urgent needs immediate cleanup, trigger a manual run via POST /api/agent/schedules/:id/run without waiting for the next cron tick. The manual run doesn't interfere with the cron schedule.
Scheduler vs. Pipeline Builder vs. Webhooks
Agent Media Tools has three systems for executing work over time. Here's how they differ:
| Feature | Agent Scheduler | Pipeline Builder | Webhooks |
|---|---|---|---|
| Trigger | Cron or future time | Manual (human or API) | External event (job done, etc.) |
| Execution | HTTP call to your endpoint | Server-side step execution | HTTP POST to your endpoint |
| Retries | Automatic (configurable) | Manual via on_error policy | Up to 5 retries, exp backoff |
| History | Full delivery log | Run history per pipeline | Delivery receipts |
| Auth required | API key | Browser session | API key for management |
| Free limit | 3 schedules | Unlimited self-serve | 1 webhook URL |
Use the Scheduler when you need time-based execution and your agent needs to stay offline. Use Pipelines for synchronous multi-step media workflows. Use Webhooks to get notified when something finishes.
Pricing and limits
- Free: 3 schedules — enough for daily scrapes, weekly reports, and one-off tasks
- Pro ($5/mo): 25 schedules
- Builder ($15/mo): 100 schedules
- Cron precision: Fires within ~60 seconds of the scheduled minute
- HTTP timeout: 30 seconds per execution
- Response size stored: First 4 KB of the response body captured in history
- History retention: 30 days per schedule
Getting started
- Sign up at agentmediatools.com — free account
- Generate an API key from your account settings
- Decide what runs — set up a simple webhook receiver or a serverless function
- Create your first schedule with the curl command above
- Check the history after the first run — inspect delivery status and response
Your agent stays focused on planning and decision-making. The Scheduler handles the execution, retries, and timing — whether your agent is online or not.
⏰ Keep your agent working while it's asleep
Create a schedule in under 30 seconds. Free accounts get 3 schedules — enough for daily scrapes, weekly reports, and one-off tasks.
Tags: cron, scheduled tasks, agent scheduler, durable execution, offline agent, periodic HTTP, cron schedule API, AI agent scheduling, background jobs for AI agents