Never lose context. Never forget decisions. Never repeat mistakes.
The memory problem is the single biggest reason agents feel dumb over time. Not the models. Not the prompts. Memory management.
MemoryRouter fixes it with one tool, zero dependencies, zero setup.
Agent memory files grow unbounded. After a week, you've got thousands of lines across dozens of files. Every session loads everything — even when the user asks "what's the weather?"
That's tokens burned on irrelevant memories, every interaction, forever.
Then compaction kicks in and details vanish.
The bottleneck isn't the model. It's what the model gets to see.
Failure ModeCauseFixForgets everythingLoads irrelevant files, context window fills upSmart manifest — load only what mattersRepeats mistakesLessons not captured or loadedEntity index + audit for conflictsRepeats workNo session state persistenceWAL protocol — write state before respondingSlow responsesLoads 50+ files when only 3 matterToken budgeting — cap context windowDuplicates everywhereNo automated cleanup--audit finds high-similarity pairs
text
┌──────────────────────────────────────────────────────┐
│ MEMORYROUTER ⚡ │
├──────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ AUTO-TIER │ │ MANIFEST │ │
│ │ MEMORY.md │ → │ GENERATOR │ │
│ │ │ │ │ │
│ │ Core (always │ │ Required: │ │
│ │ loaded) │ │ MEMORY.md │ │
│ │ + Archive │ │ Recent logs │ │
│ │ (on demand) │ │ Boosted: │ │
│ └──────────────┘ │ entity files │ │
│ └──────┬───────┘ │
│ │ │
│ ┌──────────────▼──────────────┐ │
│ │ ENTITY RESOLUTION │ │
│ │ "alice" → preferences.md, │ │
│ │ notes.md, decisions.md│ │
│ └──────────────┬──────────────┘ │
│ │ │
│ ┌──────────────▼──────────────┐ │
│ │ TOKEN BUDGET FILTER │ │
│ │ 20K budget → 7 files │ │
│ │ 100K budget → 16 files │ │
│ └──────────────┬──────────────┘ │
│ │ │
│ ┌──────────────▼──────────────┐ │
│ │ AGENT LOADS ONLY WHAT │ │
│ │ MATTERS → 70-85% REDUCTION │ │
│ └─────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
MemoryRouter automatically modifies MEMORY.md and archive files under memory/ during --tier, --audit, and --restore operations. These changes are not reversible unless you have a backup. Always run --dry-run first to preview changes.
--tier rewrites MEMORY.md permanently--restore overwrites MEMORY.md with backup content--cleanup with auto-remove can delete archived entries--confirm / --force flags and will refuse to run without themMemoryRouter reads and writes memory/ files and directories. Ensure proper filesystem permissions and avoid running in untrusted shared directories.
bash
node skills/memory-router/memory-router.js --tier --confirm
Output:
text
[memory-router] MEMORY.md: 7809 lines, 309254 chars
[memory-router] ✅ Pre-tier backup: memory/backups/MEMORY-backup-2026-05-23-1234567890.md (7809 lines saved)
[memory-router] Tiered: 202 core sections, 1002 archived
[memory-router] MEMORY.md reduced from 7809 lines to 2222 lines
bash
node skills/memory-router/memory-router.js --tier --dry-run
Output:
text
[memory-router] MEMORY.md: 7809 lines, 309254 chars
[memory-router] ── DRY RUN ──
[memory-router] Would archive: memory/active/MEMORY-archive-2026-05-23.md
[memory-router] Would reduce MEMORY.md from 7809 lines to ~2222 lines
[memory-router] Core sections: 202, Archive sections: 1002
[memory-router] ✅ No files were modified.
bash
node skills/memory-router/memory-router.js --restore --force
⚠️ Destructive — overwrites MEMORY.md. Requires --force flag. Extracts only the original content from the backup (metadata headers are stripped). Always creates a backup of the current MEMORY.md before overwriting.
bash
node skills/memory-router/memory-router.js --compact
Creates memory/memory-manifest.json — the agent's shopping list of what to load.
bash
node skills/memory-router/memory-router.js --compact --query "alice"
Files linked to "alice" get priority. No AI, no embeddings — just fast entity resolution.
bash
node skills/memory-router/memory-router.js --compact --budget 20000
Only loads files that fit within 20K tokens. Tight budgets load core only. Generous budgets load archive on demand.
bash
node skills/memory-router/memory-router.js --audit # Find duplicates & conflicts
node skills/memory-router/memory-router.js --status # Health overview
node skills/memory-router/memory-router.js --entity add alice person preferences.md
Memory management is the bottleneck, not model capability. Every agent system hits the same wall — context window fills up, everything loads, irrelevant memories dilute the signal.
MemoryRouter takes a routing approach rather than a compression approach:
text
User query → --compact --query "alice"
↓
Manifest generated
↓
Load required files (MEMORY.md, recent daily logs)
↓
Boost entity-matched files (preferences.md, notes.md)
↓
Agent loads only what matters → 70-85% context reduction
--tier)#When MEMORY.md exceeds configurable thresholds (default: 500 lines or 25KB), splits into:
memory/active/Safety features (v2):
--tier creates a full backup in memory/backups/ before modifying MEMORY.md--dry-run — Preview what tiering would do without making changes--confirm — Required for destructive writes (no auto-tier without explicit confirmation)minCoreLines/ minCoreChars thresholds--restore --force — Restore MEMORY.md from the latest backup (requires --force flag)Sections are classified by header keywords (identity, preferences, etc.) or by content heuristics.
--compact)#Creates memory/memory-manifest.json with a file list:
json
{
"generated": "2026-05-21",
"files": [
{ "path": "MEMORY.md", "tier": "core", "required": true, "size": 50346 },
{ "path": "memory/2026-05-21.md", "tier": "recent", "required": true, "size": 2034 },
{ "path": "self-improving/memory.md", "tier": "domain", "required": false, "size": 670 }
]
}
Options:
FlagDescription--query "text"Entity-aware boosting — files linked to matching entities get priority--budget NToken budget — only loads files that fit within N tokens
--audit)#Scans all memory files for:
Output: memory/memory-audit-report.md
--status)#Quick snapshot of MEMORY.md line/char counts, file counts per directory, archive count, manifest status, entity index size, and WAL state.
--entity)#CommandDescription--entity add <name> <type> <files...>Add entity (e.g., alice person preferences.md)--entity listList all entities--entity search <query>Search entities (direct and fuzzy match)
--wal)#CommandDescription--wal initInitialize SESSION-STATE.md with template--wal getShow current session state--wal update <section> --content "<text>"Update a section
Edit config.json to customize behavior:
json
{
"thresholds": {
"memoryMdMaxLines": 500,
"memoryMdMaxChars": 25000,
"tierArchiveMinAgeDays": 3,
"auditMaxFiles": 50
},
"tiering": {
"archiveDir": "memory/active",
"retentionDays": 90,
"keepInMemory": [
"identity", "preferences", "relationships",
"projects", "patterns", "boundaries", "key_facts"
]
},
"manifest": {
"generateOnTier": true,
"manifestPath": "memory/memory-manifest.json"
},
"audit": {
"reportPath": "memory/memory-audit-report.md",
"duplicateThreshold": 0.7,
"conflictKeywords": [
"revised", "updated", "changed", "no longer",
"actually", "correction", "mistake"
]
}
}
SettingDefaultDescriptionmemoryMdMaxLines500Auto-tier trigger (lines)memoryMdMaxChars25000Auto-tier trigger (characters)tierArchiveMinAgeDays3Minimum age before archivingretentionDays90⚠️ Archive retention period. Files older than this are candidates for deletion (irreversible). Set to 365+ until confident.keepInMemorysee aboveHeaders/keywords that stay in coregenerateOnTiertrueAuto-generate manifest after tieringduplicateThreshold0.7Similarity score to flag as duplicateconflictKeywordssee aboveWords that signal fact revisionbackupDir``memory/backupsDirectory for pre-tier backupsminCoreLines20Abort if core sections below thisminCoreChars1000Abort if core chars below this
When the agent wakes up, use the manifest instead of loading all memory files:
memory/memory-manifest.jsonrequired: true filesrequired: false files, use memory_search to check relevanceResult: 70–85% context reduction — load what matters, skip the rest.
Add to your HEARTBEAT.md:
markdown
### ⚡ MemoryRouter (SAFE commands only)
- Run `node skills/memory-router/memory-router.js --compact` to update manifest ✅ safe
- Run `node skills/memory-router/memory-router.js --audit` to check for issues ✅ safe
- Run `node skills/memory-router/memory-router.js --status` for health overview ✅ safe
- ⚠️ Do NOT auto-run `--tier` or `--restore` during heartbeats
- `--tier --dry-run` is side-effect free (no files created)
- For tiering: run `--tier --dry-run` manually, review output, then `--tier --confirm`
MetricResultTiering speed (8K lines)25msTiering speed (15K lines)30msToken reduction96% (7,809 → 222 lines)File count reduction53 → 15 filesMemory footprint~2MB (Node.js runtime)
ApproachTokens SavedSetup EffortMaintenancePrivacyRaw file injection0%NoneManual✅**MemoryRouter70–85%NoneAutomated✅**Obsidian vault40–60%HighMedium⚠️ CloudVector DB (ChromaDB)70–85%Very HighHigh✅mem070–85%HighMedium⚠️ Cloud
MemoryRouter gives you the best token savings of the vector DB approach with zero setup effort.
Pick one canonical name per entity and reuse it consistently:
--entity search periodically to verify your indexExamples:
bash
# ✅ Good — consistent, descriptive
node memory-router.js --entity add alice person preferences.md
node memory-router.js --entity add openclaw system AGENTS.md
# ❌ Bad — inconsistent, ambiguous
node memory-router.js --entity add alice person preferences.md
node memory-router.js --entity add Alice person notes.md
node memory-router.js --entity add JS person docs.md
The manifest JSON tells the agent which files to load:
json
{
"generated": "2026-05-21",
"version": 2,
"query": "memory management",
"budget": 20000,
"files": [
{
"path": "MEMORY.md",
"tier": "core",
"required": true,
"size": 50346
},
{
"path": "memory/2026-05-21.md",
"tier": "recent",
"ageDays": 0,
"required": true,
"size": 2034
},
{
"path": "self-improving/memory.md",
"tier": "domain",
"required": false,
"size": 670
}
]
}
FieldTypeDescriptiontierstringcore, recent, domain, or archive``requiredboolAlways load this filesizeintFile size in bytesboostedboolEntity match — higher priorityentityMatchstringEntity name that matchedloadboolIncluded under budget modebudgetUsedintTotal tokens loaded (budget mode)budgetEfficiencystringPercentage remaining (budget mode)
ProblemFix"No MEMORY.md found"Create one: echo "# MEMORY.md" > MEMORY.md"Memory directory not found"Create it: mkdir -p memoryTiering not workingCheck thresholds — if under 500 lines and 25KB, nothing happens (by design)Manifest shows wrong filesRun --compact again — it regenerates fresh each timeEntity search returns nothingAdd entities first: --entity add <name> <type> <files...>Budget too smallCore files always load. Budget only controls optional files.
--tier and --restore permanently modify user memory files.
--tier rewrites MEMORY.md, moving sections to archive files--restore overwrites MEMORY.md with backup content--confirm / --force) — they will refuse to run without it--tier --dry-run first to preview what will changeThe retentionDays config (default: 90) marks archived files as candidates for deletion after that period. This is irreversible — once deleted, archived memory sections cannot be recovered.
Before enabling retention:
memory/ directoryretentionDays to a large value (365+) until you're confidentCommandSafe in automation?Modifies files?--compact✅ YesWrites memory-manifest.json (generated output)--audit✅ YesWrites memory-audit-report.md (generated report)--status✅ YesNo file writes--entity add⚠️ Yes — but writes entity indexYes (persists entity → file mapping)--entity list/search✅ YesNo file writes--wal init⚠️ Yes — but creates SESSION-STATE.mdYes (creates new file)--wal get✅ YesNo file writes--wal update⚠️ Yes — but modifies SESSION-STATE.mdYes (updates session state)--tier --dry-run✅ YesNo file writes (side-effect free)--tier --confirm❌ No — rewrites MEMORY.md + creates backupYes--restore --force❌ No — overwrites MEMORY.mdYes
--compact, --audit, --status, --entity list/search, --wal get, and --tier --dry-run are safe for unattended/heartbeat use.
--entity add, --wal init, and --wal update write persistent files — review before automating.
--tier --confirm and --restore --force are destructive — never automate.
Built with defense-in-depth:
--confirm, --force)