Cron Jobs
Schedule recurring work with cron expressions, running either a shell command (exec) or an agent session (session), with overlap modes (allow, skip, queue) and cronEvent streaming to monitor execution. Cron jobs keep the actor alive while a job runs; the actor can sleep between executions.
Schedule a command
Section titled “Schedule a command”Run a shell command on a recurring schedule. Pass a custom id to make a job easier to manage and cancel later.
import { createClient } from "@rivet-dev/agentos/client";import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });
// Schedule a cleanup script every hourconst { id } = await client.vm.getOrCreate("my-agent").scheduleCron({ schedule: "0 * * * *", action: { type: "exec", command: "rm", args: ["-rf", "/tmp/cache/*"], },});console.log("Cron job ID:", id);Schedule an agent session
Section titled “Schedule an agent session”Create a recurring agent session that runs a prompt on a schedule.
import { createClient } from "@rivet-dev/agentos/client";import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });
// Run an agent every day at 9 AM to check for issuesawait client.vm.getOrCreate("my-agent").scheduleCron({ schedule: "0 9 * * *", action: { type: "session", agentType: "pi", prompt: "Review the logs in /home/user/logs/ and summarize any errors", options: { cwd: "/home/user" }, },});Overlap modes
Section titled “Overlap modes”Control what happens when a cron job triggers while a previous execution is still running.
| Mode | Behavior |
|---|---|
"skip" | Skip this trigger if the previous run is still active |
"allow" | Allow concurrent executions (default) |
"queue" | Queue this trigger and run it after the previous one finishes |
Prefer "skip" for most jobs to avoid unbounded concurrency if a run takes longer than the interval. Use "queue" when every trigger must eventually execute.
import { createClient } from "@rivet-dev/agentos/client";import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });
// Queue overlapping executionsawait client.vm.getOrCreate("my-agent").scheduleCron({ schedule: "*/5 * * * *", overlap: "queue", action: { type: "session", agentType: "pi", prompt: "Process the next batch of tasks", },});Monitor cron events
Section titled “Monitor cron events”Subscribe to the cronEvent event to track job execution. It is emitted whenever a cron job runs, carrying a single payload field:
data.event: ACronEventdescribing the run.
const conn = handle.connect();conn.on("cronEvent", (data) => { // data is inferred: { event: CronEvent } console.log("Cron event:", data.event);});Subscribe before scheduling so you do not miss early runs.
import { createClient } from "@rivet-dev/agentos/client";import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });const handle = client.vm.getOrCreate("my-agent");
const conn = handle.connect();conn.on("cronEvent", (data) => { // data is inferred: { event: CronEvent } console.log("Cron event:", data.event);});
await handle.scheduleCron({ schedule: "*/1 * * * *", action: { type: "exec", command: "echo", args: ["heartbeat"] },});List and cancel cron jobs
Section titled “List and cancel cron jobs”import { createClient } from "@rivet-dev/agentos/client";import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });const handle = client.vm.getOrCreate("my-agent");
// List all cron jobsconst jobs = await handle.listCronJobs();for (const job of jobs) { console.log(job.id, job.schedule);}
// Cancel a specific jobawait handle.cancelCronJob(jobs[0].id);Example: Heartbeat pattern
Section titled “Example: Heartbeat pattern”Schedule a recurring agent session to periodically check on a task. This is the core pattern behind OpenClaw, where an agent wakes up on a schedule to review progress, take action, and go back to sleep.
await handle.scheduleCron({ schedule: "*/30 * * * *", overlap: "skip", action: { type: "session", agentType: "pi", prompt: "Check the status of open issues and take any necessary action", },});The agent sleeps between executions and only consumes resources when the cron job fires.