Memory System
OWL uses a three-layer memory system to maintain persistent context across sessions.
Overview
┌─────────────────────────────────────────────────────────┐
│ Memory Layers │
├─────────────────────────────────────────────────────────┤
│ Layer 1: Memory File (~/.owl/memory.md) │
│ - Human-readable markdown │
│ - Preferences, notes, decisions │
│ - Loaded into every conversation │
├─────────────────────────────────────────────────────────┤
│ Layer 2: SQLite Database (~/.owl/memory/owl.db) │
│ - Conversation history │
│ - Auto-extracted learnings │
│ - Project context cache │
├─────────────────────────────────────────────────────────┤
│ Layer 3: Session Summaries │
│ - Compressed old conversations │
│ - Prevents context bloat │
│ - Maintains continuity │
└─────────────────────────────────────────────────────────┘
Layer 1: Memory File
The memory file (~/.owl/memory.md) stores facts you want OWL to always remember.
Structure
# Memory
## Preferences
- I prefer tabs over spaces
- Use pytest for Python testing
- Always include type hints
## Notes
- Project uses PostgreSQL database
- API keys are in .env file
- Deployment is via Docker
## Decisions
- Chose FastAPI over Flask for performance
- Using SQLAlchemy for ORM
Commands
# View memory
/memory
# Add to memory (auto-categorized)
/remember I prefer functional programming style
/remember Database password is in vault
# Remove from memory
/forget I prefer functional programming style
How It's Used
The memory file content is included in every LLM request, ensuring OWL always has access to your preferences and project facts.
Layer 2: SQLite Database
The SQLite database stores structured data that's too detailed for the memory file.
Tables
conversations
Stores all messages by session and project:
| Column | Type | Description |
|---|---|---|
| id | INTEGER | Primary key |
| session_id | TEXT | Session identifier |
| project_path | TEXT | Associated project |
| role | TEXT | user/assistant/tool |
| content | TEXT | Message content |
| timestamp | DATETIME | When sent |
| metadata | JSON | Extra data |
learnings
Auto-extracted insights from conversations:
| Column | Type | Description |
|---|---|---|
| id | INTEGER | Primary key |
| category | TEXT | preference/project/style/technical |
| observation | TEXT | What was observed |
| learning | TEXT | What to remember |
| project_path | TEXT | If project-specific |
| scope | TEXT | global/project |
| confidence | FLOAT | How certain |
| source | TEXT | user/auto |
sessions
Session metadata:
| Column | Type | Description |
|---|---|---|
| id | TEXT | Session ID |
| started_at | DATETIME | Start time |
| last_active | DATETIME | Last activity |
| message_count | INTEGER | Total messages |
| summary | TEXT | Compressed summary |
Automatic Reflection
Every 3 conversation exchanges, OWL reflects and extracts learnings:
Exchange 1: User asks about Python testing
Exchange 2: OWL suggests pytest, user agrees
Exchange 3: User mentions preference for fixtures
→ Reflection triggers
→ Learning extracted: "User prefers pytest fixtures over setup methods"
Project-Scoped History
Conversation history is scoped by project to prevent context contamination:
Project A history stays separate from Project B
When you switch projects, you get relevant history
Layer 3: Session Summaries
Long conversations are automatically summarized to prevent context overflow.
How It Works
- After 20 messages in a session
- OWL summarizes the oldest 10 messages
- Summary replaces detailed messages
- Most recent 10 messages stay fresh
Summary Format
Session Summary:
- Discussed Python testing approaches
- Decided on pytest with fixtures
- Reviewed authentication implementation
- Fixed bug in user registration
Configuration
Thresholds are set in the code:
SUMMARIZE_THRESHOLD = 20(when to summarize)SUMMARIZE_BATCH = 10(how many to summarize, leaves 10 recent)
Memory Best Practices
What to Remember
Good candidates for /remember:
- Coding style preferences
- Project-specific facts
- Tool and framework choices
- Team conventions
- Important decisions
What NOT to Remember
Avoid storing:
- Sensitive credentials (use environment variables)
- Frequently changing information
- Very specific implementation details
Organizing Memory
The memory file auto-categorizes, but you can be explicit:
# Preferences (coding style, tools)
/remember I prefer descriptive variable names
# Notes (project facts)
/remember API rate limit is 100 requests/minute
# Decisions (architectural choices)
/remember Chose event sourcing for audit trail
Viewing Memory Data
Memory File
cat ~/.owl/memory.md
SQLite Database
sqlite3 ~/.owl/memory/owl.db
# Recent messages
SELECT role, substr(content, 1, 50) FROM conversations
ORDER BY timestamp DESC LIMIT 10;
# Learnings
SELECT category, learning FROM learnings;
# Sessions
SELECT id, message_count, last_active FROM sessions;
Data Persistence
| Data | Location | Survives Restart |
|---|---|---|
| Memory file | ~/.owl/memory.md | Yes |
| Conversations | owl.db | Yes |
| Learnings | owl.db | Yes |
| Session state | Memory | No |
When you restart the daemon:
- Memory file is reloaded
- Recent session can be resumed (within 2 hours)
- All learnings persist