Skip to content

Schedule tasks

Last updated View as MarkdownAgent setup

The Agent class installs the Scheduler capability. Its scheduling methods call the scheduler, and a callback name is the name of a method on your Agent. Schedules are stored in SQLite and run from the Lifecycle's job queue, so they survive restarts and evictions. For schedule options, retries, limits, and natural-language parsing, refer to the Scheduler capability.

Schedule a callback

import { Agent } from "agents";

export class ReminderAgent extends Agent {
	async onStart() {
		// Recurring schedules are idempotent, so this adds one row however often the Agent starts.
		await this.schedule("0 8 * * *", "dailyDigest");
	}

	async remindLater(message) {
		await this.schedule(30, "sendReminder", { message }); // in 30 seconds
		await this.schedule(new Date("2026-12-01T09:00:00Z"), "sendReminder", {
			message,
		});
		await this.scheduleEvery(300, "checkInbox"); // every 5 minutes
	}

	async sendReminder(payload) {
		console.log(payload.message);
	}

	async dailyDigest() {}

	async checkInbox() {}
}
import { Agent } from "agents";

export class ReminderAgent extends Agent<Env> {
	async onStart() {
		// Recurring schedules are idempotent, so this adds one row however often the Agent starts.
		await this.schedule("0 8 * * *", "dailyDigest");
	}

	async remindLater(message: string) {
		await this.schedule(30, "sendReminder", { message }); // in 30 seconds
		await this.schedule(new Date("2026-12-01T09:00:00Z"), "sendReminder", {
			message,
		});
		await this.scheduleEvery(300, "checkInbox"); // every 5 minutes
	}

	async sendReminder(payload: { message: string }) {
		console.log(payload.message);
	}

	async dailyDigest() {}

	async checkInbox() {}
}

Agent methods

Agent method Scheduler equivalent
schedule(when, callback, payload?, options?) scheduler.set()
scheduleEvery(intervalSeconds, callback, payload?, options?) scheduler.every()
getScheduleById(id) scheduler.get()
listSchedules(criteria?) scheduler.list()
cancelSchedule(id) scheduler.cancel()

when is a delay in seconds, a Date, or a cron string. callback must name a method on the Agent. getSchedule() and getSchedules() are deprecated synchronous versions of getScheduleById() and listSchedules().

Keeping the agent alive

An idle Durable Object is evicted after about 70 to 140 seconds without requests, messages, or alarms. Work in flight at that moment stops. keepAliveWhile() holds a heartbeat on the shared alarm while a function runs, and releases it when the function settles:

import { Agent } from "agents";

export class ReportAgent extends Agent {
	async buildReport() {
		return this.keepAliveWhile(async () => {
			// Long work that must not be interrupted by idle eviction.
			return "done";
		});
	}
}
import { Agent } from "agents";

export class ReportAgent extends Agent<Env> {
	async buildReport() {
		return this.keepAliveWhile(async () => {
			// Long work that must not be interrupted by idle eviction.
			return "done";
		});
	}
}

keepAlive() returns a disposer instead, for work that does not fit one function. Always call the disposer. AIChatAgent keeps itself alive while it streams a reply. Scheduled callbacks and Workflows do not need it.

A heartbeat only prevents idle eviction. A deploy or crash still stops the work, so schedule a job or use a Workflow for work that must finish.

Next steps

Was this helpful?