435 lines
27 KiB
Markdown
435 lines
27 KiB
Markdown
# Memory System Architecture Diagram
|
|
|
|
Visual representation of how the Clawdbot memory system works.
|
|
|
|
---
|
|
|
|
## High-Level Flow
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ USER / AGENT CHAT │
|
|
│ "What did we decide about the API key strategy?" │
|
|
└──────────────────────┬──────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ AGENT REASONING LAYER │
|
|
│ "This is about prior decisions → must search memory" │
|
|
└──────────────────────┬──────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ memory_search(query) │
|
|
│ → Converts query to embedding vector │
|
|
│ → Searches SQLite vector store │
|
|
│ → Returns: snippets + file paths + line numbers │
|
|
└──────────────────────┬──────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ SEARCH RESULTS (snippets only) │
|
|
│ memory/2026-02-04.md (lines 42-58) │
|
|
│ "Decided to use manual API key signup batch..." │
|
|
│ Score: 0.87 │
|
|
└──────────────────────┬──────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ memory_get(path, from, lines) │
|
|
│ → Reads full context from markdown file │
|
|
│ → Returns: complete text from specified line range │
|
|
└──────────────────────┬──────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ AGENT RESPONSE │
|
|
│ "On Feb 4, we decided manual signup batch (~30 min) │
|
|
│ because CAPTCHA bypass violates ToS..." │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Storage Architecture
|
|
|
|
```
|
|
┌────────────────────────────────────────────────────────────────┐
|
|
│ WORKSPACE DIRECTORY │
|
|
│ ~/.clawdbot/workspace/ │
|
|
└────────────────────────┬───────────────────────────────────────┘
|
|
│
|
|
┌────────────────┴────────────────┐
|
|
│ │
|
|
▼ ▼
|
|
┌──────────────────┐ ┌──────────────────────┐
|
|
│ MARKDOWN FILES │ │ CONFIG FILES │
|
|
│ (Source Truth) │ │ (Identity/Rules) │
|
|
├──────────────────┤ ├──────────────────────┤
|
|
│ memory/ │ │ AGENTS.md │
|
|
│ ├─ 2026-02-09.md │ │ SOUL.md │
|
|
│ ├─ 2026-02-08.md │ │ USER.md │
|
|
│ ├─ research.md │ │ HEARTBEAT.md │
|
|
│ └─ TEMPLATE.md │ │ TOOLS.md │
|
|
└────────┬─────────┘ └──────────────────────┘
|
|
│
|
|
│ (watched by file watcher, 1.5s debounce)
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ INDEXING PIPELINE │
|
|
│ 1. Detect file changes (watcher) │
|
|
│ 2. Chunk markdown (~400 tokens, 80 overlap) │
|
|
│ 3. Generate embeddings (OpenAI/Gemini/local) │
|
|
│ 4. Store in SQLite │
|
|
└────────────────────┬────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ SQLITE DATABASE (Search Engine) │
|
|
│ ~/.clawdbot/memory/main.sqlite │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ Tables: │
|
|
│ ┌─────────────────────────────────────────────┐ │
|
|
│ │ files │ │
|
|
│ │ - path, hash, mtime, size │ │
|
|
│ └─────────────────────────────────────────────┘ │
|
|
│ ┌─────────────────────────────────────────────┐ │
|
|
│ │ chunks │ │
|
|
│ │ - id, file_id, text, start_line, end_line │ │
|
|
│ └─────────────────────────────────────────────┘ │
|
|
│ ┌─────────────────────────────────────────────┐ │
|
|
│ │ chunks_vec (vector table) │ │
|
|
│ │ - chunk_id, embedding (float32[1536]) │ │
|
|
│ │ - Accelerated by sqlite-vec extension │ │
|
|
│ └─────────────────────────────────────────────┘ │
|
|
│ ┌─────────────────────────────────────────────┐ │
|
|
│ │ chunks_fts (full-text search) │ │
|
|
│ │ - FTS5 index for BM25 keyword search │ │
|
|
│ └─────────────────────────────────────────────┘ │
|
|
│ ┌─────────────────────────────────────────────┐ │
|
|
│ │ embedding_cache │ │
|
|
│ │ - text_hash, embedding (dedup) │ │
|
|
│ └─────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Hybrid Search Flow (Vector + BM25)
|
|
|
|
```
|
|
memory_search("API key strategy")
|
|
│
|
|
▼
|
|
┌──────────────────────┐
|
|
│ Query Embedding │
|
|
│ (via OpenAI API) │
|
|
└──────────┬───────────┘
|
|
│
|
|
┌─────────┴─────────┐
|
|
│ │
|
|
▼ ▼
|
|
┌──────────────┐ ┌──────────────────┐
|
|
│ Vector Search│ │ BM25 Keyword │
|
|
│ (semantic) │ │ Search (exact) │
|
|
├──────────────┤ ├──────────────────┤
|
|
│ Top 20 by │ │ Top 20 by FTS5 │
|
|
│ cosine sim │ │ BM25 rank │
|
|
└──────┬───────┘ └────────┬─────────┘
|
|
│ │
|
|
└──────────┬─────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────┐
|
|
│ Merge & Rank │
|
|
│ (weighted score) │
|
|
│ 70% vector │
|
|
│ 30% keyword │
|
|
└──────────┬───────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────┐
|
|
│ Top 5 Results │
|
|
│ (with snippets) │
|
|
└──────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Embedding Providers
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ EMBEDDING PROVIDER OPTIONS │
|
|
└──────────────────────────────────────────────────────┘
|
|
|
|
Option 1: OpenAI (Recommended for Production)
|
|
┌────────────────────────────────────────────┐
|
|
│ Provider: openai │
|
|
│ Model: text-embedding-3-small │
|
|
│ Size: 1536 dimensions │
|
|
│ Cost: $0.02 / 1M tokens (Batch: $0.01) │
|
|
│ Speed: Fast (Batch API parallel) │
|
|
│ Setup: API key only │
|
|
└────────────────────────────────────────────┘
|
|
|
|
Option 2: Gemini
|
|
┌────────────────────────────────────────────┐
|
|
│ Provider: gemini │
|
|
│ Model: text-embedding-004 │
|
|
│ Size: 768 dimensions │
|
|
│ Cost: Free tier available │
|
|
│ Speed: Fast │
|
|
│ Setup: API key only │
|
|
└────────────────────────────────────────────┘
|
|
|
|
Option 3: Local (Offline)
|
|
┌────────────────────────────────────────────┐
|
|
│ Provider: local │
|
|
│ Model: embeddinggemma-300M-Q8_0.gguf │
|
|
│ Size: ~600 MB download │
|
|
│ Cost: Free (compute only) │
|
|
│ Speed: Slower (CPU/GPU dependent) │
|
|
│ Setup: Auto-download, rebuild required │
|
|
└────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Write Flow (Agent → Disk)
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ AGENT DECISION: "Need to remember this" │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ write / edit / append │
|
|
│ target: memory/2026-02-09.md │
|
|
│ content: "## Decisions Made\n- Chose X..." │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ MARKDOWN FILE UPDATED │
|
|
│ memory/2026-02-09.md (on disk) │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼ (file watcher triggers)
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ INDEXING PIPELINE (Automatic) │
|
|
│ 1. Detects change │
|
|
│ 2. Re-chunks file │
|
|
│ 3. Generates embeddings (cached if unchanged) │
|
|
│ 4. Updates SQLite │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ SEARCH INDEX UPDATED (background) │
|
|
│ New decision is now searchable │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Pre-Compaction Memory Flush
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ SESSION TOKEN COUNT MONITOR │
|
|
│ Threshold: contextWindow - reserveFloor - 4000 │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼ (threshold crossed)
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ MEMORY FLUSH TRIGGER │
|
|
│ Silent agentic turn (user doesn't see) │
|
|
│ System: "Session nearing compaction. Store now." │
|
|
│ User: "Write lasting notes; reply NO_REPLY" │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ AGENT REVIEWS CONTEXT │
|
|
│ Scans recent messages for: │
|
|
│ - Decisions made │
|
|
│ - Preferences stated │
|
|
│ - Important facts │
|
|
│ - TODOs assigned │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ WRITES TO MEMORY (if needed) │
|
|
│ write("memory/2026-02-09.md", ...) │
|
|
│ → Durable memory stored │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ REPLIES "NO_REPLY" │
|
|
│ (User never sees this turn) │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ COMPACTION PROCEEDS SAFELY │
|
|
│ Old context removed, but memory is on disk │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Git Backup Flow
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ END OF DAY / SESSION │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ MANUAL OR CRON TRIGGER │
|
|
│ git add -A && git commit -m "..." && git push │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ ALL MARKDOWN FILES STAGED │
|
|
│ memory/*.md, AGENTS.md, USER.md, etc. │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ COMMITTED TO LOCAL GIT REPO │
|
|
│ SHA: abc123... "Daily backup: 2026-02-09" │
|
|
└──────────────────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ PUSHED TO REMOTE (GitHub/GitLab) │
|
|
│ Entire memory history is now backed up │
|
|
│ Recoverable even if local disk fails │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Data Flow Summary
|
|
|
|
```
|
|
HUMAN INPUT
|
|
↓
|
|
AGENT CHAT
|
|
↓
|
|
DECISION/FACT IDENTIFIED
|
|
↓
|
|
WRITE TO MARKDOWN ← (source of truth)
|
|
↓
|
|
FILE WATCHER DETECTS CHANGE
|
|
↓
|
|
INDEXING PIPELINE
|
|
├→ Chunk text
|
|
├→ Generate embeddings
|
|
└→ Store in SQLite ← (search engine)
|
|
↓
|
|
SEARCHABLE VIA memory_search
|
|
↓
|
|
AGENT CAN RECALL IN FUTURE SESSIONS
|
|
↓
|
|
GIT BACKUP (end of day)
|
|
↓
|
|
SAFE IN REMOTE REPO
|
|
```
|
|
|
|
---
|
|
|
|
## Performance Characteristics
|
|
|
|
```
|
|
┌───────────────────────────────────────────────────────┐
|
|
│ OPERATION TIMINGS │
|
|
├───────────────────────────────────────────────────────┤
|
|
│ memory_search query: <100ms │
|
|
│ memory_get read: <10ms │
|
|
│ Index rebuild (35 files): ~2 seconds │
|
|
│ File watcher debounce: 1.5 seconds │
|
|
│ Embedding generation: ~50ms per chunk (OpenAI) │
|
|
│ SQLite vector search: <50ms (with sqlite-vec) │
|
|
│ BM25 search: <20ms (FTS5) │
|
|
└───────────────────────────────────────────────────────┘
|
|
|
|
┌───────────────────────────────────────────────────────┐
|
|
│ STORAGE FOOTPRINT │
|
|
├───────────────────────────────────────────────────────┤
|
|
│ 35 markdown files: ~500 KB │
|
|
│ SQLite database: ~15 MB │
|
|
│ Vector embeddings: ~12 MB (in SQLite) │
|
|
│ Metadata + indexes: ~3 MB │
|
|
└───────────────────────────────────────────────────────┘
|
|
|
|
┌───────────────────────────────────────────────────────┐
|
|
│ COST (OpenAI Batch API) │
|
|
├───────────────────────────────────────────────────────┤
|
|
│ Initial index (35 files): ~$0.10 │
|
|
│ Daily updates (~3 files): ~$0.01 │
|
|
│ Monthly cost: ~$0.50 │
|
|
└───────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Scaling Considerations
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ FILES │ CHUNKS │ SEARCH TIME │
|
|
├─────────────────────────────────────────────────────┤
|
|
│ < 50 files │ < 200 │ < 100ms │
|
|
│ 50-200 files │ 200-1000 │ < 200ms │
|
|
│ 200-500 files │ 1000-2500 │ < 500ms │
|
|
│ 500-1000 files │ 2500-5000 │ < 1 second │
|
|
│ 1000+ files │ 5000+ │ Consider: │
|
|
│ │ │ - Partitioning│
|
|
│ │ │ - Archiving │
|
|
│ │ │ - Multi-index│
|
|
└─────────────────────────────────────────────────────┘
|
|
|
|
Recommendation: Archive old logs after 3-6 months
|
|
- Move to `memory/archive/YYYY/`
|
|
- Keep recent 90 days active
|
|
- Full archive remains searchable if needed
|
|
```
|
|
|
|
---
|
|
|
|
## Failure Modes & Recovery
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ FAILURE SCENARIO │ RECOVERY │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ SQLite index corrupted │ Rebuild from MD │
|
|
│ Markdown files deleted │ Restore from git│
|
|
│ Embedding API down │ Fallback/local │
|
|
│ Disk full │ Archive old logs│
|
|
│ Config error │ Revert git │
|
|
│ Clawdbot crash mid-write │ Git diff check │
|
|
└─────────────────────────────────────────────────────────┘
|
|
|
|
Recovery command:
|
|
rm ~/.clawdbot/memory/main.sqlite && clawdbot memory index
|
|
|
|
Principle: Markdown files are source of truth —
|
|
SQLite is always regenerable.
|
|
```
|
|
|
|
---
|
|
|
|
**END OF ARCHITECTURE DIAGRAM**
|
|
|
|
ᕕ( ᐛ )ᕗ
|