# 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** ᕕ( ᐛ )ᕗ