mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-28 14:07:55 +00:00
216 lines
8.0 KiB
Markdown
216 lines
8.0 KiB
Markdown
---
|
|
title: Scheduled Personal Ops
|
|
description: Run autonomous agents on cron schedules for recurring personal tasks
|
|
---
|
|
|
|
# Scheduled Personal Ops
|
|
|
|
This tutorial walks through `examples/scheduled_ops/` — three scripts that run autonomous agents on cron-like schedules to handle recurring personal tasks. Together they demonstrate how to combine the `Jarvis` SDK, the scheduler CLI, and the Python `TaskScheduler` API to build a personal operations layer that runs in the background.
|
|
|
|
!!! tip "Prerequisites"
|
|
- Python 3.10 or later
|
|
- OpenJarvis installed: `uv sync --extra dev` from the repository root
|
|
- An inference engine running (Ollama with `qwen3:8b` pulled, or a cloud API key)
|
|
- For full cron expression support, install `croniter`: `uv add croniter`
|
|
|
|
## The Three Scripts
|
|
|
|
| Script | Agent | Tools | Default Schedule | Purpose |
|
|
|---|---|---|---|---|
|
|
| `daily_digest.py` | `orchestrator` | `web_search`, `think` | Daily 9:00 AM | Search and summarize top news for chosen topics |
|
|
| `code_review.py` | `native_react` | `git_log`, `git_diff`, `file_read`, `think` | Monday 8:00 AM | Review the past week of commits in a repository |
|
|
| `gym_scheduler.py` | `orchestrator` | `web_search`, `think` | MWF 6:00 AM | Check gym hours and class availability |
|
|
|
|
Each script follows the same SDK pattern: create a `Jarvis` instance, call `j.ask()` with an agent and tools, print the result, and close the instance. The schedule is managed externally by the OpenJarvis scheduler daemon.
|
|
|
|
## Quick Start: Run Scripts Manually
|
|
|
|
Test each script without a running scheduler by invoking it directly:
|
|
|
|
```bash title="Terminal"
|
|
# Morning news digest for AI and robotics
|
|
uv run python examples/scheduled_ops/daily_digest.py --topics "AI,robotics"
|
|
|
|
# Code review for the current repository (last 7 days of commits)
|
|
uv run python examples/scheduled_ops/code_review.py --repo-path .
|
|
|
|
# Gym schedule check
|
|
uv run python examples/scheduled_ops/gym_scheduler.py --gym "24 Hour Fitness"
|
|
```
|
|
|
|
All scripts accept `--model` and `--engine` flags:
|
|
|
|
```bash title="Terminal"
|
|
uv run python examples/scheduled_ops/daily_digest.py \
|
|
--model qwen3:8b --engine ollama --topics "AI,finance"
|
|
```
|
|
|
|
## How the Scheduler Works
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[jarvis scheduler start] --> B[Scheduler Daemon]
|
|
B --> C{Cron trigger fires}
|
|
C -->|0 9 * * *| D[daily_digest.py]
|
|
C -->|0 8 * * 1| E[code_review.py]
|
|
C -->|0 6 * * 1,3,5| F[gym_scheduler.py]
|
|
D --> G[OrchestratorAgent]
|
|
E --> H[NativeReActAgent]
|
|
F --> G
|
|
G --> I[web_search + think]
|
|
H --> J[git_diff + git_log + file_read + think]
|
|
I --> K[Output / Channel]
|
|
J --> K
|
|
```
|
|
|
|
The scheduler daemon reads registered tasks from SQLite, fires them at the correct time, and passes the configured prompt to the agent. Each script can also be run directly — the scheduler is only needed for recurring, unattended operation.
|
|
|
|
## Set Up Schedules with the CLI
|
|
|
|
Register each script as a recurring task using `jarvis scheduler create`:
|
|
|
|
```bash title="Terminal"
|
|
# Morning digest every day at 9 AM
|
|
jarvis scheduler create "Run daily news digest" \
|
|
--type cron --value "0 9 * * *"
|
|
|
|
# Weekly code review every Monday at 8 AM
|
|
jarvis scheduler create "Run weekly code review" \
|
|
--type cron --value "0 8 * * 1"
|
|
|
|
# Gym check on Monday, Wednesday, Friday at 6 AM
|
|
jarvis scheduler create "Check gym schedule" \
|
|
--type cron --value "0 6 * * 1,3,5"
|
|
```
|
|
|
|
Then start the scheduler daemon in the foreground (or as a background service):
|
|
|
|
```bash title="Terminal"
|
|
jarvis scheduler start
|
|
```
|
|
|
|
List registered tasks at any time:
|
|
|
|
```bash title="Terminal"
|
|
jarvis scheduler list
|
|
```
|
|
|
|
!!! note "Cron expression syntax"
|
|
OpenJarvis uses standard five-field cron syntax: `minute hour day-of-month month day-of-week`. Install `croniter` (`uv add croniter`) for full expression support including ranges and step values. Without it, basic `hour:minute` patterns still work.
|
|
|
|
## Configure Schedules with TOML
|
|
|
|
The `schedules.toml` file in `examples/scheduled_ops/` defines all three schedules declaratively. This is convenient for version-controlling your personal ops configuration or sharing it across machines:
|
|
|
|
```toml title="examples/scheduled_ops/schedules.toml"
|
|
[schedules.daily_digest]
|
|
type = "cron"
|
|
value = "0 9 * * *"
|
|
description = "Morning news and social media digest"
|
|
script = "daily_digest.py"
|
|
|
|
[schedules.code_review]
|
|
type = "cron"
|
|
value = "0 8 * * 1"
|
|
description = "Weekly code review"
|
|
script = "code_review.py"
|
|
|
|
[schedules.gym_scheduler]
|
|
type = "cron"
|
|
value = "0 6 * * 1,3,5"
|
|
description = "Gym hours and class check"
|
|
script = "gym_scheduler.py"
|
|
```
|
|
|
|
Point your own tooling or a custom loader at this file to register tasks in bulk.
|
|
|
|
## Register Tasks via the Python API
|
|
|
|
The `gym_scheduler.py` script includes a `--register` flag that demonstrates programmatic task registration using `TaskScheduler` directly:
|
|
|
|
```bash title="Terminal"
|
|
uv run python examples/scheduled_ops/gym_scheduler.py \
|
|
--register --gym "Planet Fitness"
|
|
```
|
|
|
|
The equivalent Python code:
|
|
|
|
```python title="Programmatic task registration"
|
|
from openjarvis.scheduler import TaskScheduler
|
|
from openjarvis.scheduler.store import SchedulerStore
|
|
|
|
store = SchedulerStore()
|
|
scheduler = TaskScheduler(store)
|
|
|
|
task = scheduler.create_task( # (1)!
|
|
prompt="Check gym schedule for 'Planet Fitness'",
|
|
schedule_type="cron",
|
|
schedule_value="0 6 * * 1,3,5",
|
|
agent="orchestrator",
|
|
tools="web_search,think",
|
|
)
|
|
print(f"Task registered: {task.id}")
|
|
print(f"Next run: {task.next_run}")
|
|
```
|
|
|
|
1. `create_task()` persists the task to SQLite and computes the next trigger time. The scheduler daemon picks it up without a restart.
|
|
|
|
## The Daily Digest Script
|
|
|
|
The digest script is the simplest of the three. It builds a date-stamped prompt and passes it to an orchestrator with `web_search` and `think`:
|
|
|
|
```python title="examples/scheduled_ops/daily_digest.py" hl_lines="5 6 7 8"
|
|
from openjarvis import Jarvis
|
|
|
|
j = Jarvis() # uses defaults from ~/.openjarvis/config.toml
|
|
response = j.ask(
|
|
f"Today is {today}. Search and summarize the top news on: {topics}",
|
|
agent="orchestrator",
|
|
tools=["web_search", "think"],
|
|
)
|
|
j.close()
|
|
```
|
|
|
|
The orchestrator searches for each topic in a separate turn, uses `think` to synthesize across topics, and returns a structured digest with bullet-point summaries and a one-paragraph outlook.
|
|
|
|
## Send Results to a Channel
|
|
|
|
To route script output to Slack or any other supported channel, pipe stdout through `jarvis channel send`:
|
|
|
|
```bash title="Terminal"
|
|
uv run python examples/scheduled_ops/daily_digest.py \
|
|
--topics "AI,finance" | jarvis channel send slack
|
|
```
|
|
|
|
Or add channel output inside the script:
|
|
|
|
```python title="In-script channel output"
|
|
from openjarvis.channels import ChannelRegistry
|
|
|
|
channel = ChannelRegistry.create("slack", webhook_url="https://hooks.slack.com/...")
|
|
channel.send(response)
|
|
```
|
|
|
|
List all available channels:
|
|
|
|
```bash title="Terminal"
|
|
jarvis channel list
|
|
```
|
|
|
|
!!! warning "Channel credentials"
|
|
Live channel output requires channel-specific credentials. Run `jarvis add slack` (or the relevant provider) to set up the MCP server and credential store, then configure environment variables in your `.env` file before starting the scheduler daemon.
|
|
|
|
## Customization Tips
|
|
|
|
- **Change topics**: Pass `--topics "finance,healthcare,sports"` to `daily_digest.py` for a different digest.
|
|
- **Review window**: Pass `--days 14` to `code_review.py` for a two-week review cycle instead of one week.
|
|
- **Swap agents**: Replace `orchestrator` with `native_react` in any script to compare agent behavior on the same task.
|
|
- **Add file output**: Append `"file_write"` to the `tools` list and update the prompt to save reports to disk instead of printing them.
|
|
- **One-time tasks**: Use `--type once --value "2026-04-01T09:00:00"` with `jarvis scheduler create` for non-recurring tasks.
|
|
|
|
## See Also
|
|
|
|
- [Architecture: Agents](../architecture/agents.md) — `OrchestratorAgent` and `NativeReActAgent` internals
|
|
- [Architecture: Tools and Memory](../architecture/memory.md) — tool registry and `ToolExecutor`
|
|
- [Getting Started: Configuration](../getting-started/configuration.md) — engine and model defaults
|