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:
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¶
- No timezone handling - Dates stored as YYYY-MM-DD without timezone
- No event deduplication - Same event mentioned twice creates two memories
- 20 event limit - Power users with many events may miss older ones
- 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