Routines
A scheduler for your agent. Cron, daily, weekly, interval, or one-shot — running the same agent loop as chat, on a clock.
What it is
A routine is a saved prompt plus a schedule. When the schedule fires, Froots spawns a new session, hands the prompt to your active backend (Claude, Codex, or Pi), and lets the agent run with the same tools, memory, and skills it would have in chat.
The scheduler is a Tokio task on the Rust side that polls every 30 seconds. Routines persist as ScheduledTask rows in the local database, so a quit-and-relaunch picks up exactly where it left off.
Schedule types
Five trigger shapes cover essentially every cadence:
| Type | Payload | Example |
|---|---|---|
Once | A single timestamp | Run at 3pm tomorrow |
Interval | Minutes between runs | Every 30 minutes |
Daily | HH:MM | Every day at 08:00 |
Weekly | Day + optional time | Mondays at 09:00 |
Cron | Full POSIX cron expression | 0 9 * * 1-5 |
Next-run timestamps are computed deterministically, so you can see exactly when a routine will fire next without waiting for it.
Cron type accepts full POSIX cron expressions via the cron crate. Everything else is sugar on top of the same scheduler.What ships in the box
Froots ships fifty preset templates in a Library tab — morning briefing, weekly standup, inbox triage, market pulse, planning prompts, and more. Presets are not auto-installed: you pick one, edit the prompt, set a schedule, and save. The database starts empty on first launch.
This is intentional. We’ve found that defaults nobody asked for get ignored, but presets you actively choose stick around.
Example routines people set up
These are real shapes from the preset library, lightly edited to show what an actual routine looks like.
memory/today.md.”_workspace/, group them into wins / unsolved / next-week, and append a section to workspace/retros/{date}.md.”_0 9-16/4 * * 1-5. _“Check the tickers in memory/watchlist.md, summarize anything that moved more than 3%, and only notify me if something crossed a level I’ve flagged.”_Interval. _“Read new messages in my inbox, draft replies for anything that’s clearly mine, and queue them for review. Don’t send.”_memory/decisions.md, and the notes I starred this week. Draft a one-page plan into workspace/plans/next-week.md.”_Each one is just a prompt plus a schedule. They use whatever skills are enabled on the assistant — github for the retro, browser-automation for market pulse, your mail skill for triage — and they read and write the same memory files you do.
Heartbeat
Each assistant has an optional heartbeat — a recurring background session that runs on its own cadence (configurable between 15 minutes and 2 hours). It’s off by default; you turn it on per-assistant.
When the heartbeat fires, it runs a meta-prompt asking the agent to (a) review and maintain memory/context.md, and (b) decide whether anything in the world right now is worth surfacing unprompted. If yes, the agent calls notify_user(title, body) and Froots fires a desktop notification. If no, the session exits silently — but the agent’s reasoning is saved as last_response so you can see what it considered.
Execution path
When a routine fires, it routes to whichever backend is active for that assistant. Claude and Codex both run as one-shot subprocesses (with transcript loading for multi-turn). Pi runs as a long-lived process with persistent memory. The same agent tools — agent_read_doc, agent_write_doc, agent_edit_doc, browser automation when enabled — are available.
Routines aren’t a separate runtime. They’re chat sessions on a timer.
What it isn’t (yet)
There’s no built-in “routine chaining” (where one routine triggers another) and no multi-step workflow runtime — the steps and edges fields exist on the schema but the agent-side runtime for branching workflows is still in progress. For now, routines are single prompts; complex flows live inside the prompt itself.