Task Scheduler¶
The task scheduler lets you run agent queries automatically on a schedule -- once at a future time, on a recurring interval, or via a cron expression. Scheduled tasks are persisted in SQLite so they survive process restarts, and execution is handled by a background daemon thread that polls for due tasks every 60 seconds.
Optional component
The scheduler is a standalone module (openjarvis.scheduler). It is not wired into the default Jarvis / JarvisSystem startup. You enable it explicitly via SystemBuilder or by starting the CLI daemon with jarvis scheduler start.
Schedule Types¶
schedule_type |
schedule_value format |
Example | Meaning |
|---|---|---|---|
once |
ISO 8601 UTC datetime | "2026-03-01T09:00:00Z" |
Run once at that timestamp |
interval |
Seconds as a string | "3600" |
Run every hour, starting immediately |
cron |
Standard 5-field cron expression | "0 9 * * 1-5" |
09:00 UTC, Monday–Friday |
Cron support
Full cron expression support requires croniter (uv pip install croniter). Without it, the scheduler uses a minimal built-in parser that handles simple minute hour * * * patterns only.
CLI Commands¶
The jarvis scheduler subcommand group manages tasks and the daemon from the terminal.
Start the daemon¶
Starts the background polling daemon. The daemon runs in the foreground until interrupted (Ctrl+C). In production, run it under systemd or launchd (see Deployment).
Create a task¶
# Run once at a specific time
jarvis scheduler create \
--prompt "Generate the weekly summary report" \
--type once \
--value "2026-03-01T09:00:00Z"
# Run every hour
jarvis scheduler create \
--prompt "Check for new emails and summarize" \
--type interval \
--value "3600" \
--agent orchestrator \
--tools retrieval,think
# Run on a cron schedule
jarvis scheduler create \
--prompt "Summarize overnight logs" \
--type cron \
--value "0 8 * * 1-5"
List tasks¶
# All tasks
jarvis scheduler list
# Active tasks only
jarvis scheduler list --status active
# Paused tasks
jarvis scheduler list --status paused
Example output:
ID AGENT TYPE VALUE STATUS NEXT RUN
a3f9b12c4d8e simple cron 0 8 * * 1-5 active 2026-02-26T08:00:00+00:00
b7c2e56f1a3d orchestr interval 3600 active 2026-02-25T14:05:00+00:00
Pause and resume tasks¶
# Pause a running task
jarvis scheduler pause a3f9b12c4d8e
# Resume -- next_run is recomputed from the current time
jarvis scheduler resume a3f9b12c4d8e
Cancel a task¶
View run logs¶
Example output:
Run 1: started=2026-02-25T08:00:01Z finished=2026-02-25T08:00:04Z success=True
Result: Overnight logs contain 3 warnings and no errors.
Run 2: started=2026-02-24T08:00:00Z finished=2026-02-24T08:00:05Z success=True
Result: Logs are clean.
Python API¶
from openjarvis.scheduler.store import SchedulerStore
from openjarvis.scheduler.scheduler import TaskScheduler
# Set up storage
store = SchedulerStore(db_path="~/.openjarvis/scheduler.db") # (1)!
# Wire in a JarvisSystem for task execution
from openjarvis import Jarvis
jarvis = Jarvis()
scheduler = TaskScheduler(
store=store,
system=jarvis, # (2)!
poll_interval=60, # (3)!
)
# Create tasks
daily_summary = scheduler.create_task(
prompt="Summarize the latest news headlines",
schedule_type="cron",
schedule_value="0 8 * * *",
agent="simple",
)
print(f"Created task {daily_summary.id}, next run: {daily_summary.next_run}")
# List active tasks
for task in scheduler.list_tasks(status="active"):
print(f" {task.id}: {task.prompt} @ {task.next_run}")
# Manage task state
scheduler.pause_task(daily_summary.id)
scheduler.resume_task(daily_summary.id) # next_run recomputed from now
scheduler.cancel_task(daily_summary.id) # permanent
# Start the background thread
scheduler.start() # (4)!
# ... application runs ...
scheduler.stop()
jarvis.close()
- SQLite database storing all task state and run logs.
- The scheduler calls
system.ask(task.prompt, agent=task.agent, tools=...)when a task is due. Passsystem=Nonefor a dry-run mode that logs what it would execute without calling the agent. - Seconds between polling cycles. Lower values increase responsiveness at the cost of more SQLite reads.
- Starts a daemon thread named
"jarvis-scheduler". Daemon threads exit automatically when the main process exits.
ScheduledTask Fields¶
Every task is represented as a ScheduledTask dataclass.
| Field | Type | Default | Description |
|---|---|---|---|
id |
str |
auto (16 hex) | Unique task identifier |
prompt |
str |
-- | Query sent to the agent on execution |
schedule_type |
str |
-- | "cron", "interval", or "once" |
schedule_value |
str |
-- | Cron expression, interval seconds, or ISO datetime |
context_mode |
str |
"isolated" |
Execution context mode |
status |
str |
"active" |
"active", "paused", "completed", "cancelled" |
next_run |
str or None |
computed | ISO 8601 UTC datetime of the next execution |
last_run |
str or None |
None |
ISO 8601 UTC datetime of the last execution |
agent |
str |
"simple" |
Agent registry key to use for execution |
tools |
str |
"" |
Comma-separated tool names for the agent |
metadata |
dict |
{} |
Arbitrary metadata for the task |
Using Scheduler Tools with Agents¶
The five scheduler MCP tools (schedule_task, list_scheduled_tasks, pause_scheduled_task, resume_scheduled_task, cancel_scheduled_task) can be passed to any ToolUsingAgent, allowing an agent to schedule follow-up tasks autonomously.
# Let the orchestrator schedule its own follow-up
jarvis ask --agent orchestrator \
--tools schedule_task,list_scheduled_tasks \
"Research transformer architectures and schedule a daily summary at 8am"
from openjarvis import Jarvis
j = Jarvis()
response = j.ask(
"Schedule a weekly digest of research papers every Monday at 9am",
agent="orchestrator",
tools=["schedule_task"],
)
print(response)
See Scheduler Tools for full parameter reference.
Configuration¶
Scheduler settings live in the [scheduler] section of ~/.openjarvis/config.toml.
[scheduler]
enabled = false
db_path = "~/.openjarvis/scheduler.db"
poll_interval = 60
default_agent = "simple"
| Key | Type | Default | Description |
|---|---|---|---|
enabled |
bool |
false |
Start the scheduler daemon automatically |
db_path |
str |
~/.openjarvis/scheduler.db |
SQLite database path |
poll_interval |
int |
60 |
Seconds between polling cycles |
default_agent |
str |
"simple" |
Default agent for tasks that omit agent |
See Also¶
- Scheduler Tools reference -- MCP tool parameter details
- Architecture: Agentic Logic -- how the scheduler integrates with agents
- Deployment: systemd -- running the scheduler as a system service