Continuity Mode
Written by ddxfish on .
- Docs
- Continuity Mode
- All docs ↓
Your AI doesn't have to wait for you to talk first. Continuity lets Sapphire wake up on a schedule and do things on its own—greet you in the morning, check the weather, run a dream sequence while you sleep, or remind you about something important.
What's It For?
- Morning greeting — "Good morning! Here's what's happening today..."
- Dream mode — Let the AI ramble to itself at 3 AM with a creative prompt
- Home automation — "Turn on the lights at sunset" (with Home Assistant tools)
- Alarm clock — Wake up to a personalized message instead of a beep
- Random hellos — 20% chance every hour to say something unexpected
- Scheduled research — Check news on a topic every morning
- Journaling prompts — Daily nudge to write
How It Works
- Create a task with a schedule (cron format)
- When the time hits, Sapphire sends your "initial message" to the AI
- AI responds using whatever prompt, tools, and voice you configured
- Optionally speaks the response out loud via TTS
The Chat Name field decides where that happens. Name a chat and the task runs inside it with saved history—she remembers previous runs, and you can read the conversation later. The UI never switches chats on its own. Leave it blank and the task runs in an invisible, ephemeral background context that leaves no chat behind.
Time-based tasks are half the picture: Sapphire can also react to outside events—Discord messages, email, live phone calls, HTTP requests. Those lanes (daemons, realtime rules, webhooks) share the same task machinery and are covered in Daemons & Webhooks.
Task Fields
Schedule and firing
| Field | What it does |
|---|---|
| Name | Label for the task. Shows in the list and activity log. |
| Schedule | When to run (cron format—see below). Heartbeats use a simple interval ("beats every 30 minutes") instead. |
| Active hours | Only fire inside an hour window—cron matches outside it are skipped. Overnight windows work (e.g. 8 PM–4 AM). |
| Chance % | Probability the task actually fires. 100 = always, 50 = coin flip. Good for random variety. |
| Max runs | Auto-disable after this many runs. 1 = one-shot task, 0 = unlimited. The editor shows progress toward the cap. |
| Delete after run | Remove the task itself once it finishes its runs—for one-shots that should leave no trace. |
AI and chat
| Field | What it does |
|---|---|
| Persona | Auto-fills prompt, voice, toolset, model, scopes, and more from a persona profile. You can still override individual settings. |
| Prompt | Which prompt preset to use. |
| Toolset | Which tools the AI can access. "none" disables tools entirely. |
| LLM Provider | Which AI backend. "Auto" uses your default. |
| Model | Specific model override (optional). |
| Private | Force this task onto local providers only. Auto-checked when the pinned prompt requires privacy. |
| Chat Name | Blank = invisible background run, no chat saved. Filled = run in that chat and keep history. |
| Initial Message | What gets sent to the AI when the task triggers. "Good morning!" or "Continue the story." |
| Inject datetime | Add current date/time to the system prompt so the AI knows when it is. |
Voice
| Field | What it does |
|---|---|
| Speak on server speakers | Play the response through TTS on the machine Sapphire runs on. |
| Play in browser | Send the TTS audio to open browser tabs instead—one tab claims and plays it. |
| Voice / Pitch / Speed | Override the TTS voice for this task. Pitch and speed range 0.5–2.0; blank = current defaults. |
Mind and limits
| Field | What it does |
|---|---|
| Mind scopes | Per-task memory, knowledge, people, and goals scopes (plus any plugin scopes). Default "none"—isolated unless you say otherwise. |
| Context window | Token limit for conversation history. 0 = app default. |
| Max parallel tools / Max tool rounds | Per-task tool execution limits. 0 = app default. |
If a task targets a private chat and the vault is locked, the Chat Name shows 🔒 locked vault instead of the name — saving the task keeps the real target, or type a name to retarget. A task that fires at a sealed chat fails loudly rather than creating a plaintext chat with the same name. See PRIVACY.md.
Cron Basics
Cron format: minute hour day month weekday
| Pattern | When it runs |
|---|---|
0 9 * * * |
9:00 AM every day |
30 7 * * 1-5 |
7:30 AM weekdays only |
0 */2 * * * |
Every 2 hours |
0 0 * * * |
Midnight |
*/15 * * * * |
Every 15 minutes |
0 22 * * 0 |
10 PM on Sundays |
Use * for "any value". Use */N for "every N". Use 1-5 for ranges (1=Monday, 0 or 7=Sunday).
The UI
Triggers in the sidebar is a group of five views:
| View | What lives there |
|---|---|
| 💓 Heartbeat | Recurring self-pulses on a simple interval ("beats every 30 minutes"). Vitals cards plus a heartbeat timeline. |
| 📅 Scheduled | Tasks at set times—one-off or recurring. Two columns: what you scheduled, and what Sapphire scheduled herself (via her schedule_task tool) or her plugins declared. |
| 📡 Daemons | Event listeners (Discord, email, Telegram) that wake her when something happens. |
| ⚡ Realtime | Live inbound session rules—phone lines she answers and holds open. |
| 🔗 Webhooks | HTTP triggers so outside services can poke her. |
Heartbeat and Scheduled are the time-driven views this doc covers. Each item can be toggled, edited, exported, run manually (▶), stopped mid-run (⏹ appears on a running card; toggling off stops it too), or deleted, and a timeline strip shows what ran and what's coming up, with chance percentages. Daemons, Realtime, and Webhooks fire on incoming events rather than the clock—see Daemons & Webhooks.
Tips
- Start with infrequent schedules while testing to avoid spam
- Use the ▶ Run now button to test without waiting for the schedule
- ⏹ stops a run that's already going. It lands at the next safe point — between the model's rounds — so a task waiting on a slow LLM call finishes that one call before it stops. Anything queued behind the run is dropped, and the task stays enabled for its next schedule.
- Background tasks (blank Chat Name) are great for things you don't need to see
- Combine with Home Assistant tools for smart home automation
- Low chance % + frequent schedule = occasional surprises
- Max runs 1 + Delete after run = a clean fire-and-forget reminder
Reference for AI
Continuity runs scheduled autonomous tasks. UI: Triggers nav group with five views — Heartbeat, Scheduled, Daemons, Realtime, Webhooks.
TASK CREATION (UI):
- Triggers > Scheduled > "+ Task" (heartbeats: Triggers > Heartbeat > "+ Heartbeat")
- Set schedule (cron or simple time picker), initial message, prompt, toolset; picking a Persona auto-fills prompt/voice/toolset/model/scopes
- Accordions: AI, Chat, Voice, Mind (scopes), Execution Limits
SELF-SCHEDULING (tool):
- schedule_task(description, time) — time like '5pm'/'17:00' = one-shot that auto-deletes after firing; a 5-field cron string = recurring. AI-scheduled tasks are capped and appear in the Scheduled view's "Sapphire scheduled" column.
KEY FIELDS:
- type: task | heartbeat | daemon | webhook. Realtime rules are daemon tasks whose event source is realtime — they gate live sessions instead of firing; see DAEMONS-WEBHOOKS.md
- schedule: cron (minute hour day month weekday) — time-based types
- chance: 1-100 probability to actually run
- active_hours_start/end: hour integers; cron matches outside the window are skipped; overnight wrap supported (e.g. 20→4)
- chat_target: blank = ephemeral background, named = persistent chat history (never switches the UI); 'locked' = display mask for a private chat sealed in the locked vault (saving keeps the real target)
- persona: persona name; resolved at run time to fill prompt/voice/toolset/model/scopes
- initial_message: what the AI receives when the task fires
- inject_datetime: true = date+time stamp in the system prompt; the string 'date' = day-only stamp (prompt-cache-friendly for multi-run sessions)
- tts_enabled: server speakers; browser_tts: route audio to an open browser tab instead
- voice / pitch / speed: TTS overrides; pitch/speed 0.5-2.0, null = current default
- privacy_required: local providers only; auto-set when the pinned prompt requires privacy
- context_limit / max_parallel_tools / max_tool_rounds: per-task execution limits, 0 = app default
- max_runs: auto-disable after N runs (0 = unlimited); delete_after_run: delete the task once its runs finish
- *_scope keys (memory_scope, knowledge_scope, ...): per-task mind scopes, default 'none'
MANUAL TRIGGER:
- ▶ Run now on any task in the Heartbeat/Scheduled views
CANCEL A RUN:
- ⏹ on a running card → POST /api/continuity/tasks/{id}/cancel; toggling the task off cancels implicitly, as does deleting it
- Lands at the next cancel point (each round, and between an LLM reply and its tool batch) — a blocking LLM call in flight completes its round first; queued fires behind the run are dropped; the task stays enabled
- Activity log:
cancel_requested→cancelled
TROUBLESHOOTING:
- Task not running: check enabled toggle, cron syntax, active-hours window
- Skipped (chance): random roll failed, will try next scheduled time
- Task went quiet after N runs: max_runs reached — it auto-disabled (editor shows runs done)
Edit this page on GitHub · docs/CONTINUITY.md @ c2e3170 · synced
