Install
openclaw skills install memory-routerOpenClaw skill that auto-tiers bloated MEMORY.md, generates smart per-session manifests, and routes only what matters — 70-85% context reduction with zero dependencies.
openclaw skills install memory-routerNever 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 Mode | Cause | Fix |
|---|---|---|
| Forgets everything | Loads irrelevant files, context window fills up | Smart manifest — load only what matters |
| Repeats mistakes | Lessons not captured or loaded | Entity index + audit for conflicts |
| Repeats work | No session state persistence | WAL protocol — write state before responding |
| Slow responses | Loads 50+ files when only 3 matter | Token budgeting — cap context window |
| Duplicates everywhere | No automated cleanup | --audit finds high-similarity pairs |
┌──────────────────────────────────────────────────────┐
│ 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 │ │
│ └─────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
node skills/memory-router/memory-router.js --tier
Output:
[memory-router] MEMORY.md: 7809 lines, 309254 chars
[memory-router] Tiered: 202 core sections, 1002 archived
[memory-router] MEMORY.md reduced from 7809 lines to 2222 lines
node skills/memory-router/memory-router.js --compact
Creates memory/memory-manifest.json — the agent's shopping list of what to load.
node skills/memory-router/memory-router.js --compact --query "alice"
Files linked to "alice" get priority. No AI, no embeddings — just fast entity resolution.
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.
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:
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/Sections are classified by header keywords (identity, preferences, etc.) or by content heuristics.
--compact)Creates memory/memory-manifest.json with a file list:
{
"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:
| Flag | Description |
|---|---|
--query "text" | Entity-aware boosting — files linked to matching entities get priority |
--budget N | Token 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)| Command | Description |
|---|---|
--entity add <name> <type> <files...> | Add entity (e.g., alice person preferences.md) |
--entity list | List all entities |
--entity search <query> | Search entities (direct and fuzzy match) |
--wal)| Command | Description |
|---|---|
--wal init | Initialize SESSION-STATE.md with template |
--wal get | Show current session state |
--wal update <section> --content "<text>" | Update a section |
Edit config.json to customize behavior:
{
"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"
]
}
}
| Setting | Default | Description |
|---|---|---|
memoryMdMaxLines | 500 | Auto-tier trigger (lines) |
memoryMdMaxChars | 25000 | Auto-tier trigger (characters) |
tierArchiveMinAgeDays | 3 | Minimum age before archiving |
retentionDays | 90 | Archive retention period |
keepInMemory | see above | Headers/keywords that stay in core |
generateOnTier | true | Auto-generate manifest after tiering |
duplicateThreshold | 0.7 | Similarity score to flag as duplicate |
conflictKeywords | see above | Words that signal fact revision |
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:
### ⚡ MemoryRouter
- Run `node skills/memory-router/memory-router.js --tier` if MEMORY.md is bloated
- Run `node skills/memory-router/memory-router.js --compact` to update manifest
- Run `node skills/memory-router/memory-router.js --audit` to check for issues
- Check `memory/memory-audit-report.md` for any flagged conflicts
| Metric | Result |
|---|---|
| Tiering speed (8K lines) | 25ms |
| Tiering speed (15K lines) | 30ms |
| Token reduction | 96% (7,809 → 222 lines) |
| File count reduction | 53 → 15 files |
| Memory footprint | ~2MB (Node.js runtime) |
| Approach | Tokens Saved | Setup Effort | Maintenance | Privacy |
|---|---|---|---|---|
| Raw file injection | 0% | None | Manual | ✅ |
| MemoryRouter | 70–85% | None | Automated | ✅ |
| Obsidian vault | 40–60% | High | Medium | ⚠️ Cloud |
| Vector DB (ChromaDB) | 70–85% | Very High | High | ✅ |
| mem0 | 70–85% | High | Medium | ⚠️ 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:
# ✅ 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:
{
"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
}
]
}
| Field | Type | Description |
|---|---|---|
tier | string | core, recent, domain, or archive |
required | bool | Always load this file |
size | int | File size in bytes |
boosted | bool | Entity match — higher priority |
entityMatch | string | Entity name that matched |
load | bool | Included under budget mode |
budgetUsed | int | Total tokens loaded (budget mode) |
budgetEfficiency | string | Percentage remaining (budget mode) |
| Problem | Fix |
|---|---|
| "No MEMORY.md found" | Create one: echo "# MEMORY.md" > MEMORY.md |
| "Memory directory not found" | Create it: mkdir -p memory |
| Tiering not working | Check thresholds — if under 500 lines and 25KB, nothing happens (by design) |
| Manifest shows wrong files | Run --compact again — it regenerates fresh each time |
| Entity search returns nothing | Add entities first: --entity add <name> <type> <files...> |
| Budget too small | Core files always load. Budget only controls optional files. |
Built with defense-in-depth: