Proactive AI Agent with Semantic Memory
Table of content
Most AI assistants wait for you to ask. A proactive agent notices things and reaches out when it matters.
Why Proactivity
Reactive AI: you ask → it answers.
Proactive AI: it observes → decides to speak → says something useful.
The difference:
- “What’s my screen time?” vs “3h Telegram today — normal or doom-scrolling?”
- “Check my stress” vs “Stress spiked after that meeting — noticed a pattern”
- “Remind me about X” vs “Week without cycling — miss it?”
Proactivity requires:
- Heartbeat system — agent wakes up periodically
- Semantic memory — agent recalls context by meaning, not keywords
- Good judgment — knowing when to speak vs stay silent
Heartbeat System
A cron job wakes the agent every N minutes. The agent decides whether to message.
The Mechanism
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ cron/timer │───▶│ agent runs │───▶│ speak or │
│ every 30min │ │ checks data │ │ stay silent │
└─────────────┘ └─────────────┘ └─────────────┘
HEARTBEAT.md Prompt
Create a file that defines heartbeat behavior:
# Heartbeat Rules
## Check and speak ONLY if:
- Data shows anomaly (stress spike, unusual screen time)
- Pending reminder is due
- Context is right for a deferred question
- Pattern worth noting (3rd day without exercise)
## NEVER do:
- Message every 30 minutes
- Repeat what we just discussed
- Write at night without real reason
- State obvious things ("It's Tuesday")
## Format
- 1-3 sentences max
- Questions beat statements
- Be specific, not vague
## Examples of good messages:
- "BB dropped to 25 after the call — stress pattern?"
- "4h in Cursor today, 0 commits — stuck on something?"
- "Haven't mentioned Project X in a week — dropped or just quiet?"
## Examples of bad messages:
- "Just checking in!" (empty)
- "How are you?" (generic)
- "You've been working" (obvious)
Cron Setup
# Every 30 minutes, 8am-10pm
*/30 8-22 * * * /path/to/agent heartbeat >> /var/log/agent.log 2>&1
The agent reads HEARTBEAT.md, checks available data sources (screen time, health metrics, calendar), and decides.
Semantic Memory
Keyword search fails on meaning. “What did I decide about the React project?” won’t find “chose Vue over React because of team experience.”
Semantic search finds by meaning, not exact words.
Memory Recall Prompt
Add to your agent instructions:
## Memory Recall
Before answering about past decisions, preferences, dates, or prior work:
1. Run semantic search on memory files
2. Pull specific entries that match
3. If search returns nothing, say "checked memory, didn't find"
### When to search:
- "What did we decide about..."
- "When did I..."
- "My preference for..."
- "That thing we discussed..."
- Any reference to past conversations
### Search strategy:
- Start broad: "project decisions"
- Narrow if needed: "React Vue decision January"
- Check multiple memory files if topic spans time
Implementation
Using embeddings (vector search):
## Memory Search Tool
memory_search(query, top_k=5)
- Embeds query
- Finds closest matches by cosine similarity
- Returns matching entries with dates
Example:
memory_search("frontend framework decision")
→ "2025-01-15: Chose React over Vue (team familiarity)"
Simple version without embeddings:
## Memory Search (Simple)
Search memory/*.md files for:
1. Exact phrases
2. Key terms from query
3. Date ranges if mentioned
Return matches with surrounding context (±2 lines)
Memory Structure
Directory Layout
memory/
├── MEMORY.md # Quick facts, current state
├── decisions/
│ └── 2025-01.md # Monthly decision log
├── patterns/
│ └── health.md # Observed patterns
├── projects/
│ └── project-x.md # Project-specific memory
└── daily/
└── 2025-01-27.md # Daily observations
MEMORY.md Format
Fast-access facts:
## Me
- Timezone: UTC-3
- Work hours: 10-19
- Prefer async communication
## Current Focus
- Project X: API redesign (deadline Feb 15)
- Learning: Rust basics
## Preferences
- Code style: explicit over clever
- Meetings: mornings only
- Notifications: batch, not stream
Decision Log Format
# Decisions — January 2025
## 2025-01-27
- **Chose Postgres over SQLite** for Project X
- Reason: need concurrent writes
- Revisit if: scale stays under 100 users
## 2025-01-15
- **React over Vue** for dashboard
- Reason: team knows React
- Trade-off: Vue's simpler reactivity
Pattern Log Format
# Health Patterns
## Stress
- Spikes after long meetings (>1h)
- Lower on days with morning exercise
- Correlates with screen time >6h
## Energy
- Peak: 10am-1pm
- Dip: 3-4pm (don't schedule calls)
- Second wind: 8-10pm
Real Message Examples
What a proactive agent actually sends:
Health & Metrics
"BB 25 after the standup — meetings still hitting hard?"
"Stress baseline up 15% this week. Anything specific or just accumulation?"
"Sleep debt: 3h over past week. Weekend catchup or push through?"
Productivity
"4h in Slack, 45min in IDE — meeting-heavy day or context-switching?"
"Third day without commits. Stuck, planning, or intentional break?"
"Finished 0 of 5 planned tasks. Priorities shifted or underestimated?"
Patterns & Observations
"You mention 'tired' in evening messages 4x this week. Pattern or just words?"
"Project X deadline in 3 days, no activity in 5. Reprioritized?"
"Last bike ride: 9 days ago. Weather or motivation?"
Context-Aware
"Flight tomorrow at 7am. Alarm set, or should I remind at 10pm?"
"Meeting with [person] in 2h. Last time you wanted to discuss [topic] — still relevant?"
When to Stay Silent
Proactive ≠ chatty. Rules for silence:
## Stay Silent When:
- No meaningful observation
- Would repeat recent message
- User is clearly busy (deep work detected)
- Night time (unless urgent)
- Observation is obvious ("you're working")
- Data is stale (>2h old metrics)
## Speak When:
- Anomaly detected (outside normal range)
- Actionable insight (not just observation)
- Time-sensitive context (upcoming event)
- Pattern formed (3+ data points)
- User explicitly requested proactive check
Frequency Guidelines
| Context | Frequency | Condition |
|---|---|---|
| Health anomaly | Immediate | >2 std dev from baseline |
| Daily summary | Once | End of work hours |
| Pattern observation | When formed | 3+ occurrences |
| Reminder | As scheduled | User-set time |
| Random check-in | Never | Don’t do this |
Putting It Together
Agent System Prompt Addition
## Proactive Behavior
You have heartbeat capability. When triggered:
1. Load HEARTBEAT.md rules
2. Check available data sources
3. Search memory for relevant context
4. Decide: speak or stay silent
5. If speaking: 1-3 sentences, specific, question-form preferred
Priority order:
1. Time-sensitive (reminders, upcoming events)
2. Anomalies (health, productivity spikes/dips)
3. Patterns (multi-day observations)
4. Curiosity (open threads worth revisiting)
Default: silence. Speak only when valuable.
Data Sources to Check
| Source | What to look for |
|---|---|
| Screen time | Unusual apps, total hours |
| Health metrics | Stress, HRV, sleep |
| Calendar | Upcoming events, patterns |
| Git activity | Commits, PR status |
| Memory files | Open threads, due reminders |
Common Mistakes
Too chatty: Messaging on every heartbeat. Fix: default to silence.
Too vague: “You seem busy.” Fix: be specific or don’t speak.
No memory: Asking things already discussed. Fix: search before speaking.
Wrong timing: Messaging during focus time. Fix: detect work patterns.
Stating obvious: “You’re in a meeting.” Fix: only non-obvious insights.
Next: Memory System
Get updates
New guides, workflows, and AI patterns. No spam.
Thank you! You're on the list.