memory-router

Central dispatch layer for OpenClaw Memory Stack. Routes memory queries to the best backend via signal detection, class-based dispatch, and sequential fallback.

3,891 stars

Best use case

memory-router is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Central dispatch layer for OpenClaw Memory Stack. Routes memory queries to the best backend via signal detection, class-based dispatch, and sequential fallback.

Teams using memory-router should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/memory-router/SKILL.md --create-dirs "https://raw.githubusercontent.com/openclaw/skills/main/skills/apptah/openclaw-memory-stack/skills/memory-router/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/memory-router/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How memory-router Compares

Feature / Agentmemory-routerStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Central dispatch layer for OpenClaw Memory Stack. Routes memory queries to the best backend via signal detection, class-based dispatch, and sequential fallback.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Memory Router — SKILL.md

## Overview

Memory Router is the central dispatch layer of the OpenClaw Memory Stack. It receives memory queries from the AI agent and routes them to the appropriate backend based on a deterministic rule table with sequential fallback. It is **not** an AI-powered optimizer — it is a rule-based router with explicit signal matching and a well-defined fallback chain.

**How it works:**
1. Read `~/.openclaw/state/backends.json` to discover which backends are installed.
2. Match the incoming query against the routing rule table (top-to-bottom, first match wins).
3. Dispatch to the primary backend.
4. If the result is poor (normalized_relevance < 0.4, status = empty, or status = error), fall back sequentially through the fallback chain.
5. Return the best result found, wrapped in the router envelope.

The router adds zero storage — it is purely a dispatch and fallback coordinator. All actual memory operations happen in the backends.

## Prerequisites

- `~/.openclaw/state/backends.json` must exist and list installed backends.
- At least one backend must be installed (QMD and Total Recall are always present in Starter).
- The router itself has no runtime dependencies beyond the ability to read JSON and invoke backend skills.

## Routing Rules

### Tier-Aware Backend Discovery

Before evaluating rules, the router reads `~/.openclaw/state/backends.json` to build the **candidate list** of available backends. If a backend appears in a routing rule but is not in the candidate list, it is silently skipped — no error, no warning. The fallback chain advances to the next available backend.

**Starter tier** (QMD + Total Recall): Cognee and Lossless rules are effectively disabled — queries that would route to them fall through to QMD or Total Recall alternatives automatically.

**Pro tier** (all 4 backends): The full routing table is active.

### Rule Table

Rules are evaluated top-to-bottom. The first rule whose signal matches the query wins. If no rule matches, the default rule applies.

| # | Signal in Query | Primary Backend | Fallback Chain | Rationale |
|---|----------------|----------------|----------------|-----------|
| 1 | Exact symbol, function name, class name, method name (`find function`, `find class`, `find method`, or a CamelCase/snake_case identifier) | QMD (`search` mode) | Total Recall | BM25 excels at exact token matching on code identifiers |
| 2 | Relationship query: "how does X relate to Y", "dependency between", "connection between", "what depends on", "call chain", "trace from...to" | Cognee | QMD (`vsearch`) > Total Recall | Graph traversal is required to follow entity relationships |
| 3 | Decision recall: "what did we decide about", "earlier in conversation", "decision from", "why did we choose", "recall the decision" | Lossless | Total Recall > QMD (`search`) | DAG preserves causal decision chains from conversation history |
| 4 | Concept/behavior query: "how does X work", "where is Y handled", "explain the...strategy", "what is the approach for" | QMD (`vsearch` mode) | QMD (`query`) > Total Recall | Vector semantic search finds conceptually related code |
| 5 | Recent context: "just discussed", "few minutes ago", "last change", "what was the last thing", "recently" | Total Recall | QMD (`search`) | Time-decay relevance prioritizes recent memories |
| 6 | File/path pattern: "in src/auth/", "*.swift files", file path segments, glob patterns | QMD (`search` mode) | Total Recall | BM25 path-based search matches filesystem patterns |
| 7 | Ambiguous / no clear signal (single words, vague references, catch-all) | QMD (`query` mode) | Total Recall | Hybrid search (BM25 + vector) is the safest default for unclear intent |

**Rule 7 is the default rule.** If no signal from rules 1-6 is detected, the query routes to QMD hybrid search.

### Signal Detection

Signal matching uses keyword and pattern detection, not semantic understanding. The router looks for:

- **Rule 1 (exact symbol)**: Query contains `find.*function`, `find.*class`, `find.*method`, `find all usages of`, `search for`, or a token that matches CamelCase/snake_case identifier patterns.
- **Rule 2 (relationship)**: Query contains `relate`, `relationship`, `depends on`, `dependency`, `connection`, `call chain`, `trace.*to`, `path between`.
- **Rule 3 (decision recall)**: Query contains `decide`, `decision`, `chose`, `why did we`, `recall.*decision`, `earlier in conversation`, `morning session`, `afternoon session`.
- **Rule 4 (concept/behavior)**: Query contains `how does.*work`, `where is.*handled`, `explain`, `strategy`, `approach for`, `what is the.*for`.
- **Rule 5 (recent context)**: Query contains `just discussed`, `few minutes ago`, `last change`, `recently`, `last thing`, `what was the last`.
- **Rule 6 (file/path)**: Query contains file path separators (`/`), glob patterns (`*`, `**`), or file extensions (`.ts`, `.swift`, `.py`, etc.).
- **Rule 7 (default)**: No signal detected from rules 1-6.

## Fallback Logic

The fallback mechanism is sequential and deterministic:

1. **Dispatch to primary backend** per the matched rule.
2. **Evaluate the response:**
   - `normalized_relevance >= 0.4` AND `status = success` — Accept the result. Done.
   - `normalized_relevance < 0.4` OR `status = empty` — Result is insufficient. Move to next backend in fallback chain.
   - `status = error` — Immediate fallback. Log the error to `~/.openclaw/state/router.log`.
3. **Timeout enforcement:** The router measures wall-clock time for each backend call. If a backend exceeds 5000ms, the router marks the response as `QUERY_TIMEOUT` and moves to the next backend in the chain.
4. **Chain exhaustion:** If the entire fallback chain is exhausted without a good result (normalized_relevance >= 0.4), the router returns the **best result found across all attempted backends** (even if < 0.4) with `status: partial`.
5. **Total failure:** If every backend in the chain returns `status = error`, the router returns:

```json
{
  "status": "error",
  "error_code": "ALL_BACKENDS_FAILED",
  "error_message": "All backends in the fallback chain failed. Check ~/.openclaw/state/router.log for details."
}
```

### Fallback Behavior with Missing Backends

When a backend in the fallback chain is not installed (not in `backends.json`), the router skips it silently and advances to the next entry. This is how Starter tier works naturally — Cognee and Lossless are simply not in the candidate list, so rules 2 and 3 fall through to their QMD/Total Recall alternatives.

**Example — Rule 2 on Starter tier:**
- Primary: Cognee (not installed) — skip
- Fallback 1: QMD vsearch — execute
- Fallback 2: Total Recall — execute if QMD result is poor

## Few-Shot Routing Examples

### Clear Queries (10)

**1. "find the function parseAuthToken"**
- Signal: `find.*function` + CamelCase identifier
- Rule matched: #1 (exact symbol)
- Routed to: QMD `search` mode
- Fallback chain: [Total Recall]

**2. "how does the auth middleware relate to the session store"**
- Signal: `relate` keyword, two identifiable entities
- Rule matched: #2 (relationship)
- Routed to: Cognee (if Pro), else QMD `vsearch` (Starter fallthrough)
- Fallback chain: [QMD vsearch, Total Recall]

**3. "what did we decide about the database schema in the morning session"**
- Signal: `decide` keyword, `morning session`
- Rule matched: #3 (decision recall)
- Routed to: Lossless (if Pro), else Total Recall (Starter fallthrough)
- Fallback chain: [Total Recall, QMD search]

**4. "how does error handling work in the API layer"**
- Signal: `how does.*work`
- Rule matched: #4 (concept/behavior)
- Routed to: QMD `vsearch`
- Fallback chain: [QMD query, Total Recall]

**5. "what was the last thing we changed"**
- Signal: `last thing`
- Rule matched: #5 (recent context)
- Routed to: Total Recall
- Fallback chain: [QMD search]

**6. "search in src/models/*.ts"**
- Signal: file path separator `/`, glob pattern `*`, extension `.ts`
- Rule matched: #6 (file/path pattern)
- Routed to: QMD `search`
- Fallback chain: [Total Recall]

**7. "find all usages of UserService"**
- Signal: `find all usages of` + CamelCase identifier
- Rule matched: #1 (exact symbol)
- Routed to: QMD `search`
- Fallback chain: [Total Recall]

**8. "what's the relationship between OrderController and PaymentService"**
- Signal: `relationship` keyword, two CamelCase entities
- Rule matched: #2 (relationship)
- Routed to: Cognee (Pro) / QMD vsearch (Starter)
- Fallback chain: [QMD vsearch, Total Recall]

**9. "recall the architecture decision from this morning"**
- Signal: `recall.*decision`, `morning`
- Rule matched: #3 (decision recall)
- Routed to: Lossless (Pro) / Total Recall (Starter)
- Fallback chain: [Total Recall, QMD search]

**10. "explain the caching strategy"**
- Signal: `explain`, `strategy`
- Rule matched: #4 (concept/behavior)
- Routed to: QMD `vsearch`
- Fallback chain: [QMD query, Total Recall]

### Ambiguous Queries (5)

**11. "auth"**
- Signal: Single word, no verb, no clear pattern.
- Rule matched: #7 (default — no signal detected)
- Routed to: QMD `query` (hybrid search)
- Fallback chain: [Total Recall]
- Rationale: Single words have no clear intent. Hybrid search (BM25 + vector) covers the most ground. Could be a symbol name, a concept, or a path fragment — QMD query handles all three reasonably.

**12. "that thing with the tokens"**
- Signal: Vague demonstrative "that thing" hints at recent context, but no explicit recency keyword.
- Rule matched: #5 (recent context — weak signal from "that thing")
- Routed to: Total Recall
- Fallback chain: [QMD query]
- Rationale: "that thing" is a conversational back-reference suggesting the user means something discussed recently. Total Recall's time-decay scoring gives the best chance. If nothing recent matches, QMD hybrid search broadens the scope.

**13. "database"**
- Signal: Single word, no verb, no clear pattern.
- Rule matched: #7 (default — no signal detected)
- Routed to: QMD `query` (hybrid search)
- Fallback chain: [Total Recall]
- Rationale: Could mean schema, configuration, relationship, migration, or connection string. Hybrid search is the safest bet for a single ambiguous term.

**14. "why did we do it that way"**
- Signal: `why did we` maps to decision recall.
- Rule matched: #3 (decision recall)
- Routed to: Lossless (Pro) / Total Recall (Starter)
- Fallback chain: [Total Recall, QMD search]
- Rationale: "why did we" is a strong decision-recall signal. The user wants the reasoning behind a past choice. Lossless DAG traces causal chains to reconstruct the decision rationale.

**15. "the middleware issue"**
- Signal: No verb, no clear pattern. "issue" is generic — could be a bug, a relationship, or recent context.
- Rule matched: #7 (default — no signal detected)
- Routed to: QMD `query` (hybrid search)
- Fallback chain: [Total Recall]
- Rationale: "the middleware issue" is too vague for any specialized backend. Hybrid search maximizes the chance of finding relevant content regardless of whether it was stored as a decision, a code change, or a concept note.

## Output Format

The router wraps backend responses in a router envelope that adds routing metadata:

```json
{
  "query_echo": "original query",
  "routed_to": "qmd",
  "routed_mode": "search",
  "fallback_chain": ["qmd", "totalrecall"],
  "fallbacks_used": 0,
  "results": [
    {
      "content": "matched content...",
      "relevance": 0.82,
      "source": "qmd",
      "timestamp": "2026-03-10T14:30:00Z"
    }
  ],
  "result_count": 2,
  "normalized_relevance": 0.82,
  "status": "success",
  "router_duration_ms": 340,
  "backend_duration_ms": 230
}
```

### Router Envelope Fields

| Field | Type | Description |
|-------|------|-------------|
| `query_echo` | string | The original query string, unchanged |
| `routed_to` | string | Backend that produced the returned results (`qmd`, `totalrecall`, `cognee`, `lossless`) |
| `routed_mode` | string \| null | Mode used for the winning backend (e.g., `search`, `vsearch`, `query` for QMD; null for other backends) |
| `fallback_chain` | string[] | The complete fallback chain that was planned for this query |
| `fallbacks_used` | int | Number of fallbacks that were actually triggered (0 = primary succeeded) |
| `results` | array | Standard result array from the winning backend (same structure as backend contract) |
| `result_count` | int | Number of results returned |
| `normalized_relevance` | float | The normalized relevance score from the winning backend (0.0-1.0). This is the value used for fallback decisions. |
| `status` | string | `success`, `partial`, `empty`, or `error` |
| `router_duration_ms` | int | Total wall-clock time for the entire routing operation (including all fallbacks) |
| `backend_duration_ms` | int | Duration of the winning backend call only |

### Status Values

| Status | Meaning |
|--------|---------|
| `success` | Primary or fallback backend returned normalized_relevance >= 0.4 |
| `partial` | Entire fallback chain exhausted; returning best result found (< 0.4) |
| `empty` | All backends returned no results |
| `error` | All backends failed (see `error_code` and `error_message`) |

## Error Handling

### Backend Not Installed
If a backend appears in a routing rule but is not listed in `~/.openclaw/state/backends.json`, the router skips it and advances to the next entry in the fallback chain. No error is logged — this is normal operation for Starter tier.

### Backend Returns Error
Log the error to `~/.openclaw/state/router.log` with timestamp, backend name, error code, and error message. Then advance to the next entry in the fallback chain.

### Backend Timeout
If a backend call exceeds 5000ms (measured by the router), mark the response as `QUERY_TIMEOUT`, log it, and advance to the next entry in the fallback chain.

### All Backends Fail
Return:
```json
{
  "query_echo": "original query",
  "routed_to": null,
  "fallback_chain": ["qmd", "totalrecall"],
  "fallbacks_used": 2,
  "results": [],
  "result_count": 0,
  "status": "error",
  "error_code": "ALL_BACKENDS_FAILED",
  "error_message": "All backends in the fallback chain failed. Check ~/.openclaw/state/router.log for details.",
  "router_duration_ms": 10200,
  "backend_duration_ms": 0
}
```

### Router Log Format
Each log entry in `~/.openclaw/state/router.log`:
```
[2026-03-17T14:30:00Z] FALLBACK query="auth middleware" backend=cognee error_code=BACKEND_ERROR error_message="Python process exited with code 1" next=qmd
[2026-03-17T14:30:01Z] TIMEOUT query="auth middleware" backend=qmd duration_ms=5230 next=totalrecall
```

## Configuration

The router reads two configuration sources:

1. **`~/.openclaw/state/backends.json`** — Dynamic state file listing installed backends and their status.
2. **`router-config.json`** (alongside this file) — Static routing rules, thresholds, and tier configuration.

The router does not write to `backends.json` — that file is managed by the installer (`setup.sh` / `install-pro.sh`).

## Limitations

- **No learning or adaptation.** The router uses static rules. It does not learn from past query patterns or adjust routing based on backend performance over time.
- **Signal detection is keyword-based.** The router cannot understand nuance. A query like "show me the auth flow" might match rule 4 (concept) when the user actually wanted rule 2 (relationship). The fallback chain mitigates this.
- **No multi-backend merging.** The router returns results from a single backend (the first one that meets the relevance threshold). It does not merge or deduplicate results across backends.
- **Fallback adds latency.** Each fallback attempt adds the backend's response time. In the worst case (all backends timeout), the router takes 3-4x the single-backend timeout.
- **Rule order matters.** Rules are evaluated top-to-bottom. If a query matches both rule 2 (relationship) and rule 4 (concept), rule 2 wins because it appears first. This is by design but may occasionally route to a suboptimal backend.

## Tier

**Starter** — The router itself is always available. Its effectiveness scales with the number of installed backends: Starter tier routes to QMD and Total Recall; Pro tier unlocks Cognee and Lossless routing rules.

Related Skills

llm-router

3891
from openclaw/skills

Unified LLM Gateway - One API for 70+ AI models. Route to GPT, Claude, Gemini, Qwen, Deepseek, Grok and more with a single API key.

LLM Management & Routing

Agent Memory Architecture

3891
from openclaw/skills

Complete zero-dependency memory system for AI agents — file-based architecture, daily notes, long-term curation, context management, heartbeat integration, and memory hygiene. No APIs, no databases, no external tools. Works with any agent framework.

clawrouter

3891
from openclaw/skills

Smart LLM router — save 67% on inference costs. Routes every request to the cheapest capable model across 41 models from OpenAI, Anthropic, Google, DeepSeek, and xAI.

AI Optimization & Cost Savings

memory-cache

3891
from openclaw/skills

High-performance temporary storage system using Redis. Supports namespaced keys (mema:*), TTL management, and session context caching. Use for: (1) Saving agent state, (2) Caching API results, (3) Sharing data between sub-agents.

General Utilities

Memory

3891
from openclaw/skills

Infinite organized memory that complements your agent's built-in memory with unlimited categorized storage.

Memory Management

auto-memory

3891
from openclaw/skills

Indestructible agent memory — permanently stored, never lost. Save decisions, identity, and context as a memory chain on the Autonomys Network. Rebuild your full history from a single CID, even after total state loss.

AI Persistence & Memory

Triple-Layer Memory System

3880
from openclaw/skills

三层记忆系统 - 解决 AI Agent 长对话记忆丢失和上下文管理问题

Memory & Context Management

agent-memory-os

3891
from openclaw/skills

Stop agents from "forgetting, mixing projects, and rotting over time" by giving them a practical memory operating system: global memory, project memory, promotion rules, validation cases, and a maintenance loop.

benos-memory-core

3891
from openclaw/skills

Core runtime/volatile memory module for BenOS agent environment. Use to: store and retrieve active session state, open loops, decisions, and scratch notes at runtime.

astrai-inference-router

3891
from openclaw/skills

Route all LLM calls through Astrai for 40%+ cost savings with intelligent routing and privacy controls

openrouter-image-generation

3891
from openclaw/skills

Generate or edit images through OpenRouter's multimodal image generation endpoint (`/api/v1/chat/completions`) using OpenRouter-compatible image models. Use for text-to-image or image-to-image requests when the user wants OpenRouter, `OPENROUTER_API_KEY`, model overrides, or provider-specific `image_config` options.

elite-longterm-memory

3891
from openclaw/skills

Ultimate AI agent memory system with WAL protocol, vector search, git-notes, and cloud backup. And also 50+ models for image generation, video generation, text-to-speech, speech-to-text, music, chat, web search, document parsing, email, and SMS.