Skip to content

Event Tracker: Proactive "I Remember" Moments

Overview

The EventTracker service enables Sage and Echo to proactively ask about events that users mentioned in the past. This creates the experience of a friend who genuinely cares and remembers your life.

Example Flow: 1. User says: "I have a job interview tomorrow at Google" 2. EventTracker extracts and stores the event with date 3. Next day, user says: "Hey, how's it going?" 4. Sage responds: "Hey! How did the Google interview go??"

This transforms Sage from an "assistant with memory" into a "friend who cares."

Architecture

User Message
┌─────────────────────────────────────────────────────────┐
│                  Message Handler                         │
│                                                          │
│  ┌─────────────────┐     ┌─────────────────────────┐   │
│  │ Response Flow   │     │ Background Task         │   │
│  │                 │     │                         │   │
│  │ 1. Classify     │     │ detect_and_store_event()│   │
│  │ 2. Load Context │     │   - Heuristic check     │   │
│  │    └─ get_recent│     │   - GPT-5-nano extract  │   │
│  │       _past_    │     │   - Store in Supermemory│   │
│  │       events()  │     │                         │   │
│  │ 3. Generate     │     └─────────────────────────┘   │
│  │ 4. Deliver      │              ▲                    │
│  │ 5. Delete asked │              │                    │
│  │    events       │     Runs async after response     │
│  └─────────────────┘                                    │
└─────────────────────────────────────────────────────────┘

Key Components

1. Event Detection (detect_and_store_event)

Runs as a background task after every message (zero latency impact).

Two-stage detection: 1. Fast Heuristic Filter - Checks for temporal keywords to skip LLM calls 2. LLM Extraction - Uses GPT-5-nano to extract structured event data

Temporal Keywords:

[
    "tomorrow", "today", "tonight", "this evening", "later today",
    "next week", "next month", "next year", "this weekend",
    "in a few days", "in a week", "in a month", "in a couple",
    "upcoming", "this coming",
    "on monday", "on tuesday", ... "on sunday",
    "january", "february", ... "december",
    "on the", "at the end of",
]

Extraction Output:

{
    "is_event": true,
    "description": "Job interview with Google",
    "event_date": "2026-01-10",
    "importance": 9
}

2. Event Storage

Events are stored in Supermemory with special metadata:

memory_text = "User has Job interview with Google on 2026-01-10"
metadata = {
    "type": "future_event",
    "event_date": "2026-01-10",
    "event_description": "Job interview with Google",
    "importance": 9,
    "status": "pending"
}

Namespace Isolation: - Direct chats: Stored in user's personal namespace - Group chats: Stored in group namespace (Echo can ask about group plans)

3. Event Retrieval (get_recent_past_events)

Called during context loading, before response generation.

Configuration: - Lookback Window: 3 days (today, yesterday, 2 days ago, 3 days ago) - Limit: 20 events max (filtered in Python)

Date Logic:

today_start = midnight today
cutoff = today_start - 3 days
tomorrow_start = midnight tomorrow

# Included if: cutoff <= event_date < tomorrow_start
# This means: events from past 3 days INCLUDING today

4. Context Injection

Recent events are injected as high-priority memories:

memories.append({
    "memory": "RECENT EVENT (2026-01-10): User had 'Job interview with Google'. You should proactively ask how it went!",
    "score": 2.0  # High priority - ensures LLM sees it
})

5. Event Deletion (Ask Only Once)

After surfacing an event, it's deleted to prevent repeat questions:

# After injecting into context
asyncio.create_task(
    event_tracker.mark_event_as_asked(memory_id)
)

This ensures natural conversation flow - Sage won't ask "how was your interview?" multiple days in a row.

Configuration

Setting Value Location
Extraction Model gpt-5-nano event_tracker.py:30
Lookback Days 3 event_tracker.py:144
Memory Limit 20 event_tracker.py:173
Context Score 2.0 message_handler.py:1603

Supported Scenarios

Direct Messages (Sage)

  • User mentions personal events
  • Sage asks about them when they become "recent past"
  • Events deleted after asking

Group Chats (Echo)

  • Group members mention group plans ("let's meet Saturday!")
  • Echo asks about them in the group context
  • Separate namespace from personal events

Error Handling

  • Heuristic bypass: Messages without temporal keywords AND < 20 chars skip LLM
  • LLM failures: Logged and ignored (graceful degradation)
  • Date parsing errors: Events with invalid dates skipped
  • Deletion failures: Logged but don't block conversation

Files

File Purpose
app/memory/event_tracker.py Core EventTracker service
app/orchestrator/message_handler.py Integration points

Testing

# Verify imports
python -c "from app.memory.event_tracker import EventTracker; print('OK')"

# Test date boundary logic
python3 << 'EOF'
from datetime import datetime, timedelta

now = datetime.now()
today_start = datetime(now.year, now.month, now.day)
cutoff = today_start - timedelta(days=3)
tomorrow_start = today_start + timedelta(days=1)

test_date = today_start  # Today
in_range = cutoff <= test_date < tomorrow_start
print(f"Today included: {in_range}")  # Should be True
EOF

Limitations

  1. No timezone handling - Dates stored as YYYY-MM-DD without timezone
  2. No event deduplication - Same event mentioned twice creates two memories
  3. 20 event limit - Power users with many events may miss older ones
  4. No multi-day events - Events treated as single-day occurrences

Future Improvements

  • Timezone-aware date handling
  • Event deduplication before storage
  • Multi-day event support
  • Configurable lookback per user
  • Event importance-based prioritization

Last Updated: January 2026 Status: Production-ready, deployed to dev/prod