-
-
Notifications
You must be signed in to change notification settings - Fork 4
Scheduler and Cron
Cron scheduling, durable/session storage, jitter, catch-up, and fire injection for the agent runtime.
See also Exec Runtime and Chat System.
The scheduler owns cron-style scheduled tasks and is spawned from background tasks only when enabled. It supports both session-only tasks and durable tasks stored per project at <project>/.refact/scheduled_tasks.json.
- Session jobs live in the in-memory scheduler store and disappear on engine restart.
- Durable jobs are persisted per project and survive restarts.
- The scheduler uses a 5-field cron expression in local time.
- Jitter is applied automatically to spread load, but it does not change the stored cron expression.
- Due jobs do not inject while the owning chat is
Generating,ExecutingTools, orPaused; they defer and re-check later. - Recurring durable jobs compute their next future fire from now instead of replaying a backlog burst.
- Past one-shot durable jobs fire ASAP and may mark the fire payload as missed.
- Recurring jobs default to a 30-day auto-expiration window and final fires carry
final=truebefore deletion.
Scheduler startup and cron effects are skipped when any of the following are set:
REFACT_DISABLE_SCHEDULER=1--no-scheduler-
scheduler.enabled: falsein global config
A separate config flag, scheduler.disable_durable: true, makes cron_create fall back to session-only and return the note durable schedules disabled by config.
Schedule a prompt to be enqueued later.
Schema:
{
"type": "object",
"properties": {
"cron": { "type": "string", "description": "Standard 5-field cron expression in local time." },
"prompt": { "type": "string", "description": "Prompt enqueued at each fire time." },
"recurring": { "type": "boolean", "default": true },
"durable": { "type": "boolean", "default": false },
"description": { "type": "string", "description": "Short description (≤80 chars) shown in cron_list UI." }
},
"required": ["cron", "prompt", "description"]
}Returns { id, human_schedule, recurring, durable } and emits event(system_notice, "scheduler.cron", {id, cron, recurring, durable}, summary).
Notes:
- Rejects invalid cron expressions.
- Rejects expressions with no match within a year.
- Rejects descriptions over 80 chars.
- Rejects durable jobs when there is no project root.
- Rejects jobs beyond the configured cap.
List scheduled tasks, optionally filtering by session-only or durable scope.
Schema:
{
"type": "object",
"properties": {
"scope": { "type": "string", "enum": ["session", "durable", "all"], "default": "all" }
},
"required": []
}Returns an array of:
{
"id": "...",
"cron": "0 9 * * 1-5",
"human_schedule": "...",
"description": "...",
"prompt": "...",
"recurring": true,
"durable": true,
"next_fire_at_ms": 0,
"fire_count": 0,
"created_at_ms": 0
}The prompt is truncated to the first 200 characters.
Cancel a scheduled task by ID.
Schema:
{
"type": "object",
"properties": { "id": { "type": "string" } },
"required": ["id"]
}Returns { "removed": boolean } and notifies the runner to recompute wakeups.
On fire, the runner appends:
{
"role": "event",
"content": "...",
"extra": {
"event": {
"subkind": "cron_fire",
"source": "scheduler.cron",
"payload": {
"task_id": "...",
"cron": "...",
"recurring": true,
"fire_count": 1,
"final": false,
"missed": false
}
}
}
}It also enqueues a ChatCommand::UserMessage with the configured prompt so the agent wakes up.
Refact on GitHub: https://github.com/JegernOUTT/refact
- Agent Modes
- Agent Tools
- Task Planner & Cards
- Worktrees
- Subagents
- Memory & Knowledge
- Hidden Roles & Plans
- Context Compression
- Scheduler & Cron
- Processes & PTY
- Buddy
- MCP
- Skills, Commands & Hooks
- Marketplace
- Chat System
- Providers
- Caps & Models
- Code Completion (FIM)
- AST
- VecDB
- Exec Runtime
- HTTP API
- Checkpoints & Git
- Voice