PRD — Proactive Intelligence System¶
Doc owner: Justin Audience: Eng, Design, Product Status: v1 (February 2026) Depends on: prd.md (core platform), PRD 1 (Composable MiniApp System), PRD 3 (Progression & Loadout)
Implementation Status¶
| Section | Status | Notes |
|---|---|---|
| Proactive scheduler infrastructure | ✅ Shipped | app/scheduler/background_service.py |
| Morning Calendar Prep workflow | ✅ Shipped | Built but disabled (ENABLE_PROACTIVE_SCHEDULER=false) |
| Email Urgency Alerts workflow | ✅ Shipped | Built but disabled |
| Calendar Event Reminders | ✅ Shipped | Built but disabled |
| Evening Prep workflow | ✅ Shipped | Built but disabled |
| Travel Support workflow | ✅ Shipped | Built but disabled |
| Cancellation Protector | ✅ Shipped | Built but disabled |
| Edge agent delivery integration | ✅ Shipped | schedule_message via /edge/sync |
| Anti-annoyance decision engine | 🟡 Partial | Basic limits exist, full decision engine not implemented |
| Proactive preferences API | ❌ Not Shipped | No user-facing preference management |
| Voice controls ("stop briefings") | ❌ Not Shipped | No natural language preference changes |
| Streak Saver workflow | ❌ Not Shipped | No streak tracking (depends on PRD 3) |
| Weekly Recap workflow | ❌ Not Shipped | Not built |
| Urgency scoring with learning | ❌ Not Shipped | Static thresholds only |
| Gold-tier proactive unlocks | ❌ Not Shipped | Depends on PRD 3 tier system |
Note: 6 of 6 shipped workflows are disabled by default via ENABLE_PROACTIVE_SCHEDULER=false for cost control. The PRD states "6 workflows built" — implementation shows 29 total workflows (including 16 proactive), many more than documented.
References¶
This PRD uses standardized terminology, IDs, pricing, and model references defined in the companion documents:
| Document | What it Covers |
|---|---|
| REFERENCE_GLOSSARY_AND_IDS.md | Canonical terms: workflow vs miniapp vs superpower, ID formats |
| REFERENCE_PRICING.md | Canonical pricing: $7.99/mo + $50/yr, free tier limits |
| REFERENCE_MODEL_ROUTING.md | Pipeline stage → model tier mapping |
| REFERENCE_DEPENDENCY_GRAPH.md | PRD blocking relationships and priority order |
| REFERENCE_FEATURE_FLAGS.md | All feature flags by category |
| REFERENCE_TELEMETRY.md | Amplitude event catalog and gaps |
Executive Summary¶
Proactive Intelligence is what separates Sage from every other AI assistant. Instead of waiting for the user to ask, Sage initiates — a morning briefing before the user checks their calendar, an email urgency alert when something important arrives, a gentle check-in when a streak is about to break. This is the feature that makes users say "it's like she actually cares about my life."
Current state: 6 proactive workflows built and tested (morning calendar prep, email urgency alerts every 15min, event reminders, evening prep, travel support, cancellation monitoring). All disabled by default for cost control. Backend supports scheduling. Edge agent handles local delivery.
Core challenge: The line between "helpful" and "annoying" is razor-thin. One too many unsolicited messages and the user mutes or removes Sage. This PRD defines the intelligence layer that decides when to be proactive, what to say, and when to shut up.
1) Proactive Workflow Catalog¶
1.1 Shipped (Disabled by Default)¶
| Workflow | Schedule | Trigger | What It Does |
|---|---|---|---|
| Morning Calendar Prep | 7:00am daily | Cron | Checks day's schedule, weather, commute. Sends briefing. |
| Email Urgency Alerts | Every 15min (8am-8pm) | Cron | Scans new emails for deadlines/urgency. Alerts only if high-priority. |
| Calendar Event Reminders | 30min before events | Event-driven | Reminds with context and prep tips. |
| Evening Prep | 8:00pm daily | Cron | Checks tomorrow's schedule, suggests wind-down. |
| Travel Support | Travel day | Event-driven | Detects travel from calendar, provides itinerary/weather. |
| Cancellation Protector | Continuous | Event-driven | Monitors flight status, hotel reservations (planned). |
1.2 Planned¶
| Workflow | Trigger | What It Does |
|---|---|---|
| Streak Saver | 9pm if no messages today | Gentle check-in to preserve streak |
| Weekly Recap | Sunday 7pm | Week summary: wins, challenges, upcoming |
| Birthday/Event Reminder | Day before | Reminds about friend birthdays from memory |
| Deadline Countdown | 48h before deadline | Proactive reminder with prep suggestions |
| Mood Pattern Alert | After 3+ negative mood entries | Gentle "I've noticed a pattern" with resource suggestion |
| Superpower Insight | After 10 uses of a superpower | Tier-up teaser or usage insight |
2) The Intelligence Layer¶
2.1 When to Be Proactive (Decision Engine)¶
Not every scheduled trigger should result in a message. The decision engine evaluates:
async def should_send_proactive(user_id: str, workflow_id: str, content: dict) -> bool:
user_prefs = await get_proactive_preferences(user_id)
# Hard gates
if not user_prefs.proactive_enabled:
return False
if is_quiet_hours(user_prefs.quiet_start, user_prefs.quiet_end):
return False
if workflow_id in user_prefs.disabled_workflows:
return False
# Soft gates (anti-annoyance)
recent = await get_recent_proactive_messages(user_id, hours=24)
if len(recent) >= user_prefs.max_daily_proactive: # default: 3
return False
last_message = await get_last_proactive(user_id)
if last_message and (now() - last_message.sent_at).total_seconds() < 3600: # 1h minimum gap
return False
# Value gate (don't send if nothing interesting)
if content.get("urgency", 0) < 0.5 and workflow_id != "streak_saver":
return False # Nothing urgent enough to bother the user
return True
2.2 Anti-Annoyance Rules¶
| Rule | Default | Configurable |
|---|---|---|
| Max proactive messages per day | 3 | Yes (1-10) |
| Minimum gap between proactive messages | 1 hour | Yes (30min-4h) |
| Quiet hours | 11pm-7am | Yes (user sets) |
| Per-workflow opt-out | All enabled if proactive is on | Yes |
| Urgency threshold for non-scheduled | 0.5 (medium) | No |
| Cooldown after user ignores 2 proactive messages | +24h silence | No |
2.3 Urgency Scoring¶
Each proactive workflow produces an urgency score (0-1) that gates delivery:
def score_urgency(workflow_output: dict) -> float:
signals = {
"has_deadline_today": 0.9,
"has_deadline_this_week": 0.5,
"has_urgent_email": 0.8,
"calendar_conflict_detected": 0.7,
"streak_about_to_break": 0.4,
"nothing_special": 0.1,
"travel_day": 0.6,
"meeting_in_30min": 0.9,
}
return max(signals.get(s, 0) for s in workflow_output.get("signals", ["nothing_special"]))
Messages below the threshold are silently dropped — the user never knows a workflow fired and found nothing interesting.
3) User Preferences & Controls¶
3.1 Opt-In Model¶
Proactive is off by default. Users opt in via: - Sage suggests: "want me to check your calendar every morning and give you a heads up?" - Settings page: toggle proactive on/off + per-workflow toggles - Level unlock: at Level 3, Sage mentions proactive as a new capability
3.2 Preference Schema¶
{
"user_id": "user_123",
"proactive_enabled": false,
"quiet_hours": {"start": "23:00", "end": "07:00"},
"timezone": "America/Los_Angeles",
"max_daily_proactive": 3,
"min_gap_minutes": 60,
"workflows": {
"morning_calendar": {"enabled": true, "time": "07:00"},
"email_urgency": {"enabled": true, "interval_minutes": 15},
"event_reminders": {"enabled": true, "minutes_before": 30},
"evening_prep": {"enabled": false},
"streak_saver": {"enabled": true, "time": "21:00"}
}
}
3.3 Voice Controls¶
Users can adjust via chat: - "Sage, stop the morning briefings" → disables morning_calendar - "Sage, only bug me about really urgent stuff" → raises urgency threshold to 0.8 - "Sage, you can be more proactive" → raises max_daily to 5, lowers gap to 30min - "Sage, quiet mode" → disables all proactive for 24h
4) Delivery Architecture¶
4.1 Scheduling¶
[Backend Scheduler]
→ Evaluates cron triggers every minute
→ For each triggered workflow:
1. Run workflow (fetch calendar/email data)
2. Score urgency
3. Run should_send_proactive() decision engine
4. If approved: generate Sage-voice message via Persona Styler
5. Send schedule_message command to edge agent
[Edge Agent (Mac Mini)]
→ Receives schedule_message command via /edge/sync
→ Stores in local SQLite queue
→ Fires at scheduled time (even if backend is offline)
→ Sends via iMessage
→ Reports delivery confirmation to backend
4.2 Cost Model¶
| Workflow | LLM Calls | Frequency | Cost/User/Month |
|---|---|---|---|
| Morning Calendar | 1 (calendar fetch + compose) | 30/mo | ~$0.15 |
| Email Urgency | 1 per check (most produce no message) | ~300 checks/mo | ~$1.50 |
| Event Reminders | 0.5 (only if event exists) | ~20/mo | ~$0.10 |
| Evening Prep | 1 | 30/mo | ~$0.15 |
| Streak Saver | 0.5 (only if at risk) | ~10/mo | ~$0.05 |
Total proactive cost: ~\(2/user/month at full engagement. This is why proactive is disabled by default during beta — at 100 users, adds ~\)200/month.
4.3 Efficiency Optimizations¶
- Batch scheduling: Process all users' morning briefings in one batch, not individual cron jobs
- Short-circuit: If calendar/email fetch returns nothing interesting, skip LLM call entirely
- Cache: Calendar data cached for 15 minutes (reduces API calls for overlapping workflows)
- Edge delivery: Proactive messages queued on edge agent, reducing backend load to scheduling-only
5) Proactive Message Tone¶
Proactive messages must feel like a friend texting, not a notification system:
Good (Sage voice):
hey your Thursday is looking ROUGH — 5 meetings back to back
starting at 9. do you want me to find a gap for lunch or are
you just going to power through?
Bad (notification voice):
Rules: - Always in persona voice (Sage or Echo) - Never use corporate language ("alert," "notification," "reminder") - Include a question or actionable suggestion (not just information) - Keep under 3 message bubbles - Reference user's context naturally ("your Thursday" not "the user's calendar") - If nothing is notable, don't send anything — silence is better than filler
6) Progression Integration (PRD 3)¶
Superpower Tier-Ups Enable Proactive¶
| Superpower | Bronze (default) | Silver (10 uses) | Gold (30 uses) |
|---|---|---|---|
| Calendar Stress | Manual only | Scans 14 days + trends | Monday morning auto-briefing |
| Gmail Mind Reader | Manual only | Learns urgent senders | Proactive scanning (if enabled) |
| Habit Tracker | Manual only | Predicts skip days | Proactive encouragement |
| Mood Tracker | Manual only | Trend detection | "I've noticed a pattern" alerts |
Design principle: Proactive capabilities are earned through use, not purchased. This aligns with PRD 3's tier system — Gold-tier superpowers unlock proactive behaviors as a reward for engagement.
7) Data Model¶
-- Proactive preferences
CREATE TABLE proactive_preferences (
user_id UUID PRIMARY KEY REFERENCES users(id),
enabled BOOLEAN DEFAULT false,
quiet_start TIME DEFAULT '23:00',
quiet_end TIME DEFAULT '07:00',
timezone TEXT DEFAULT 'America/Los_Angeles',
max_daily INTEGER DEFAULT 3,
min_gap_minutes INTEGER DEFAULT 60,
workflow_overrides JSONB DEFAULT '{}',
urgency_threshold FLOAT DEFAULT 0.5,
updated_at TIMESTAMPTZ DEFAULT now()
);
-- Proactive message log (for anti-annoyance tracking)
CREATE TABLE proactive_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
workflow_id TEXT NOT NULL,
urgency_score FLOAT,
decision TEXT CHECK (decision IN ('sent', 'suppressed_quiet', 'suppressed_limit', 'suppressed_gap', 'suppressed_urgency', 'suppressed_ignored')),
message_text TEXT,
delivered_at TIMESTAMPTZ,
user_responded BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT now()
);
8) Success Metrics¶
| Metric | Target | Why |
|---|---|---|
| Proactive opt-in rate | >30% of active users | Feature is compelling enough to enable |
| Proactive message open/response rate | >40% | Messages are relevant, not noise |
| Ignore rate (2+ consecutive ignored) | <20% | Anti-annoyance is working |
| Proactive → conversation rate | >25% | Proactive sparks real engagement |
| User satisfaction (survey) | >⅘ "Sage's check-ins are helpful" | Core value metric |
| Cost per proactive user | <$3/month | Sustainable at scale |
9) Phasing¶
Phase 1: Foundation (Weeks 1-2)¶
- Proactive preferences table and API
- Decision engine (should_send_proactive)
- Anti-annoyance rules
- Morning Calendar Prep (first workflow enabled)
- Edge agent delivery integration
Phase 2: Core Workflows (Weeks 3-4)¶
- Email Urgency Alerts
- Event Reminders
- Streak Saver
- Voice controls ("stop the morning briefings")
Phase 3: Intelligence (Weeks 5-8)¶
- Urgency scoring with learning (track which messages get responses)
- Ignored-message cooldown
- Gold-tier proactive unlocks (PRD 3 integration)
- Weekly Recap
- Deadline Countdown
Feature Flags & Gating¶
| Flag Key | Default | Purpose |
|---|---|---|
ENABLE_PROACTIVE_SCHEDULER |
false |
Master switch for all proactive workflows (env var) |
enable_proactive_messages |
false |
Per-user proactive message delivery |
proactive_max_daily |
3 |
Maximum proactive messages per user per day |
proactive_min_gap_minutes |
60 |
Minimum gap between proactive messages |
proactive_urgency_threshold |
0.5 |
Minimum urgency score to deliver |
enable_morning_calendar |
false |
Morning Calendar Prep workflow |
enable_email_urgency |
false |
Email Urgency Alerts workflow |
enable_event_reminders |
false |
Calendar Event Reminders workflow |
enable_evening_prep |
false |
Evening Prep workflow |
enable_streak_saver |
false |
Streak Saver workflow |
enable_weekly_recap |
false |
Weekly Recap workflow |
See REFERENCE_FEATURE_FLAGS.md for the full catalog.
Telemetry¶
| Event | Trigger | Properties |
|---|---|---|
proactive_workflow_fired |
Workflow cron/event trigger fires | user_id, workflow_id, urgency_score |
proactive_sent |
Message delivered to user | user_id, workflow_id, urgency_score, delivery_method |
proactive_suppressed |
Decision engine blocks delivery | user_id, workflow_id, suppression_reason (quiet/limit/gap/urgency/ignored) |
proactive_responded |
User replies to proactive message | user_id, workflow_id, response_time_seconds |
proactive_ignored |
User doesn't respond within 24h | user_id, workflow_id, consecutive_ignores |
proactive_opted_in |
User enables proactive | user_id, source (sage_suggestion/settings/level_unlock) |
proactive_opted_out |
User disables proactive | user_id, workflows_disabled |
proactive_preference_changed |
User adjusts settings via voice or UI | user_id, preference_key, old_value, new_value |
Needed but not yet tracked:
- proactive_cost_per_user — monthly proactive LLM cost per user
- proactive_workflow_error — when a workflow fails (API timeout, data fetch error)
See REFERENCE_TELEMETRY.md for the full event catalog.
Definition of Done¶
- Proactive preferences API allows per-user, per-workflow opt-in/out
- Decision engine enforces all anti-annoyance rules (daily limit, gap, quiet hours, urgency threshold)
- Voice controls change preferences via natural language ("stop morning briefings")
- Edge agent delivers scheduled messages even when backend is offline
- Urgency scoring gates all non-critical workflows (nothing sent below threshold)
- Ignored-message cooldown extends silence after 2+ consecutive ignores
- Proactive cost per user tracked and stays under $3/month at full engagement
- All workflows individually gated by feature flags
- Telemetry tracks every fire/send/suppress/respond cycle
- Proactive opt-in rate: >30% of active users (feature is compelling)
- Proactive response rate: >40% (messages are relevant, not noise)
10) Open Questions¶
- Should proactive messages count toward the user's daily message limit (credits)?
- How do we A/B test proactive timing? (7am vs 7:30am vs 8am for morning briefing)
- Should proactive messages be different for users at different relationship stages?
- If a user ignores all proactive messages for 7 days, should we auto-disable?
- Should proactive work in group chats? ("hey your dinner is in 2 hours" sent to group)
- How do we handle timezone changes? (User travels → morning briefing fires at wrong time)