How Prime Agent's Scheduling Architecture Manages Delayed and Recurring Prompts
Prime Agent employs a dedicated cron-style subsystem utilizing AgentCronJobStore for persistence and AgentCronScheduler for execution to handle both delayed (one-time) and recurring prompts through interval and cron expression support.
The PrimeIntellect-ai/prime-agent repository implements a deterministic scheduling architecture that cleanly separates job definition from execution logic. This system enables AI agents to schedule future tasks using human-readable strings like "in 10m" or "every 5m", persisting state across daemon restarts in scheduled-jobs.json while respecting Node.js timer limitations.
Core Components of the Scheduling Architecture
AgentCronJobStore and Persistent State
The AgentCronJobStore class in packages/coding-agent/src/core/cron-jobs.ts handles persistence of scheduled jobs to a JSON file (typically scheduled-jobs.json). It provides CRUD operations for managing job lifecycles, storing critical metadata including nextRunAt timestamps, schedule configurations, and current status. The job record structure (lines 35‑53) defines fields such as activeSessionId, sessionFile, prompt, and status, ensuring scheduled prompts survive process restarts.
AgentCronScheduler and Execution Logic
The AgentCronScheduler drives the actual execution loop. It polls the store, calculates next run times, and invokes the supplied runJob hook when deadlines are reached. The scheduler's runDue method updates nextRunAt after each execution for recurring jobs, while one-time jobs transition to "completed" or "cancelled" status. This implementation handles the timer orchestration, including fallback logic when delays exceed Node.js's maximum timeout value.
Schedule Types and Parsing
The system supports three distinct schedule kinds via AgentCronScheduleKind:
"once"— Single delayed execution at a specific future time"interval"— Recurring execution based on fixed millisecond intervals"cron"— Full cron-expression support for complex scheduling patterns
The parseAgentCronSchedule function converts human-readable strings (e.g., "in 1m", "every 5m") into structured AgentCronSchedule objects with calculated nextRunAt timestamps. Schedule definitions (lines 29‑33) specify the shape including kind, intervalMs, and cron expressions.
Handling Delayed (One-Time) Prompts
When users supply schedules like "in 1m", the parser returns a kind: "once" schedule with nextRunAt set to the current time plus the specified duration. The create method (lines 23‑46) persists this job with status: "active".
The scheduler monitors active jobs and fires when nextRunAt is reached. Upon execution completion, the job status updates to "completed" (or "cancelled" on error), preventing further invocations.
import { AgentCronJobStore } from "./core/cron-jobs.js";
const store = new AgentCronJobStore("my-session/scheduled-jobs.json");
// Schedule a one-time delayed prompt
store.create({
activeSessionId: "sess-1",
sessionId: "sess-1",
sessionFile: "session.json",
cwd: "/home/user",
label: "reminder",
prompt: "Check inbox",
scheduleText: "in 10m", // Executes once after 10 minutes
});
Managing Recurring Prompts
Interval-Based Recurrence
For schedules such as "every 5m", parseAgentCronSchedule produces kind: "interval" with intervalMs set to 300,000 milliseconds. The create method initializes nextRunAt to the current time plus the interval duration.
After each successful execution, the scheduler's runDue implementation updates nextRunAt by adding intervalMs to the previous value. The job maintains status: "active" indefinitely, enabling continuous execution until explicitly paused, cancelled, or until the session terminates.
Cron Expression Support
The architecture also supports standard cron expressions through the "cron" schedule kind, allowing complex patterns like "0 9 * * 1" for weekly Monday morning executions. The scheduler evaluates these expressions to determine the next valid nextRunAt timestamp using standard cron parsing logic.
// Schedule a recurring heartbeat prompt
store.create({
activeSessionId: "sess-1",
sessionId: "sess-1",
sessionFile: "session.json",
cwd: "/home/user",
label: "heartbeat",
prompt: "Send keep-alive",
scheduleText: "every 5m", // Recurring every 5 minutes
});
Daemon Integration and Heartbeat Defaults
The daemon mode in packages/coding-agent/src/modes/daemon/daemon-mode.ts instantiates AgentCronScheduler and wires the runJob hook to the agent's execution pipeline. It leverages the createHeartbeat method (lines 13‑50) to establish default recurring schedules.
The system supplies a default heartbeat schedule of every 5m (defined in lines 17‑18) and a default delivery mode of steer. This ensures continuous agent activity through persistent, automatically managed heartbeat prompts that keep the session alive between user interactions.
Edge Cases and Timer Limitations
The scheduler respects Node.js's maximum timer value (MAX_TIMEOUT_MS ≈ 2.1 billion milliseconds). When nextRunAt exceeds this limit (roughly 24.8 days in the future), the implementation falls back to a poll-loop mechanism rather than using native setTimeout. This ensures reliable execution of long-delayed prompts without timer overflow issues.
Unit tests in packages/coding-agent/test/cron-jobs.test.ts verify correct state transitions for both delayed (in 1m) and recurring (every 5m) scenarios, ensuring the architecture handles edge cases deterministically.
Summary
- Prime Agent's scheduling architecture separates persistence (
AgentCronJobStore) from execution (AgentCronScheduler) to enable reliable delayed and recurring prompts. - Three schedule kinds—
"once","interval", and"cron"—support everything from one-time delays to complex recurring patterns. - Human-readable parsing via
parseAgentCronScheduleconverts strings like"in 10m"or"every 5m"into executable schedules with precisenextRunAttimestamps. - State management tracks job status through
"active","completed", and"cancelled"states, persisting toscheduled-jobs.jsonfor durability across restarts. - Timer safety respects Node.js's
MAX_TIMEOUT_MSlimit through intelligent poll-loop fallbacks for long-dated schedules.
Frequently Asked Questions
How does Prime Agent parse human-readable schedule strings?
The parseAgentCronSchedule function in packages/coding-agent/src/core/cron-jobs.ts analyzes strings like "in 1m" or "every 5m" to determine the schedule kind, extract millisecond values, and calculate the initial nextRunAt timestamp. It supports relative time expressions for delayed execution and recurrence patterns, returning a structured AgentCronSchedule object that the job store can persist and the scheduler can execute.
What happens when a scheduled prompt fails during execution?
When the runJob hook encounters an error, the scheduler catches the exception and updates the job's status to "cancelled" rather than "completed". For recurring interval jobs, this typically prevents the next nextRunAt calculation, effectively halting the schedule. The persisted state in scheduled-jobs.json preserves the error status, allowing inspection and potential rescheduling by the user or daemon recovery logic.
How does the scheduler handle very long delays beyond Node.js timer limits?
The architecture monitors whether nextRunAt exceeds MAX_TIMEOUT_MS (approximately 2.1 billion milliseconds or 24.8 days). When delays extend beyond this boundary, AgentCronScheduler abandons the standard setTimeout approach and switches to a poll-loop mechanism that periodically checks if the target time has been reached, ensuring reliable execution of long-dated prompts without timer overflow.
Can recurring jobs be paused or cancelled mid-execution?
Yes. The AgentCronJobStore provides methods to update job status from "active" to "paused" or "cancelled". While paused, the scheduler skips execution of that job's runJob hook even when nextRunAt is reached. Cancellation permanently stops the schedule regardless of kind, preventing both immediate execution and future next-run calculations for interval or cron-based prompts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →