Documentation Index
Fetch the complete documentation index at: https://mintlify.com/cloudflare/agents/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Agents provide built-in task scheduling with support for one-time tasks, delayed execution, cron-based schedules, and fixed intervals. Schedules persist across hibernation and support automatic retry on failure.
import { Agent, callable } from "agents";
class TaskAgent extends Agent {
async onStart() {
// Schedule a daily backup at midnight
await this.schedule("dailyBackup", {
cron: "0 0 * * *"
});
}
async dailyBackup() {
console.log("Running daily backup...");
// Backup logic
}
}
schedule()
Schedule a callback to run at a future time or on a recurring interval.
Name of the method to call
Schedule configuration (see variants below)
Returns: Promise<string> - Schedule ID
Schedule Types
One-Time (Specific Time)
Execute a callback at a specific date/time.
Data to pass to the callback
Retry options for this schedule
// Schedule for tomorrow at 2 PM
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(14, 0, 0, 0);
await this.schedule("sendReminder", {
time: tomorrow,
payload: { userId: "123", type: "subscription" }
});
Delayed Execution
Execute a callback after a delay (in seconds).
Number of seconds to delay
Data to pass to the callback
Retry options for this schedule
// Schedule to run in 1 hour
await this.schedule("processUpload", {
delayInSeconds: 3600,
payload: { fileId: "abc123" }
});
// Schedule to run in 30 seconds
await this.schedule("quickTask", {
delayInSeconds: 30
});
Cron Schedule
Execute a callback on a recurring schedule using cron syntax.
Cron expression (e.g., “0 0 * * *”)
Data to pass to the callback
Retry options for this schedule
// Every day at midnight
await this.schedule("dailyBackup", {
cron: "0 0 * * *"
});
// Every Monday at 9 AM
await this.schedule("weeklyReport", {
cron: "0 9 * * 1",
payload: { reportType: "weekly" }
});
// Every 15 minutes
await this.schedule("healthCheck", {
cron: "*/15 * * * *"
});
Cron Format: minute hour day month weekday
* = any value
*/n = every n units
0-6 = Sunday through Saturday (for weekday)
Interval
Execute a callback at fixed intervals (in seconds).
Number of seconds between executions
Data to pass to the callback
Retry options for this schedule
// Every 5 minutes
await this.schedule("syncData", {
intervalSeconds: 300
});
// Every hour
await this.schedule("generateReport", {
intervalSeconds: 3600,
payload: { reportType: "hourly" }
});
Interval schedules are resilient to hung executions. If a callback takes longer than hungScheduleTimeoutSeconds (default: 30s), the interval is reset.
Callback Implementation
Scheduled callbacks receive the payload (if provided):
class TaskAgent extends Agent<Env, State> {
async onStart() {
await this.schedule("processTask", {
time: new Date(Date.now() + 3600000),
payload: { taskId: "123", priority: "high" }
});
}
async processTask(payload: { taskId: string; priority: string }) {
console.log(`Processing task ${payload.taskId} with priority ${payload.priority}`);
// Task logic
}
}
Retry Options
Schedules support automatic retry on failure:
Maximum number of retry attempts
Base delay in milliseconds for exponential backoff
Maximum delay cap in milliseconds
await this.schedule("unreliableTask", {
delayInSeconds: 60,
retry: {
maxAttempts: 5,
baseDelayMs: 200,
maxDelayMs: 5000
}
});
Retry options can also be configured globally via static options.retry on the Agent class.
Managing Schedules
getSchedules()
Query existing schedules.
const schedules = this.sql<Schedule>`
SELECT * FROM cf_agents_schedules
WHERE callback = 'dailyBackup'
`;
for (const schedule of schedules) {
console.log(`Schedule ${schedule.id}: ${schedule.type}`);
}
cancelSchedule()
Cancel a scheduled task.
const scheduleId = await this.schedule("task", { delayInSeconds: 60 });
// Cancel it
this.sql`DELETE FROM cf_agents_schedules WHERE id = ${scheduleId}`;
updateSchedule()
Update a schedule’s payload or timing:
this.sql`
UPDATE cf_agents_schedules
SET payload = ${JSON.stringify(newPayload)}
WHERE id = ${scheduleId}
`;
Queue vs Schedule
queue()
For immediate asynchronous execution:
// Execute as soon as possible
await this.queue("processUpload", {
fileId: "abc123"
});
When to use:
- Immediate background tasks
- Fire-and-forget operations
- No specific timing requirements
schedule()
For time-based or recurring execution:
// Execute at a specific time
await this.schedule("sendEmail", {
time: scheduledDate,
payload: { to: "user@example.com" }
});
When to use:
- Time-based tasks
- Recurring operations
- Delayed execution
Natural Language Scheduling
Use AI to parse natural language schedule requests:
import { generateObject } from "ai";
import { scheduleSchema, getSchedulePrompt } from "agents/schedule";
@callable()
async scheduleTask(userInput: string) {
const result = await generateObject({
model: this.env.AI.run("@cf/meta/llama-3.3-70b-instruct-fp8-fast"),
prompt: `${getSchedulePrompt({ date: new Date() })} Input: "${userInput}"`,
schema: scheduleSchema,
providerOptions: {
openai: { strictJsonSchema: false }
}
});
const { description, when } = result.object;
switch (when.type) {
case "scheduled":
await this.schedule("executeTask", {
time: new Date(when.date),
payload: { description }
});
break;
case "delayed":
await this.schedule("executeTask", {
delayInSeconds: when.delayInSeconds,
payload: { description }
});
break;
case "cron":
await this.schedule("executeTask", {
cron: when.cron,
payload: { description }
});
break;
}
return `Scheduled: ${description}`;
}
Example inputs:
- “Backup database every day at midnight”
- “Send report tomorrow at 2 PM”
- “Run health check every 15 minutes”
Persistence
Schedules are stored in SQLite:
CREATE TABLE cf_agents_schedules (
id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),
callback TEXT,
payload TEXT,
type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed', 'cron', 'interval')),
time INTEGER,
delayInSeconds INTEGER,
cron TEXT,
intervalSeconds INTEGER,
running INTEGER DEFAULT 0,
retry_options TEXT,
created_at INTEGER DEFAULT (unixepoch())
);
Schedules survive Agent hibernation and are automatically restored on wake.
Best Practices
Keep Callbacks Small
// ✅ Good - focused callback
async dailyBackup() {
const data = await this.fetchData();
await this.sendToBackup(data);
}
// ❌ Bad - too much logic
async dailyBackup() {
// 100 lines of backup logic
}
Use Payloads for Context
// ✅ Good - payload provides context
await this.schedule("processOrder", {
delayInSeconds: 3600,
payload: { orderId: "123", customerId: "456" }
});
async processOrder(payload: { orderId: string; customerId: string }) {
const order = await this.fetchOrder(payload.orderId);
// ...
}
// ❌ Bad - no context
await this.schedule("processOrder", {
delayInSeconds: 3600
});
Handle Failures
async unreliableTask(payload: unknown) {
try {
await this.externalAPI.call(payload);
} catch (error) {
console.error("Task failed:", error);
// Retry is automatic if retry options are set
throw error;
}
}
Use Cron for Recurring Tasks
// ✅ Good - cron for daily task
await this.schedule("dailyReport", {
cron: "0 9 * * *" // 9 AM every day
});
// ❌ Bad - manually scheduling daily
for (let i = 0; i < 365; i++) {
const date = new Date();
date.setDate(date.getDate() + i);
await this.schedule("dailyReport", { time: date });
}