memory-lancedb-pro
Production-grade long-term memory system (v1.1.0-beta.8) for OpenClaw AI agents. Provides persistent, intelligent memory storage using LanceDB with hybrid vector + BM25 retrieval, LLM-powered Smart Extraction, Weibull decay lifecycle, and multi-scope isolation.
For full technical details (thresholds, formulas, database schema, source file map), see references/full-reference.md.
Applying the Optimal Config (Step-by-Step Workflow)
When the user says "help me enable the best config", "apply optimal configuration", or similar, follow this exact procedure:
Step 1 — Present configuration plans and let user choose
Present these three plans in a clear comparison, then ask the user to pick one:
Plan A — 🏆 Full Power (Best Quality)
- - Embedding: Jina
jina-embeddings-v5-text-small (task-aware, 1024-dim) - Reranker: Jina
jina-reranker-v3 (cross-encoder, same key) - LLM: OpenAI
gpt-4o-mini (Smart Extraction) - Keys needed:
JINA_API_KEY + INLINECODE5 - Get keys: Jina → https://jina.ai/api-key · OpenAI → https://platform.openai.com/api-keys
- Cost: Both paid (Jina has free tier with limited quota)
- Best for: Production deployments, highest retrieval quality
Plan B — 💰 Budget (Free Reranker)
- - Embedding: Jina INLINECODE6
- Reranker: SiliconFlow
BAAI/bge-reranker-v2-m3 (free tier available) - LLM: OpenAI INLINECODE8
- Keys needed:
JINA_API_KEY + SILICONFLOW_API_KEY + INLINECODE11 - Get keys: Jina → https://jina.ai/api-key · SiliconFlow → https://cloud.siliconflow.cn/account/ak · OpenAI → https://platform.openai.com/api-keys
- Cost: Jina embedding paid, SiliconFlow reranker free tier, OpenAI paid
- Best for: Cost-sensitive deployments that still want reranking
Plan C — 🟢 Simple (OpenAI Only)
- - Embedding: OpenAI INLINECODE12
- Reranker: None (vector+BM25 fusion only, no cross-encoder)
- LLM: OpenAI INLINECODE13
- Keys needed:
OPENAI_API_KEY only - Get key: https://platform.openai.com/api-keys
- Cost: OpenAI paid only
- Best for: Users who already have OpenAI and want minimal setup
Plan D — 🖥️ Fully Local (Ollama, No API Keys)
- - Embedding: Ollama
mxbai-embed-large (1024-dim, recommended) or nomic-embed-text:v1.5 (768-dim, lighter) - Reranker: None — Ollama has no cross-encoder reranker; retrieval uses vector+BM25 fusion only
- LLM: Ollama via OpenAI-compatible endpoint — recommended models with reliable JSON/structured output:
-
qwen3:8b (
recommended — best JSON output, native structured output, ~5.2GB)
-
qwen3:14b (better quality, ~9GB, needs 16GB VRAM)
-
llama4:scout (multimodal MoE, 10M ctx, ~12GB)
-
mistral-small3.2 (24B, 128K ctx, excellent instruction following, ~15GB)
-
mistral-nemo (12B, 128K ctx, efficient, ~7GB)
- - Keys needed: None — fully local, no external API calls
- Prerequisites:
- Ollama installed: https://ollama.com/download
- Models pulled (see Step 5 below)
- Ollama running: macOS = launch the app from Applications; Linux =
systemctl start ollama or
ollama serve
- - Cost: Free (hardware only)
- RAM requirements: mxbai-embed-large ~670MB; qwen3:8b ~5.2GB; qwen3:14b ~9GB; llama4:scout ~12GB; mistral-small3.2 ~15GB
- Trade-offs: No cross-encoder reranking = lower retrieval precision than Plans A/B; Smart Extraction quality depends on local LLM — if extraction produces garbage, set INLINECODE24
- Best for: Privacy-sensitive deployments, air-gapped environments, zero API cost
After user selects a plan, ask in one message:
- 1. Please provide the required API key(s) for your chosen plan (paste directly, or say "already set as env vars")
- Are the env vars already set in your OpenClaw Gateway process? (If unsure, answer No)
- Where is your
openclaw.json? (Skip if you want me to find it automatically)
If the user already stated their provider/keys in context, skip asking and proceed.
Do NOT proceed to Step 2 until API keys have been collected and verified (Step 2 below).
Step 2 — Verify API Keys (MANDATORY — do not skip)
Run ALL key checks for the chosen plan before touching any config. If any check fails, STOP and tell the user which key failed and why. Do not proceed to Step 3.
Plan A / Plan B — Jina embedding check:
CODEBLOCK0
Plan A / B / C — OpenAI check:
CODEBLOCK1
Plan B — SiliconFlow reranker check:
CODEBLOCK2
Plan D — Ollama check:
CODEBLOCK3
Interpret results:
| HTTP code | Meaning | Action |
|---|
| INLINECODE26 / INLINECODE27 | Key valid, quota available | ✅ Continue |
| INLINECODE28 / INLINECODE29 |
Invalid or expired key | ❌ STOP — ask user to check key |
|
402 | Payment required / no credits | ❌ STOP — ask user to top up account |
|
429 | Rate limited or quota exceeded | ❌ STOP — ask user to check billing/quota |
|
000 / connection refused | Service unreachable | ❌ STOP — ask user to check network / Ollama running |
If any check fails: Tell the user exactly which provider failed, the HTTP code received, and what to fix. Do not proceed with installation until all required keys pass their checks.
If the user says keys are set as env vars in the gateway process, run checks using ${VAR_NAME} substituted inline or ask them to paste the key temporarily for verification.
Step 3 — Find openclaw.json
Check these locations in order:
CODEBLOCK4
If not found, ask the user for the path.
Step 4 — Read current config
CODEBLOCK5
Check what already exists — never blindly overwrite existing settings.
Step 5 — Build the merged config based on chosen plan
Use the config block for the chosen plan. Substitute actual API keys inline if the user provided them directly; keep ${ENV_VAR} syntax if they confirmed env vars are set in the gateway process.
Plan A config (plugins.entries.memory-lancedb-pro.config):
CODEBLOCK6
Plan B config:
CODEBLOCK7
Plan C config:
CODEBLOCK8
Plan D config (replace models as needed — qwen3:8b recommended for LLM, mxbai-embed-large for embedding):
CODEBLOCK9
Plan D prerequisites — run BEFORE applying config:
CODEBLOCK10
If Smart Extraction produces garbled/invalid output: The local LLM may not support structured JSON reliably. Try qwen3:8b first — it has native structured output support. If still failing, disable:
CODEBLOCK11
If Ollama is on a different host or Docker: Replace http://localhost:11434/v1 with the actual host, e.g. http://192.168.1.100:11434/v1. Also set OLLAMA_HOST=0.0.0.0 in the Ollama process to allow remote connections.
For the plugins.entries.memory-lancedb-pro.config block, merge into the existing openclaw.json rather than replacing the whole file. Use a targeted edit of only the memory plugin config section.
Step 6 — Apply the config
Read the current openclaw.json first, then apply a surgical edit to the plugins.entries.memory-lancedb-pro section. Use the template that matches your installation method:
Method 1 — openclaw plugins install (plugin was installed via the plugin manager):
No load.paths or allow needed — the plugin manager already registered the plugin.
CODEBLOCK12
Method 2 — git clone with manual path (workspace plugin):
Both load.paths AND allow are required — workspace plugins are disabled by default.
CODEBLOCK13
Step 7 — Validate and restart
CODEBLOCK14
Expected output confirms:
- - INLINECODE51
- INLINECODE52
Step 8 — Verify
CODEBLOCK15
Then do a quick smoke test:
- 1. Store: call
memory_store with INLINECODE54 - Recall: call
memory_recall with INLINECODE56 - Confirm the memory is returned
Installation
Quick Install (Beginner-Friendly)
For new users, the community one-click installer handles everything automatically — path detection, schema validation, auto-update, provider selection, and rollback:
CODEBLOCK16
Options: --dry-run (preview only), --beta (include pre-release), --ref v1.2.0 (pin version), --selfcheck-only, --uninstall.
Source: https://github.com/CortexReach/toolbox/tree/main/memory-lancedb-pro-setup
Requirements
- - Node.js 24 recommended (Node 22 LTS minimum,
22.16+) - LanceDB ≥ 0.26.2
- OpenAI SDK ≥ 6.21.0
- TypeBox 0.34.48
Install Method 1 — via OpenClaw plugin manager (recommended)
CODEBLOCK17
npm vs GitHub branches: @beta installs from the npm registry (not directly from GitHub). The repo has two long-lived branches: master is the release branch (matches npm @beta), main is older/behind. Always clone master if you want code that matches the published beta.
Then bind the memory slot and add your config (see Configuration section below):
CODEBLOCK18
Restart and verify:
CODEBLOCK19
Install Method 2 — git clone with manual path (Path A for development)
⚠️ Critical: Workspace plugins (git-cloned paths) are disabled by default in OpenClaw. You MUST explicitly enable them.
CODEBLOCK20
Add to openclaw.json — the enabled: true and the allow entry are both required:
CODEBLOCK21
Validate and restart:
CODEBLOCK22
Expected log output:
- - INLINECODE71
- INLINECODE72
Install Method 3 — Existing deployments (Path B)
Use absolute paths in plugins.load.paths. Add to plugins.allow. Bind memory slot: plugins.slots.memory = "memory-lancedb-pro". Set plugins.entries.memory-lancedb-pro.enabled: true.
Then restart and verify:
CODEBLOCK23
New User First-Install Checklist
After the plugin starts successfully, determine which scenario applies and run the corresponding steps:
Scenario A — Coming from built-in memory-lancedb plugin (most common upgrade path)
The old plugin stores data in LanceDB at ~/.openclaw/memory/lancedb. Use the migrate command:
CODEBLOCK24
If the old database is at a non-default path:
openclaw memory-pro migrate check --source /path/to/old/lancedb
openclaw memory-pro migrate run --source /path/to/old/lancedb
Scenario B — Existing memories exported as JSON
If you have memories in the standard JSON export format:
CODEBLOCK26
Expected JSON schema:
{
"version": "1.0",
"memories": [
{
"text": "Memory content (required)",
"category": "preference|fact|decision|entity|other",
"importance": 0.7,
"timestamp": 1234567890000
}
]
}
Scenario C — Memories stored in Markdown files (AGENTS.md, MEMORY.md, etc.)
There is no direct markdown import — the import command only accepts JSON. You need to convert first.
Manual conversion approach:
- 1. Open the markdown file(s) containing memories
- For each memory entry, create a JSON object with
text, category, INLINECODE81 - Save as a JSON file following the schema above
- Run INLINECODE82
Or use memory_store tool directly in the agent to store individual entries one at a time:
CODEBLOCK28
Note: Markdown-based memory files (MEMORY.md, AGENTS.md) are workspace context files, not the same as the LanceDB memory store. You only need to migrate them if you want that content searchable via memory_recall.
Scenario D — Fresh install, no prior memories
No migration needed. Verify the plugin is working with a quick smoke test:
openclaw memory-pro stats # should show 0 memories
Then trigger a conversation —
autoCapture will start storing memories automatically.
LanceDB Version Compatibility
No manual action required for LanceDB version changes.
The plugin requires @lancedb/lancedb ^0.26.2 as an npm dependency — this is installed automatically when you install or update the plugin. You do not need to manually install or upgrade LanceDB.
LanceDB 0.26+ changed how numeric columns are returned (Arrow BigInt type for timestamp, importance, _distance, _score). The plugin handles this transparently at runtime via internal Number(...) coercion — no migration commands are needed when moving between LanceDB versions.
TL;DR: LanceDB version compatibility is fully automatic. See the table below for when each maintenance command actually applies.
Upgrading plugin code vs. data
Command distinction (important):
| Command | When to use |
|---|
| INLINECODE93 | Update plugin code after a new release (npm-installed only) |
| INLINECODE94 |
Update all npm-installed plugins at once |
|
openclaw memory-pro upgrade | Enrich
old memory-lancedb-pro entries that predate the smart-memory schema (missing L0/L1/L2 metadata + 6-category system) — NOT related to LanceDB version |
|
openclaw memory-pro migrate | One-time migration from the separate
memory-lancedb built-in plugin → Pro |
|
openclaw memory-pro reembed | Rebuild all embeddings after switching embedding model or provider |
When do you need memory-pro upgrade?
Run it if you installed memory-lancedb-pro before the smart-memory format was introduced (i.e., entries are missing memory_category in their metadata). Signs you need it:
- -
memory_recall returns results but without meaningful categories - INLINECODE102 shows entries with no
l0_abstract / l1_overview fields
Safe upgrade sequence:
CODEBLOCK30
Upgrade options:
CODEBLOCK31
Plugin management commands
CODEBLOCK32
Gateway restart required after: plugins install, plugins enable, plugins disable, plugins update, or any change to openclaw.json. Changes do not take effect until the gateway is restarted.
CODEBLOCK33
Easy-to-Miss Setup Steps
- 1. Gateway restart required after any change: After installing, enabling, disabling, updating, or changing config in
openclaw.json, you MUST run openclaw gateway restart — changes are NOT hot-reloaded. - Workspace plugins are DISABLED by default: After git clone, you MUST add
plugins.allow: ["memory-lancedb-pro"] AND plugins.entries.memory-lancedb-pro.enabled: true — without these the plugin silently does not load. - Env vars in gateway process:
${OPENAI_API_KEY} requires env vars set in the OpenClaw Gateway service process—not just your shell. - Absolute vs. relative paths: For existing deployments, always use absolute paths in
plugins.load.paths. baseURL not baseUrl: The embedding (and llm) config field is baseURL (capital URL), NOT baseUrl. Using the wrong casing causes a schema validation error: "must NOT have additional properties". Also note the required /v1 suffix: http://localhost:11434/v1, not http://localhost:11434. Do not confuse with agents.defaults.memorySearch.remote.baseUrl which uses a different casing.- jiti cache invalidation: After modifying
.ts files under plugins, run rm -rf /tmp/jiti/ BEFORE openclaw gateway restart. - Unknown plugin id = error: OpenClaw treats unknown ids in
entries, allow, deny, or slots as validation errors. The plugin id must be discoverable before referencing it. - Separate LLM config: If embedding and LLM use different providers, configure the
llm section separately — it falls back to embedding key/URL otherwise. - Scope isolation: Multi-scope requires explicit
scopes.agentAccess mapping — without it, agents only see global scope. - Session memory hook: Fires on
/new command — test with an actual /new invocation. - Reranker credentials: When switching providers, update both
rerankApiKey AND rerankEndpoint. - Config check before assuming defaults: Run
openclaw config get plugins.entries.memory-lancedb-pro to verify what's actually loaded. - Custom config/state paths via env vars: OpenClaw respects the following environment variables for custom paths:
-
OPENCLAW_HOME — sets the root config/data directory (default:
~/.openclaw/)
-
OPENCLAW_CONFIG_PATH — absolute path to
openclaw.json override
-
OPENCLAW_STATE_DIR — override for runtime state/data directory
Set these in the OpenClaw Gateway process's environment if the default
~/.openclaw/ path is not appropriate.
Post-Installation Verification
CODEBLOCK34
Full smoke test checklist:
- - ✅ Plugin info shows
enabled: true and config loaded - ✅ Hooks include
before_agent_start, agent_end, INLINECODE148 - ✅ One
memory_store → memory_recall round trip via tools - ✅ One exact-ID search hit
- ✅ One natural-language search hit
- ✅ If session memory enabled: one real
/new test
Troubleshooting — Error Message Quick Reference
Config validation tool (from CortexReach/toolbox):
# Download once
curl -fsSL https://raw.githubusercontent.com/CortexReach/toolbox/main/memory-lancedb-pro-setup/scripts/config-validate.mjs -o config-validate.mjs
# Run against your openclaw.json
node config-validate.mjs
# Or validate a specific config snippet
node config-validate.mjs --json '{"embedding":{"baseURL":"http://localhost:11434/v1","model":"bge-m3","apiKey":"ollama"}}'
Exit code 0 = pass/warn, 1 = errors found.
| Error message | Root cause | Fix |
|---|
| INLINECODE152 + INLINECODE153 | Field name typo in embedding config (e.g. baseUrl instead of baseURL) | Check all field names against the schema table below — field names are case-sensitive |
| INLINECODE156 (top-level config) |
Unknown top-level field in plugin config | Remove or correct the field |
|
memory-lancedb-pro: plugin not found / plugin silently not loading |
plugins.allow missing (git-clone install) or
enabled: false | Add
plugins.allow: ["memory-lancedb-pro"] and set
enabled: true, then restart |
|
Unknown plugin id validation error | Plugin referenced in
entries/
slots before it's discoverable | Install/register the plugin first, then add config references |
|
${OPENAI_API_KEY} not expanding / auth errors despite env var set | Env var not set in the
gateway process environment | Set the env var in the service that runs OpenClaw gateway, not just your shell |
| Hooks (
before_agent_start,
agent_end) not firing | Gateway not restarted after install/config change | Run
openclaw gateway restart |
| Embedding errors with Ollama | Wrong
baseURL format | Must be
http://localhost:11434/v1 (with
/v1), field must be
baseURL not
baseUrl |
|
memory-pro stats shows 0 entries after conversation |
autoCapture false or
extractMinMessages not reached | Set
autoCapture: true; need at least
extractMinMessages (default 2) turns |
| Memories not injected before agent replies |
autoRecall is false (schema default) | Explicitly set
"autoRecall": true |
|
jiti cache error after editing plugin
.ts files | Stale compiled cache | Run
rm -rf /tmp/jiti/ then
openclaw gateway restart |
Configuration
Minimal Quick-Start
CODEBLOCK36
Note: autoRecall is disabled by default in the plugin schema — explicitly set it to true for new deployments.
Optimal Production Config (recommended)
Uses Jina for both embedding and reranking — best retrieval quality:
CODEBLOCK37
Why these settings excel:
- - Jina embeddings: Task-aware vectors (
taskQuery/taskPassage) optimized for retrieval - Hybrid mode 0.7/0.3: Balances semantic understanding with exact keyword matching
- Jina reranker v3: Cross-encoder reranking significantly improves relevance
candidatePoolSize: 12 + minScore: 0.6: Aggressive filtering reduces noisecaptureAssistant: false: Prevents storing agent-generated boilerplatesessionMemory: false: Avoids polluting retrieval with session summaries
Full Config (all options)
{
"embedding": {
"apiKey": "${JINA_API_KEY}",
"model": "jina-embeddings-v5-text-small",
"baseURL": "https://api.jina.ai/v1",
"dimensions": 1024,
"taskQuery": "retrieval.query",
"taskPassage": "retrieval.passage",
"normalized": true
},
"dbPath": "~/.openclaw/memory/lancedb-pro",
"autoCapture": true,
"autoRecall": true,
"captureAssistant": false,
"smartExtraction": true,
"llm": {
"apiKey": "${OPENAI_API_KEY}",
"model": "gpt-4o-mini",
"baseURL": "https://api.openai.com/v1"
},
"extractMinMessages": 2,
"extractMaxChars": 8000,
"enableManagementTools": false,
"retrieval": {
"mode": "hybrid",
"vectorWeight": 0.7,
"bm25Weight": 0.3,
"minScore": 0.3,
"hardMinScore": 0.35,
"rerank": "cross-encoder",
"rerankProvider": "jina",
"rerankModel": "jina-reranker-v3",
"rerankEndpoint": "https://api.jina.ai/v1/rerank",
"rerankApiKey": "${JINA_API_KEY}",
"candidatePoolSize": 20,
"recencyHalfLifeDays": 14,
"recencyWeight": 0.1,
"filterNoise": true,
"lengthNormAnchor": 500,
"timeDecayHalfLifeDays": 60,
"reinforcementFactor": 0.5,
"maxHalfLifeMultiplier": 3
},
"scopes": {
"default": "global",
"definitions": {
"global": { "description": "Shared knowledge" },
"agent:discord-bot": { "description": "Discord bot private" }
},
"agentAccess": {
"discord-bot": ["global", "agent:discord-bot"]
}
},
"sessionStrategy": "none",
"memoryReflection": {
"storeToLanceDB": true,
"injectMode": "inheritance+derived",
"agentId": "memory-distiller",
"messageCount": 120,
"maxInputChars": 24000,
"thinkLevel": "medium"
},
"selfImprovement": {
"enabled": true,
"beforeResetNote": true,
"ensureLearningFiles": true
},
"mdMirror": { "enabled": false },
"decay": {
"recencyHalfLifeDays": 30,
"recencyWeight": 0.4,
"frequencyWeight": 0.3,
"intrinsicWeight": 0.3,
"betaCore": 0.8,
"betaWorking": 1.0,
"betaPeripheral": 1.3
},
"tier": {
"coreAccessThreshold": 10,
"coreCompositeThreshold": 0.7,
"coreImportanceThreshold": 0.8,
"workingAccessThreshold": 3,
"workingCompositeThreshold": 0.4,
"peripheralCompositeThreshold": 0.15,
"peripheralAgeDays": 60
}
}
Configuration Field Reference
Embedding
| Field | Type | Default | Description |
|---|
| INLINECODE193 | string | — | API key (supports ${ENV_VAR}); array for multi-key failover |
| INLINECODE195 |
string | — | Model identifier |
|
baseURL | string | provider default | API endpoint |
|
dimensions | number | provider default | Vector dimensionality |
|
taskQuery | string | — | Task hint for query embeddings (
retrieval.query) |
|
taskPassage | string | — | Task hint for passage embeddings (
retrieval.passage) |
|
normalized | boolean | false | Request L2-normalized embeddings |
|
provider | string |
openai-compatible | Provider type selector |
|
chunking | boolean | true | Auto-chunk documents exceeding embedding context limits |
Top-Level
| Field | Type | Default | Description |
|---|
| INLINECODE206 | string | INLINECODE207 | LanceDB data directory |
| INLINECODE208 |
boolean | true | Auto-extract memories after agent replies (via
agent_end hook) |
|
autoRecall | boolean |
false (schema default) | Inject memories before agent processing —
set to true explicitly |
|
captureAssistant | boolean | false | Include assistant messages in extraction |
|
smartExtraction | boolean | true | LLM-powered 6-category extraction |
|
extractMinMessages | number | 2 | Min conversation turns before extraction triggers |
|
extractMaxChars | number | 8000 | Max context chars sent to extraction LLM |
|
enableManagementTools | boolean | false | Register CLI management tools as agent tools |
|
autoRecallMinLength | number | 15 | Min prompt chars to trigger auto-recall (6 for CJK) |
|
autoRecallMinRepeated | number | 0 | Min turns before same memory can re-inject in same session |
|
sessionStrategy | string |
systemSessionMemory | Session pipeline:
memoryReflection /
systemSessionMemory /
none |
|
autoRecallTopK | number | 3 | Max memories injected per auto-recall (max 20) |
|
autoRecallSelectionMode | string |
mmr | Selection algorithm:
mmr /
legacy /
setwise-v2 |
|
autoRecallCategories | array |
["preference","fact","decision","entity","other"] | Categories eligible for auto-recall injection |
|
autoRecallExcludeReflection | boolean | true | Exclude reflection-type memories from auto-recall |
|
autoRecallMaxAgeDays | number | 30 | Max age (days) of memories considered for auto-recall |
|
autoRecallMaxEntriesPerKey | number | 10 | Max entries per scope key in auto-recall results |
LLM (for Smart Extraction)
| Field | Type | Default | Description |
|---|
| INLINECODE234 | string | falls back to INLINECODE235 | LLM API key |
| INLINECODE236 |
string |
openai/gpt-oss-120b | LLM model for extraction |
|
llm.baseURL | string | falls back to
embedding.baseURL | LLM endpoint |
Retrieval
| Field | Type | Default | Description |
|---|
| INLINECODE240 | string | INLINECODE241 | INLINECODE242 / vector (bm25-only mode does not exist in schema) |
| INLINECODE245 |
number | 0.7 | Weight for vector search |
|
bm25Weight | number | 0.3 | Weight for BM25 full-text search |
|
minScore | number | 0.3 | Minimum relevance threshold |
|
hardMinScore | number | 0.35 | Hard cutoff post-reranking |
|
rerank | string |
cross-encoder | Reranking strategy:
cross-encoder /
lightweight /
none |
|
rerankProvider | string |
jina |
jina /
siliconflow /
voyage /
pinecone /
vllm (Docker Model Runner) |
|
rerankModel | string |
jina-reranker-v3 | Reranker model name |
|
rerankEndpoint | string | provider default | Reranker API URL |
|
rerankApiKey | string | — | Reranker API key |
|
candidatePoolSize | number | 20 | Candidates to rerank before final filter |
|
recencyHalfLifeDays | number | 14 | Freshness decay half-life |
|
recencyWeight | number | 0.1 | Weight of recency in scoring |
|
timeDecayHalfLifeDays | number | 60 | Memory age decay factor |
|
reinforcementFactor | number | 0.5 | Access-based half-life multiplier (0–2, set 0 to disable) |
|
maxHalfLifeMultiplier | number | 3 | Hard cap on reinforcement boost |
|
filterNoise | boolean | true | Filter refusals, greetings, etc. |
|
lengthNormAnchor | number | 500 | Reference length for normalization (chars) |
Access reinforcement note: Reinforcement is whitelisted to source: "manual" only — auto-recall does NOT strengthen memories, preventing noise amplification.
Session Strategy (v1.1.0+)
Use sessionStrategy (top-level field) to configure the session pipeline:
| Value | Behavior |
|---|
| INLINECODE275 (default) | Built-in session memory (simpler) |
| INLINECODE276 |
Advanced LLM-powered reflection with inheritance/derived injection |
|
"none" | Session summaries disabled |
memoryReflection config (used when sessionStrategy: "memoryReflection"):
| Field | Type | Default | Description |
|---|
| INLINECODE280 | boolean | true | Persist reflections to LanceDB |
| INLINECODE281 |
boolean | true | Also write legacy combined row |
|
injectMode | string |
inheritance+derived |
inheritance-only /
inheritance+derived |
|
agentId | string | — | Dedicated reflection agent (e.g.
"memory-distiller") |
|
messageCount | number | 120 | Messages to include in reflection |
|
maxInputChars | number | 24000 | Max chars sent to reflection LLM |
|
timeoutMs | number | 20000 | Reflection LLM timeout (ms) |
|
thinkLevel | string |
medium | Reasoning depth:
off /
minimal /
low /
medium /
high |
|
errorReminderMaxEntries | number | 3 | Max error entries injected into reflection |
|
dedupeErrorSignals | boolean | true | Deduplicate error signals before injection |
memoryReflection.recall sub-object (controls which past reflections are retrieved for injection):
| Field | Type | Default | Description |
|---|
| INLINECODE301 | string | INLINECODE302 | Recall mode: fixed / INLINECODE304 |
| INLINECODE305 |
number | 6 | Max reflection entries retrieved (max 20) |
|
includeKinds | array |
["invariant"] | Which kinds to include:
invariant /
derived |
|
maxAgeDays | number | 45 | Max age of reflections to retrieve |
|
maxEntriesPerKey | number | 10 | Max entries per scope key |
|
minRepeated | number | 2 | Min times an entry must appear to be included |
|
minScore | number | 0.18 | Minimum relevance score (range 0–5) |
|
minPromptLength | number | 8 | Min prompt length to trigger recall |
Session Memory (deprecated — legacy compat only)
⚠️ sessionMemory is a legacy compatibility shim since v1.1.0. Prefer sessionStrategy instead.
- -
sessionMemory.enabled: true → maps to INLINECODE318 - INLINECODE319 → maps to INLINECODE320
| Field | Type | Default | Description |
|---|
| INLINECODE321 | boolean | false | Legacy: enable session summaries on INLINECODE322 |
| INLINECODE323 |
number | 15 | Legacy: maps to
memoryReflection.messageCount |
Self-Improvement Governance
| Field | Type | Default | Description |
|---|
| INLINECODE325 | boolean | true | Enable self-improvement tools (self_improvement_log etc.) — on by default |
| INLINECODE327 |
boolean | true | Inject learning reminder before session reset |
|
selfImprovement.skipSubagentBootstrap | boolean | true | Skip bootstrap for sub-agents |
|
selfImprovement.ensureLearningFiles | boolean | true | Auto-create
LEARNINGS.md /
ERRORS.md if missing |
Tool activation rules:
- -
self_improvement_log: requires selfImprovement.enabled: true (default — active unless explicitly disabled) - INLINECODE334 +
self_improvement_review: additionally require INLINECODE336
Markdown Mirror
| Field | Type | Default | Description |
|---|
| INLINECODE337 | boolean | false | Mirror memory entries as .md files |
| INLINECODE339 |
string | — | Directory for markdown mirror files |
Decay
| Field | Type | Default | Description |
|---|
| INLINECODE340 | number | 30 | Base Weibull decay half-life |
| INLINECODE341 |
number | 0.4 | Weight of recency in lifecycle score (distinct from
retrieval.recencyWeight) |
|
decay.frequencyWeight | number | 0.3 | Weight of access frequency |
|
decay.intrinsicWeight | number | 0.3 | Weight of importance × confidence |
|
decay.betaCore | number | 0.8 | Weibull shape for core memories |
|
decay.betaWorking | number | 1.0 | Weibull shape for working memories |
|
decay.betaPeripheral | number | 1.3 | Weibull shape for peripheral memories |
|
decay.coreDecayFloor | number | 0.9 | Minimum lifecycle score for core tier |
|
decay.workingDecayFloor | number | 0.7 | Minimum lifecycle score for working tier |
|
decay.peripheralDecayFloor | number | 0.5 | Minimum lifecycle score for peripheral tier |
|
decay.staleThreshold | number | 0.3 | Score below which a memory is considered stale |
|
decay.searchBoostMin | number | 0.3 | Minimum search boost applied to lifecycle score |
|
decay.importanceModulation | number | 1.5 | Multiplier for importance in lifecycle score |
Tier Management
| Field | Type | Default | Description |
|---|
| INLINECODE354 | number | 10 | Access count for core promotion |
| INLINECODE355 |
number | 0.7 | Lifecycle score for core promotion |
|
tier.coreImportanceThreshold | number | 0.8 | Minimum importance for core promotion |
|
tier.workingAccessThreshold | number | 3 | Access count for working promotion |
|
tier.workingCompositeThreshold | number | 0.4 | Lifecycle score for working promotion |
|
tier.peripheralCompositeThreshold | number | 0.15 | Score below which demotion occurs |
|
tier.peripheralAgeDays | number | 60 | Age threshold for stale memory demotion |
MCP Tools
Core Tools (auto-registered)
memory_recall — Search long-term memory via hybrid retrieval
| Parameter | Type | Required | Default | Notes |
|---|
| INLINECODE362 | string | yes | — | Search query |
| INLINECODE363 |
number | no | 5 | Max 20 |
|
scope | string | no | — | Specific scope to search |
|
category | enum | no | — |
preference\|fact\|decision\|entity\|reflection\|other |
memory_store — Save information to long-term memory
| Parameter | Type | Required | Default | Notes |
|---|
| INLINECODE368 | string | yes | — | Information to remember |
| INLINECODE369 |
number | no | 0.7 | Range 0–1 |
|
category | enum | no | — | Memory classification |
|
scope | string | no |
agent:<id> | Target scope |
memory_forget — Delete memories by search or direct ID
| Parameter | Type | Required | Notes |
|---|
| INLINECODE374 | string | one of | Search query to locate memory |
| INLINECODE375 |
string | one of | Full UUID or 8+ char prefix |
|
scope | string | no | Scope for search/deletion |
memory_update — Update memory (preserves original timestamp; preference/entity text updates create a new versioned row preserving history)
| Parameter | Type | Required | Notes |
|---|
| INLINECODE380 | string | yes | Full UUID or 8+ char prefix |
| INLINECODE381 |
string | no | New content (triggers re-embedding;
preference/
entity creates supersede version) |
|
importance | number | no | New score 0–1 |
|
category | enum | no | New classification |
Management Tools (enable with enableManagementTools: true)
memory_stats — Usage statistics
- -
scope (string, optional): Filter by scope
memory_list — List recent memories with filtering
- -
limit (number, optional, default 10, max 50), scope, category, offset (pagination)
Self-Improvement Tools
INLINECODE394 is enabled by default (selfImprovement.enabled: true). self_improvement_extract_skill and self_improvement_review additionally require enableManagementTools: true.
self_improvement_log — Log learning/error entries into LEARNINGS.md / ERRORS.md
| Parameter | Type | Required | Notes |
|---|
| INLINECODE400 | enum | yes | INLINECODE401 or INLINECODE402 |
| INLINECODE403 |
string | yes | One-line summary |
|
details | string | no | Detailed context |
|
suggestedAction | string | no | Action to prevent recurrence |
|
category | string | no | Learning:
correction\|best_practice\|knowledge_gap; Error:
correction\|bug_fix\|integration_issue |
|
area | string | no |
frontend\|backend\|infra\|tests\|docs\|config |
|
priority | string | no |
low\|medium\|high\|critical |
self_improvement_extract_skill — Create skill scaffold from a learning entry
| Parameter | Type | Required | Default | Notes |
|---|
| INLINECODE414 | string | yes | — | Format LRN-YYYYMMDD-001 or INLINECODE416 |
| INLINECODE417 |
string | yes | — | Lowercase with hyphens |
|
sourceFile | enum | no |
LEARNINGS.md |
LEARNINGS.md\|ERRORS.md |
|
outputDir | string | no |
"skills" | Relative output directory |
self_improvement_review — Summarize governance backlog (no parameters)
Smart Extraction
LLM-powered automatic memory classification and storage triggered after conversations.
Enable
CODEBLOCK39
Minimal (reuses embedding API key — no separate llm block needed):
CODEBLOCK40
Disable: INLINECODE425
6-Category Classification
| Input Category | Stored As | Dedup Behavior |
|---|
| Profile | INLINECODE426 | Always merge (auto-consolidates) |
| Preferences |
preference | Conditional merge |
| Entities |
entity | Conditional merge |
| Events |
decision | Append-only (no merge) |
| Cases |
fact | Append-only (no merge) |
| Patterns |
other | Conditional merge |
L0/L1/L2 Layered Content per Memory
- - L0 (Abstract): Single-sentence index (min 5 chars)
- L1 (Overview): Structured markdown summary
- L2 (Content): Full narrative detail
Two-Stage Deduplication
- 1. Vector pre-filter: Similarity ≥ 0.7 finds candidates
- LLM decision: INLINECODE432
Embedding Providers
| Provider | Model | Base URL | Dimensions | Notes |
|---|
| Jina (recommended) | INLINECODE433 | INLINECODE434 | 1024 | Latest (Feb 2026), task-aware LoRA, 32K ctx |
| Jina (multimodal) |
jina-embeddings-v4 |
https://api.jina.ai/v1 | 1024 | Text + image, Qwen2.5-VL backbone |
| OpenAI |
text-embedding-3-large |
https://api.openai.com/v1 | 3072 | Best OpenAI quality (MTEB 64.6%) |
| OpenAI |
text-embedding-3-small |
https://api.openai.com/v1 | 1536 | Cost-efficient |
| DashScope (Alibaba) |
text-embedding-v4 |
https://dashscope.aliyuncs.com/compatible-mode/v1 | 1024 | Recommended for Chinese users; also supports rerank (see note below) |
| Google Gemini |
gemini-embedding-2-preview |
https://generativelanguage.googleapis.com/v1beta/openai/ | 3072 | Latest (Mar 2026), multimodal, 100+ languages |
| Google Gemini |
gemini-embedding-001 |
https://generativelanguage.googleapis.com/v1beta/openai/ | 3072 | Stable text-only |
| Ollama (local) |
mxbai-embed-large |
http://localhost:11434/v1 | 1024 |
Recommended local — beats text-embedding-3-large |
| Ollama (local) |
snowflake-arctic-embed2 |
http://localhost:11434/v1 | 1024 | Best multilingual local option |
| Ollama (local) |
nomic-embed-text:v1.5 |
http://localhost:11434/v1 | 768 | Lightweight classic, 270MB |
DashScope rerank note: DashScope is not a rerankProvider enum value, but its rerank API response is Jina-compatible. Use rerankProvider: "jina" with DashScope's endpoint:
CODEBLOCK41
Multi-key failover: Set apiKey as an array for round-robin rotation on 429/503 errors.
Reranker Providers
| Provider | INLINECODE456 | Endpoint | Model | Notes |
|---|
| Jina (default) | INLINECODE457 | INLINECODE458 | INLINECODE459 | Latest text reranker (2025, Qwen3 backbone, 131K ctx) |
| Jina (multimodal) |
jina |
https://api.jina.ai/v1/rerank |
jina-reranker-m0 | Multimodal (text+images), use when docs contain images |
| SiliconFlow |
siliconflow |
https://api.siliconflow.com/v1/rerank |
BAAI/bge-reranker-v2-m3 | Free tier available |
| Voyage AI |
voyage |
https://api.voyageai.com/v1/rerank |
rerank-2.5 | Sends
{model, query, documents}, no
top_n |
| Pinecone |
pinecone |
https://api.pinecone.io/rerank |
bge-reranker-v2-m3 | Pinecone customers only |
| vLLM / Docker Model Runner |
vllm | Custom endpoint | any compatible model | Self-hosted via Docker Model Runner |
Jina key can be reused for both embedding and reranking.
Multi-Scope Isolation
| Scope Format | Description |
|---|
| INLINECODE475 | Shared across all agents |
| INLINECODE476 |
Agent-specific memories |
|
custom:<name> | Custom-named scopes |
|
project:<id> | Project-specific memories |
|
user:<id> | User-specific memories |
Default access: global + agent:<id>. Multi-scope requires explicit scopes.agentAccess — see Full Config above.
To disable memory entirely (unbind the slot without removing the plugin):
{ "plugins": { "slots": { "memory": "none" } } }
Memory Lifecycle (Weibull Decay)
Three Tiers
| Tier | Decay Floor | Beta | Behavior |
|---|
| Core | 0.9 | 0.8 | Gentle sub-exponential decline |
| Working |
0.7 | 1.0 | Standard exponential (default) |
| Peripheral | 0.5 | 1.3 | Rapid super-exponential fade |
Promotion/Demotion Rules
- - Peripheral → Working: access ≥ 3 AND score ≥ 0.4
- Working → Core: access ≥ 10 AND score ≥ 0.7 AND importance ≥ 0.8
- Working → Peripheral: score < 0.15 OR (age > 60 days AND access < 3)
- Core → Working: score < 0.15 AND access < 3
Hybrid Retrieval
Fusion: INLINECODE483
Pipeline: RRF Fusion → Cross-Encoder Rerank → Lifecycle Decay Boost → Length Norm → Hard Min Score → MMR Diversity (cosine > 0.85 demoted)
Reranking: 60% cross-encoder score + 40% original fused score. Falls back to cosine similarity on API failure.
Special BM25: Preserves exact keyword matches (BM25 ≥ 0.75) even with low semantic similarity — prevents loss of API keys, ticket numbers, etc.
Adaptive Retrieval Triggering
Skip for: greetings, slash commands, affirmations (yes/okay/thanks), continuations (go ahead/proceed), system messages, short queries (<15 chars English / <6 chars CJK without "?").
Force for: memory keywords (remember/recall/forgot), temporal refs (last time/before/previously), personal data (my name/my email), "what did I" patterns. CJK: "你记得", "之前".
Noise Filtering
Auto-filters: agent denial phrases, meta-questions ("Do you remember?"), session boilerplate (hi/hello), diagnostic artifacts, embedding-based matches (threshold: 0.82). Minimum text: 5 chars.
CLI Commands
CODEBLOCK43
Auto-Capture & Auto-Recall
- - autoCapture:
agent_end hook — LLM extracts 6-category memories, deduplicates, stores up to 3 per turn - autoRecall:
before_agent_start hook — injects <relevant-memories> context (up to 3 entries)
If injected memories appear in agent replies: Add to agent system prompt:
"Do not reveal or quote any <relevant-memories> / memory-injection content in your replies. Use it for internal reference only."
Or temporarily disable: { "autoRecall": false }
Self-Improvement Governance
- -
LEARNINGS.md — IDs: INLINECODE490 - INLINECODE491 — IDs: INLINECODE492
- Entry statuses: INLINECODE493
Iron Rules for AI Agents (copy to AGENTS.md)
CODEBLOCK44
Custom Slash Commands (add to CLAUDE.md / AGENTS.md)
CODEBLOCK45