Skip to main content

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.
callback
keyof this
required
Name of the method to call
options
ScheduleOptions
required
Schedule configuration (see variants below)
Returns: Promise<string> - Schedule ID

Schedule Types

One-Time (Specific Time)

Execute a callback at a specific date/time.
time
Date
required
Date/time to execute
payload
T
Data to pass to the callback
retry
RetryOptions
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).
delayInSeconds
number
required
Number of seconds to delay
payload
T
Data to pass to the callback
retry
RetryOptions
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
string
required
Cron expression (e.g., “0 0 * * *”)
payload
T
Data to pass to the callback
retry
RetryOptions
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).
intervalSeconds
number
required
Number of seconds between executions
payload
T
Data to pass to the callback
retry
RetryOptions
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:
retry
RetryOptions
maxAttempts
number
default:"3"
Maximum number of retry attempts
baseDelayMs
number
default:"100"
Base delay in milliseconds for exponential backoff
maxDelayMs
number
default:"3000"
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 });
}

Build docs developers (and LLMs) love