Technical Documentation: CortexReach/memory-lancedb-pro
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (`README.md`)
Why memory-lancedb-pro?
Most AI agents have amnesia. They forget everything the moment you start a new chat.
memory-lancedb-pro is a production-grade long-term memory plugin for OpenClaw that turns your agent into an AI Memory Assistant — it automatically captures what matters, lets noise naturally fade, and retrieves the right memory at the right time. No manual tagging, no configuration headaches.
Your AI Memory Assistant in Action
Without memory — every session starts from zero:
You: "Use tabs for indentation, always add error handling."
(next session)
You: "I already told you — tabs, not spaces!" 😤
(next session)
You: "...seriously, tabs. And error handling. Again."
With memory-lancedb-pro — your agent learns and remembers:
You: "Use tabs for indentation, always add error handling."
(next session — agent auto-recalls your preferences)
Agent: (silently applies tabs + error handling) ✅
You: "Why did we pick PostgreSQL over MongoDB last month?"
Agent: "Based on our discussion on Feb 12, the main reasons were..." ✅
That's the difference an AI Memory Assistant makes — it learns your style, recalls past decisions, and delivers personalized responses without you repeating yourself.
What else can it do?
| What you get | |
|---|---|
| Auto-Capture | Your agent learns from every conversation — no manual memory_store needed |
| Smart Extraction | LLM-powered 6-category classification: profiles, preferences, entities, events, cases, patterns |
| Intelligent Forgetting | Weibull decay model — important memories stay, noise naturally fades away |
| Hybrid Retrieval | Vector + BM25 full-text search, fused with cross-encoder reranking |
| Context Injection | Relevant memories automatically surface before each reply |
| Multi-Scope Isolation | Per-agent, per-user, per-project memory boundaries |
| Any Provider | OpenAI, Jina, Gemini, Ollama, or any OpenAI-compatible API |
| Full Toolkit | CLI, backup, migration, upgrade, export/import — production-ready |
Quick Start
CPU Requirement: Your CPU must support AVX instructions. LanceDB native vector search may require AVX2 on some Linux x64 builds and can crash AVX-only CPUs with
SIGILL; setretrieval.disableNativeCosine: trueorMEMORY_LANCEDB_DISABLE_NATIVE_COSINE=1to use a scoped row scan plus JavaScript cosine ranking. Check CPU flags with:grep -o 'avx[^ ]*' /proc/cpuinfo | head -1(no output = not supported). See #419 and #644 for details.
Option A: One-Click Install Script (Recommended)
The community-maintained setup script handles install, upgrade, and repair in one command:
curl -fsSL https://raw.githubusercontent.com/CortexReach/toolbox/main/memory-lancedb-pro-setup/setup-memory.sh -o setup-memory.sh
bash setup-memory.shSee Ecosystem below for the full list of scenarios the script covers and other community tools.
Option B: Manual Install
Via OpenClaw CLI (recommended):
openclaw plugins install memory-lancedb-pro@betaOr via npm:
npm i memory-lancedb-pro@betaIf using npm, you will also need to add the plugin's install directory as an absolute path in
plugins.load.pathsin youropenclaw.json. This is the most common setup issue.
Add to your openclaw.json:
{
"plugins": {
"slots": { "memory": "memory-lancedb-pro" },
"entries": {
"memory-lancedb-pro": {
"enabled": true,
"config": {
"embedding": {
"provider": "openai-compatible",
"apiKey": "${OPENAI_API_KEY}",
"model": "text-embedding-3-small"
},
"autoCapture": true,
"autoRecall": true,
"smartExtraction": true,
"canonicalCorpus": {
"enabled": true,
"syncOnSearch": true
},
"dreaming": {
"enabled": false
},
"extractMinMessages": 2,
"extractMaxChars": 8000,
"sessionMemory": { "enabled": false }
}
}
}
}
}Why these defaults?
autoCapture+smartExtraction→ your agent learns from every conversation automaticallyautoRecall→ relevant memories are injected before each replyextractMinMessages: 2→ extraction triggers in normal two-turn chatssessionMemory.enabled: false→ avoids polluting retrieval with session summaries on day one
⚠️ Memory Architecture (Important)
When memory-lancedb-pro owns the OpenClaw memory slot, it now exposes one memory capability with two coordinated stores:
| Memory Layer | Storage | What it's for | Recallable? |
|---|---|---|---|
| Plugin Memory | LanceDB (vector store) | Semantic recall via memory_recall / auto-recall |
✅ Yes |
| Canonical Corpus | MEMORY.md, memory/**/*.md, recent session transcripts, memory/dreaming/**/*.md |
Source-of-truth files and public artifacts | ✅ Via LanceDB semantic index when canonicalCorpus.enabled is true |
Key principle:
Canonical files remain the source of truth. LanceDB is the semantic index used to retrieve them with grounded paths, line spans, snippets, and citations.
What this means for you:
- Need semantic recall? → Use
memory_storeor let auto-capture do it memory/YYYY-MM-DD.md→ treat as a daily journal / log that can also be indexed for semantic lookupMEMORY.md→ curated human-readable reference that can be indexed as canonical contextmemory/dreaming/**/*.md→ dream reports exposed as public artifacts and indexed as reflection context- Session JSONL transcripts → indexed as
source: "sessions"whencanonicalCorpus.includeSessionTranscriptsis enabled - Plugin memory → primary write path for durable facts, preferences, decisions, and auto-captured memories
OpenClaw hosts receive:
api.registerMemoryCapability({ runtime, promptBuilder, flushPlanResolver, publicArtifacts })- runtime search results shaped as
path,startLine,endLine,snippet,source, andcitation - public artifacts for
MEMORY.md,memory/**/*.md, dream reports, and the dreaming event log atmemory/.dreams/events.jsonl
Dreaming compatibility is configured under the same plugin entry. If dreaming.enabled is true while this plugin owns plugins.slots.memory, OpenClaw can use the memory-core dreaming sidecar against this plugin's memory capability and public artifacts.
On hosts exposing openclaw/plugin-sdk/memory-recall, interactive memory_recall
(including the memory_search/memory_get aliases) and successful auto-recall
injections also report surfaced canonical-file excerpts to native dreaming.
This requires canonical-corpus metadata for the current workspace, matching
content hashes, and the host's live tool/hook run context. The host validates the
excerpt against the source file, applies its existing dreaming eligibility rules,
and deduplicates repeated recalls within the same run. Only literal displayed
primary text counts; generated abstracts, neighbor text, virtual LanceDB IDs,
session transcripts, and late/failed injections do not become file evidence.
Auto-context markup transformations are conservatively excluded. Daily corpus
ingestion does not produce interactive signals. Older hosts without the API or
invocation context continue normal retrieval without this additional recording.
No native dreaming thresholds, promotion budgets, or provenance labels are
changed by this bridge; it does not write native state directly.
Validate & restart:
openclaw config validate
openclaw gateway restart
openclaw logs --follow --plain | grep "memory-lancedb-pro"You should see:
memory-lancedb-pro: smart extraction enabledmemory-lancedb-pro@...: plugin registered
Done! Your agent now has long-term memory.
More installation paths (existing users, upgrades)
Already using OpenClaw?
- Add the plugin with an absolute
plugins.load.pathsentry - Bind the memory slot:
plugins.slots.memory = "memory-lancedb-pro" - Verify:
openclaw plugins info memory-lancedb-pro && openclaw memory-pro stats
Upgrading from pre-v1.1.0?
# 1) Backup
openclaw memory-pro export --scope global --output memories-backup.json
# 2) Dry run
openclaw memory-pro upgrade --dry-run
# 3) Run upgrade
openclaw memory-pro upgrade
# 4) Verify
openclaw memory-pro statsSee CHANGELOG-v1.1.0.md for behavior changes and upgrade rationale.
Turning on Jina task hints on an existing database?
Task hints are two config keys under the plugin's embedding block:
"memory-lancedb-pro": {
"config": {
"embedding": {
"model": "jina-embeddings-v5-text-small",
"taskQuery": "retrieval.query",
"taskPassage": "retrieval.passage"
}
}
}They only affect vectors written after you set them. Rows already in your store
were embedded without a task hint, so a query embedded with retrieval.query is
compared against passages that live in a different vector space — you get roughly
half the benefit, silently.
To fix existing rows, re-embed into a fresh database and cut over to it. Do
not re-embed in place: reembed writes each row with table.add() (append by
id, not replace), so an in-place run — which is exactly what --force unlocks —
leaves the old vector beside the new one and doubles every row; retries pile on
more. reembed refuses same-path runs unless you force it, for this reason.
# 0) Stop the gateway so nothing writes mid-migration.
# 1) Back up the whole store — a real filesystem copy of the LanceDB directory.
# (Do NOT rely on `memory-pro export`: it defaults to --limit 1000 and a single
# --scope, so it silently drops rows past 1000 and every non-global scope.)
cp -r <your dbPath> <your dbPath>.bak
# 2) In the plugin config, set the task hints AND point `dbPath` at a new, empty
# target (e.g. "<your dbPath>-v2"). A fresh target is also what lets you change
# `embedding.dimensions`: a new vector width can only go into a new table.
# 3) Dry run — reads the source, prints the row count, writes nothing.
openclaw memory-pro reembed --source-db <old dbPath> --dry-run
# 4) Re-embed old -> new with the now-current task hints. Source != target, so each
# id lands exactly once. Safe to re-run with --skip-existing if interrupted.
openclaw memory-pro reembed --source-db <old dbPath>
# 5) Verify before trusting the cutover: the "imported" count and
# `memory-pro stats` on the new dbPath must equal the dry-run row count.
openclaw memory-pro stats
# 6) Start the gateway; it now opens the new dbPath.The same cutover applies whenever you change embedding.model orembedding.dimensions — always re-embed into a fresh dbPath, never in place.
Telegram Bot Quick Import (click to expand)
If you are using OpenClaw's Telegram integration, the easiest way is to send an import command directly to the main Bot instead of manually editing config.
Send this message:
Help me connect this memory plugin with the most user-friendly configuration: https://github.com/CortexReach/memory-lancedb-pro
Requirements:
1. Set it as the only active memory plugin
2. Use Jina for embedding, and set embedding.taskQuery=retrieval.query and embedding.taskPassage=retrieval.passage
3. Use Jina for reranker
4. Use gpt-4o-mini for the smart-extraction LLM
5. Enable autoCapture, autoRecall, smartExtraction
6. extractMinMessages=2
7. sessionMemory.enabled=false
8. captureAssistant=false
9. retrieval mode=hybrid, vectorWeight=0.7, bm25Weight=0.3
10. rerank=cross-encoder, candidatePoolSize=12, minScore=0.6, hardMinScore=0.62
11. Generate the final openclaw.json config directly, not just an explanationEcosystem
memory-lancedb-pro is the core plugin. The community has built tools around it to make setup and daily use even smoother:
Setup Script — One-Click Install, Upgrade & Repair
Not just a simple installer — the script intelligently handles a wide range of real-world scenarios:
| Your situation | What the script does |
|---|---|
| Never installed | Fresh download → install deps → pick config → write to openclaw.json → restart |
Installed via git clone, stuck on old commit |
Auto git fetch + checkout to latest → reinstall deps → verify |
| Config has invalid fields | Auto-detect via schema filter, remove unsupported fields |
Installed via npm |
Skips git update, reminds you to run npm update yourself |
openclaw CLI broken due to invalid config |
Fallback: read workspace path directly from openclaw.json file |
extensions/ instead of plugins/ |
Auto-detect plugin location from config or filesystem |
| Already up to date | Run health checks only, no changes |
bash setup-memory.sh # Install or upgrade
bash setup-memory.sh --dry-run # Preview only
bash setup-memory.sh --beta # Include pre-release versions
bash setup-memory.sh --uninstall # Revert config and remove pluginBuilt-in provider presets: Jina / DashScope / SiliconFlow / OpenAI / Ollama, or bring your own OpenAI-compatible API. For full usage (including --ref, --selfcheck-only, and more), see the setup script README.
Claude Code / OpenClaw Skill — AI-Guided Configuration
Install this skill and your AI agent (Claude Code or OpenClaw) gains deep knowledge of every feature in memory-lancedb-pro. Just say "help me enable the best config" and get:
- Guided 7-step configuration workflow with 4 deployment plans:
- Full Power (Jina + OpenAI) / Budget (free SiliconFlow reranker) / Simple (OpenAI only) / Fully Local (Ollama, zero API cost)
- All 9 MCP tools used correctly:
memory_recall,memory_store,memory_forget,memory_update,memory_stats,memory_list,self_improvement_log,self_improvement_extract_skill,self_improvement_review(full toolset requiresenableManagementTools: true— the default Quick Start config exposes the 4 core tools) - Common pitfall avoidance: workspace plugin enablement,
autoRecalldefault-false, jiti cache, env vars, scope isolation, and more
Install for Claude Code:
git clone https://github.com/CortexReach/memory-lancedb-pro-skill.git ~/.claude/skills/memory-lancedb-proInstall for OpenClaw:
git clone https://github.com/CortexReach/memory-lancedb-pro-skill.git ~/.openclaw/workspace/skills/memory-lancedb-pro-skillVideo Tutorial
Full walkthrough: installation, configuration, and hybrid retrieval internals.
https://www.bilibili.com/video/BV1zUf2BGEgn/
Architecture
┌─────────────────────────────────────────────────────────┐
│ index.ts (Entry Point) │
│ Plugin Registration · Config Parsing · Lifecycle Hooks │
└────────┬──────────┬──────────┬──────────┬───────────────┘
│ │ │ │
┌────▼───┐ ┌────▼───┐ ┌───▼────┐ ┌──▼──────────┐
│ store │ │embedder│ │retriever│ │ scopes │
│ .ts │ │ .ts │ │ .ts │ │ .ts │
└────────┘ └────────┘ └────────┘ └─────────────┘
│ │
┌────▼───┐ ┌─────▼──────────┐
│migrate │ │noise-filter.ts │
│ .ts │ │adaptive- │
└────────┘ │retrieval.ts │
└────────────────┘
┌─────────────┐ ┌──────────┐
│ tools.ts │ │ cli.ts │
│ (Agent API) │ │ (CLI) │
└─────────────┘ └──────────┘For a deep-dive into the full architecture, see docs/memory_architecture_analysis.md.
File Reference (click to expand)
| File | Purpose |
|---|---|
index.ts |
Plugin entry point. Registers with OpenClaw Plugin API, parses config, mounts lifecycle hooks via api.on() and command hooks via api.registerHook() |
openclaw.plugin.json |
Plugin metadata + full JSON Schema config declaration |
cli.ts |
CLI commands: memory-pro list/search/stats/delete/delete-bulk/export/import/reembed/upgrade/migrate |
src/store.ts |
LanceDB storage layer. Table creation / FTS indexing / Vector search / BM25 search / CRUD |
src/embedder.ts |
Embedding abstraction. Compatible with any OpenAI-compatible API provider |
src/retriever.ts |
Hybrid retrieval engine. Vector + BM25 → Hybrid Fusion → Rerank → Lifecycle Decay → Filter |
src/scopes.ts |
Multi-scope access control |
src/tools.ts |
Agent tool definitions: memory_recall, memory_store, memory_forget, memory_update + management tools |
src/noise-filter.ts |
Filters out agent refusals, meta-questions, greetings, and low-quality content |
src/adaptive-retrieval.ts |
Determines whether a query needs memory retrieval |
src/migrate.ts |
Migration from built-in memory-lancedb to Pro |
src/smart-extractor.ts |
LLM-powered 6-category extraction with L0/L1/L2 layered storage and two-stage dedup |
src/decay-engine.ts |
Weibull stretched-exponential decay model |
src/tier-manager.ts |
Three-tier promotion/demotion: Peripheral ↔ Working ↔ Core |
Core Features
Hybrid Retrieval
Query → embedQuery() ─┐
├─→ Hybrid Fusion → Rerank → Lifecycle Decay Boost → Length Norm → Filter
Query → BM25 FTS ─────┘- Vector Search — semantic similarity via LanceDB ANN (cosine distance)
- BM25 Full-Text Search — exact keyword matching via LanceDB FTS index
- Hybrid Fusion — vector score as base, BM25 hits receive a weighted boost (not standard RRF — tuned for real-world recall quality)
- Configurable Weights —
vectorWeight,bm25Weight,minScore
Cross-Encoder Reranking
- Built-in adapters for Jina, SiliconFlow, Voyage AI, and Pinecone
- Compatible with any Jina-compatible endpoint (e.g., Hugging Face TEI, DashScope)
- Hybrid scoring: 60% cross-encoder + 40% original fused score
- Graceful degradation: falls back to cosine similarity on API failure
Multi-Stage Scoring Pipeline
| Stage | Effect |
|---|---|
| Hybrid Fusion | Combines semantic and exact-match recall |
| Cross-Encoder Rerank | Promotes semantically precise hits |
| Lifecycle Decay Boost | Weibull freshness + access frequency + importance × confidence |
| Length Normalization | Prevents long entries from dominating (anchor: 500 chars) |
| Hard Min Score | Removes irrelevant results (default: 0.35) |
| MMR Diversity | Cosine similarity > 0.85 → demoted |
Smart Memory Extraction (v1.1.0)
- LLM-Powered 6-Category Extraction: profile, preferences, entities, events, cases, patterns
- L0/L1/L2 Layered Storage: L0 (one-sentence index) → L1 (structured summary) → L2 (full narrative)
- Two-Stage Dedup: vector similarity pre-filter (≥0.7) → LLM semantic decision (CREATE/MERGE/SKIP)
- Category-Aware Merge:
profilealways merges,events/casesare append-only
Memory Lifecycle Management (v1.1.0)
- Weibull Decay Engine: composite score = recency + frequency + intrinsic value
- Three-Tier Promotion:
Peripheral ↔ Working ↔ Corewith configurable thresholds - Access Reinforcement: frequently recalled memories decay slower (spaced-repetition style)
- Importance-Modulated Half-Life: important memories decay slower
Multi-Scope Isolation
- Built-in scopes:
global,agent:,custom:<name>,project:,user: - Agent-level access control via
scopes.agentAccess - Default: each agent accesses
global+ its ownagent:scope - Read-only tools such as
memory_recall,memory_search,memory_list, andmemory_debugfail soft when a requested scope is inaccessible: they search the caller's accessible scopes instead and returnignoredScopeplusaccessibleScopesin details. Write and mutation tools still returnscope_access_deniedfor inaccessible scopes.
Auto-Capture & Auto-Recall
- Auto-Capture (
agent_end): extracts preference/fact/decision/entity from conversations, deduplicates, stores up to 3 per turn - Auto-Recall (
before_prompt_build): injects<relevant-memories>context (up to 3 entries)
Note (v1.1.0-beta.9+): Auto-recall now uses the
before_prompt_buildhook instead of the deprecatedbefore_agent_start. See Hook Adaptation below for details.
Noise Filtering & Adaptive Retrieval
- Filters low-quality content: agent refusals, meta-questions, greetings
- Skips retrieval for greetings, slash commands, simple confirmations, emoji
- Forces retrieval for memory keywords ("remember", "previously", "last time")
- CJK-aware thresholds (Chinese: 6 chars vs English: 15 chars)
Compared to Built-in memory-lancedb (click to expand)
| Feature | Built-in memory-lancedb |
memory-lancedb-pro |
|---|---|---|
| Vector search | Yes | Yes |
| BM25 full-text search | - | Yes |
| Hybrid fusion (Vector + BM25) | - | Yes |
| Cross-encoder rerank (multi-provider) | - | Yes |
| Recency boost & time decay | - | Yes |
| Length normalization | - | Yes |
| MMR diversity | - | Yes |
| Multi-scope isolation | - | Yes |
| Noise filtering | - | Yes |
| Adaptive retrieval | - | Yes |
| Management CLI | - | Yes |
| Session memory | - | Yes |
| Task-aware embeddings | - | Yes |
| LLM Smart Extraction (6-category) | - | Yes (v1.1.0) |
| Weibull Decay + Tier Promotion | - | Yes (v1.1.0) |
| Any OpenAI-compatible embedding | Limited | Yes |
Configuration
API-key fields (embedding.apiKey, retrieval.rerankApiKey, and llm.apiKey) accept plain strings, ${ENV_VAR} placeholders, or SecretRef objects. This plugin supports the env and file SecretRef sources:
{
"embedding": {
"apiKey": { "source": "env", "id": "JINA_API_KEY" }
},
"retrieval": {
"rerankApiKey": { "source": "file", "id": "~/.openclaw/secrets/jina-rerank" }
}
}For source: "file", id is resolved through OpenClaw's api.resolvePath() and then read as a UTF-8 file. The optional provider field is accepted for SecretRef object-shape compatibility but is not used for provider dispatch. exec and other SecretRef sources are rejected by runtime config validation.
Full Configuration Example
/* Detailed source-code truncated for AI context efficiency. */OpenClaw Hook Permissions
The published plugin manifest declares hooks.allowConversationAccess so the agent_end auto-capture hook can read conversation context. If you maintain a custom plugin entry or non-bundled install that overrides manifest hook metadata, keep conversation access enabled:
{
"plugins": {
"entries": {
"memory-lancedb-pro": {
"hooks": {
"allowConversationAccess": true
}
}
}
}
}Without conversation access, recall can still load but auto-capture may be blocked.
Embedding Providers
Works with OpenAI-compatible embedding APIs, including provider-specific payload adapters for services such as Jina and Voyage:
| Provider | Model | Base URL | Dimensions |
|---|---|---|---|
| Jina (recommended) | jina-embeddings-v5-text-small |
https://api.jina.ai/v1 |
1024 |
| OpenAI | text-embedding-3-small |
https://api.openai.com/v1 |
1536 |
| Voyage | voyage-4-lite / voyage-4 |
https://api.voyageai.com/v1 |
1024 / 1024 |
| Google Gemini | gemini-embedding-001 |
https://generativelanguage.googleapis.com/v1beta/openai/ |
3072 |
| Ollama (local) | nomic-embed-text |
http://localhost:11434/v1 |
provider-specific |
Voyage embedding requests use Voyage's model + input payload shape. When requestDimensions is configured it is sent as output_dimension; OpenAI-only fields such as encoding_format are omitted.
Set embedding.maxInputChars for local embedding servers with small context or batch limits. The plugin applies a conservative default for nomic-embed-text; with automatic chunking enabled, longer documents are split before the cap is applied to each provider request.
Rerank Providers
Cross-encoder reranking supports multiple providers via rerankProvider:
| Provider | rerankProvider |
Example Model |
|---|---|---|
| Jina (default) | jina |
jina-reranker-v3 |
| SiliconFlow (free tier available) | siliconflow |
BAAI/bge-reranker-v2-m3 |
| Voyage AI | voyage |
rerank-2.5 |
| Pinecone | pinecone |
bge-reranker-v2-m3 |
Any Jina-compatible rerank endpoint also works — set rerankProvider: "jina" and point rerankEndpoint to your service (e.g., Hugging Face TEI, DashScope qwen3-rerank).
Smart Extraction (LLM) — v1.1.0
When smartExtraction is enabled (default: true), the plugin uses an LLM to intelligently extract and classify memories instead of regex-based triggers.
| Field | Type | Default | Description |
|---|---|---|---|
smartExtraction |
boolean | true |
Enable/disable LLM-powered 6-category extraction |
llm.auth |
string | api-key |
api-key uses llm.apiKey / embedding.apiKey; oauth uses a plugin-scoped OAuth token file by default |
llm.apiKey |
string | (falls back to embedding.apiKey) |
API key for the LLM provider |
llm.model |
string | openai/gpt-oss-120b |
LLM model name |
llm.baseURL |
string | (falls back to embedding.baseURL) |
LLM API endpoint |
llm.oauthProvider |
string | openai-codex |
OAuth provider id used when llm.auth is oauth |
llm.oauthPath |
string | ~/.openclaw/.memory-lancedb-pro/oauth.json |
OAuth token file used when llm.auth is oauth |
llm.timeoutMs |
number | 30000 |
LLM request timeout in milliseconds |
extractMinMessages |
number | 2 |
Minimum messages before extraction triggers |
extractMaxChars |
number | 8000 |
Maximum characters sent to the LLM |
OAuth llm config (use existing Codex / ChatGPT login cache for LLM calls):
{
"llm": {
"auth": "oauth",
"oauthProvider": "openai-codex",
"model": "gpt-5.4",
"oauthPath": "${HOME}/.openclaw/.memory-lancedb-pro/oauth.json",
"timeoutMs": 30000
}
}Notes for llm.auth: "oauth":
llm.oauthProvideris currentlyopenai-codex.- OAuth tokens default to
~/.openclaw/.memory-lancedb-pro/oauth.json. - You can set
llm.oauthPathif you want to store that file somewhere else. auth loginsnapshots the previous api-keyllmconfig next to the OAuth file, andauth logoutrestores that snapshot when available.- Switching from
api-keytooauthdoes not automatically carry overllm.baseURL. Set it manually in OAuth mode only when you intentionally want a custom ChatGPT/Codex-compatible backend.
Legacy CPU Fallback
If an AVX-only Linux x64 host crashes inside LanceDB native vector search with SIGILL, disable native cosine and let memory-lancedb-pro scan scoped rows and rank them in JavaScript:
{
"retrieval": {
"disableNativeCosine": true
}
}You can also set MEMORY_LANCEDB_DISABLE_NATIVE_COSINE=1 for the same behavior.
Lifecycle Configuration (Decay + Tier)
| Field | Default | Description |
|---|---|---|
decay.recencyHalfLifeDays |
30 |
Base half-life for Weibull recency decay |
decay.frequencyWeight |
0.3 |
Weight of access frequency in composite score |
decay.intrinsicWeight |
0.3 |
Weight of importance × confidence |
decay.betaCore |
0.8 |
Weibull beta for core memories |
decay.betaWorking |
1.0 |
Weibull beta for working memories |
decay.betaPeripheral |
1.3 |
Weibull beta for peripheral memories |
tier.coreAccessThreshold |
10 |
Min recall count before promoting to core |
tier.peripheralAgeDays |
60 |
Age threshold for demoting stale memories |
Access Reinforcement
Frequently recalled memories decay more slowly (spaced-repetition style).
Config keys (under retrieval):
reinforcementFactor(0-2, default:0.5) — set0to disablemaxHalfLifeMultiplier(1-10, default:3) — hard cap on effective half-life
CLI Commands
openclaw memory-pro list [--scope global] [--category fact] [--limit 20] [--json]
openclaw memory-pro search "query" [--scope global] [--limit 10] [--json]
openclaw memory-pro stats [--scope global] [--json]
openclaw memory-pro auth login [--provider openai-codex] [--model gpt-5.4] [--oauth-path /abs/path/oauth.json]
openclaw memory-pro auth status
openclaw memory-pro auth logout
openclaw memory-pro delete <id>
openclaw memory-pro delete-bulk --scope global [--before 2025-01-01] [--dry-run]
openclaw memory-pro export [--scope global] [--output memories.json]
openclaw memory-pro import memories.json [--scope global] [--dry-run]
openclaw memory-pro reembed --source-db /path/to/old-db [--batch-size 32] [--skip-existing]
openclaw memory-pro upgrade [--dry-run] [--batch-size 10] [--no-llm] [--limit N] [--scope SCOPE]
openclaw memory-pro migrate check|run|verify [--source /path]OAuth login flow:
- Run
openclaw memory-pro auth login - If
--provideris omitted in an interactive terminal, the CLI shows an OAuth provider picker before opening the browser - The command prints an authorization URL and opens your browser unless
--no-browseris set - After the callback succeeds, the command saves the plugin OAuth file (default:
~/.openclaw/.memory-lancedb-pro/oauth.json), snapshots the previous api-keyllmconfig for logout, and replaces the pluginllmconfig with OAuth settings (auth,oauthProvider,model,oauthPath) openclaw memory-pro auth logoutdeletes that OAuth file and restores the previous api-keyllmconfig when that snapshot exists
Advanced Topics
Locking and concurrent writers
memory-lancedb-pro uses a cross-process file lock for LanceDB writes. This is
enough for one gateway process, multiple agents through that gateway, and local
processes that share the same database directory.
Redis is not required for those deployments. Redis locking is enabled whenlocking.redis.enabled is true, when redisUrl/locking.redis.url is set, or
when MEMORY_LANCEDB_REDIS_URL is present in that process environment. For
multi-machine or multi-container writers, read
Lock Management before sharing a LanceDB directory
across processes, and make sure every writer uses the same lock configuration.
If injected memories show up in replies
Sometimes the model may echo the injected <relevant-memories> block.
Option A (lowest-risk): temporarily disable auto-recall:
{ "plugins": { "entries": { "memory-lancedb-pro": { "config": { "autoRecall": false } } } } }Option B (preferred): keep recall, 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.
Option C (for background/batch agents): exclude specific agents from auto-recall injection:
{
"plugins": {
"entries": {
"memory-lancedb-pro": {
"config": {
"autoRecall": true,
"autoRecallExcludeAgents": ["memory-distiller", "my-cron-agent"]
}
}
}
}
}Useful for background agents (e.g. memory-distiller, cron workers) whose output should not be contaminated by injected memory context.
Auto-recall timeout tuning
Auto-recall has a configurable timeout (default 5s) to prevent stalling agent startup. If you're behind a proxy or using a high-latency embedding API, increase it:
{ "plugins": { "entries": { "memory-lancedb-pro": { "config": { "autoRecallTimeoutMs": 8000 } } } } }If auto-recall consistently times out, check your embedding API latency first. The timeout only affects the automatic injection path — manual memory_recall tool calls are not affected.
Auto-recall rerank cost model
When autoRecall=true and hybrid retrieval uses retrieval.rerank="cross-encoder" with an external rerank API such as Jina, every eligible prompt can make a rerank request. The number of documents sent to that request is governed by auto-recall's retrieve limit and the retriever's rerank input window, not directly by retrieval.candidatePoolSize or by the final autoRecallMaxItems injection cap.
For example, with autoRecallMaxItems: 3, auto-recall asks retrieval for 6 items and hybrid retrieval may send up to 12 candidates to the external reranker before injecting at most 3 memories. To reduce external rerank usage, lower autoRecallMaxItems or maxRecallPerTurn, switch retrieval.rerank to "lightweight" or "none", increase autoRecallMinLength, or keep auto-recall disabled and use manual memory_recall where appropriate.
Startup logs warn when auto-recall plus hybrid cross-encoder rerank can send more items to the reranker than it will inject. Debug auto-recall stats include the actual rerankInput, rerankInputLimit, retrieveLimit, rerank, rerankProvider, and configured retrievalCandidatePoolSize.
Session Memory
- Triggered on
/newcommand — saves previous session summary to LanceDB - Disabled by default (OpenClaw already has native
.jsonlsession persistence) - Configurable message count (default: 15)
See docs/openclaw-integration-playbook.md for deployment modes and /new verification.
Custom Slash Commands (e.g. /lesson)
Add to your CLAUDE.md, AGENTS.md, or system prompt:
## /lesson command
When the user sends `/lesson <content>`:
1. Use memory_store to save as category=fact (raw knowledge)
2. Use memory_store to save as category=decision (actionable takeaway)
3. Confirm what was saved
## /remember command
When the user sends `/remember <content>`:
1. Use memory_store to save with appropriate category and importance
2. Confirm with the stored memory IDIron Rules for AI Agents
Copy the block below into your
AGENTS.mdso your agent enforces these rules automatically.
## Rule 1 — Dual-layer memory storage
Every pitfall/lesson learned → IMMEDIATELY store TWO memories:
- Technical layer: Pitfall: [symptom]. Cause: [root cause]. Fix: [solution]. Prevention: [how to avoid]
(category: fact, importance >= 0.8)
- Principle layer: Decision principle ([tag]): [behavioral rule]. Trigger: [when]. Action: [what to do]
(category: decision, importance >= 0.85)
## Rule 2 — LanceDB hygiene
Entries must be short and atomic (< 500 chars). No raw conversation summaries or duplicates.
## Rule 3 — Recall before retry
On ANY tool failure, ALWAYS memory_recall with relevant keywords BEFORE retrying.
## Rule 4 — Confirm target codebase
Confirm you are editing memory-lancedb-pro vs built-in memory-lancedb before changes.
## Rule 5 — Clear jiti cache after plugin code changes
After modifying .ts files under plugins/, MUST run rm -rf /tmp/jiti/ BEFORE openclaw gateway restart.Database Schema
LanceDB table memories:
| Field | Type | Description |
|---|---|---|
id |
string (UUID) | Primary key |
text |
string | Memory text (FTS indexed) |
vector |
float[] | Embedding vector |
category |
string | Storage category: preference / fact / decision / entity / reflection / other |
scope |
string | Scope identifier (e.g., global, agent:main) |
importance |
float | Importance score 0-1 |
timestamp |
int64 | Creation timestamp (ms) |
metadata |
string (JSON) | Extended metadata |
Common metadata keys in v1.1.0: l0_abstract, l1_overview, l2_content, memory_category, tier, access_count, confidence, last_accessed_at
Note on categories: The top-level
categoryfield uses 6 storage categories. The 6-category semantic labels from Smart Extraction (profile/preferences/entities/events/cases/patterns) are stored inmetadata.memory_category.
Troubleshooting
"Cannot mix BigInt and other types" (LanceDB / Apache Arrow)
On LanceDB 0.26+, some numeric columns may be returned as BigInt. Upgrade to memory-lancedb-pro >= 1.0.14 — this plugin now coerces values using Number(...) before arithmetic.
Hook Adaptation (OpenClaw 2026.3+)
Starting with v1.1.0-beta.9, the plugin's lifecycle hooks have been updated for compatibility with the refactored OpenClaw plugin system.
What changed
| Hook | Before | After | Why |
|---|---|---|---|
| Auto-recall | before_agent_start |
before_prompt_build (priority 10) |
before_agent_start is deprecated; before_prompt_build is the recommended hook for prompt mutation |
| Reflection invariants | before_agent_start |
before_prompt_build (priority 12) |
Same reason as above |
| Reflection derived focus | before_prompt_build |
before_prompt_build (priority 15) |
Unchanged event, added explicit priority |
| All other lifecycle hooks | unchanged | unchanged | agent_end, after_tool_call, session_end, message_received, before_message_write |
Hook API distinction
OpenClaw exposes two hook registration methods. They write to different registries:
| Method | Registry | Dispatch | Use for |
|---|---|---|---|
api.on(event, handler, opts) |
registry.typedHooks |
Dispatched by the lifecycle hook runner | Lifecycle events: before_prompt_build, agent_end, after_tool_call, session_end, message_received, before_message_write |
api.registerHook(event, handler, opts) |
registry.hooks |
Dispatched by the internal hook system | Command/bootstrap events: command:new, command:reset, agent:bootstrap |
Using the wrong method causes hooks to register silently without firing. This plugin uses api.on() for all lifecycle hooks and api.registerHook() for command hooks.
Verifying hooks after install
openclaw plugins info memory-lancedb-proYou should see:
Legacy before_agent_start: no
Typed hooks:
agent_end
before_message_write
before_prompt_build (priority 10)
message_received
Custom hooks:
memory-lancedb-pro-session-memory: command:newIf Legacy before_agent_start: yes appears, you are running an older version of the plugin.
Migration from older versions
If you are upgrading from v1.1.0-beta.8 or earlier:
- Replace the plugin files (copy or
openclaw plugins install) - Clear the jiti cache:
rm -rf /tmp/jiti/ - Restart the gateway:
openclaw gateway restart - Verify:
openclaw plugins info memory-lancedb-proshould showLegacy before_agent_start: no
No config changes or data migration required. All existing memories, scopes, and settings are preserved.
OpenClaw version requirements
- Minimum: OpenClaw 2026.3.22
- Recommended: OpenClaw latest (2026.3.23+)
This version uses before_prompt_build hooks (replacing the deprecated before_agent_start), which requires OpenClaw 2026.3.22 or later. Running openclaw doctor --fix after upgrading will automatically migrate plugin config (e.g. minimax-portal-auth → minimax, Brave search as a standalone plugin).
To upgrade OpenClaw:
npm update -g openclaw
openclaw --version # verify >= 2026.3.22
openclaw doctor --fix # resolve any stale config after upgradeDocumentation
| Document | Description |
|---|---|
| OpenClaw Integration Playbook | Deployment modes, verification, regression matrix |
| Memory Architecture Analysis | Full architecture deep-dive |
| CHANGELOG v1.1.0 | v1.1.0 behavior changes and upgrade rationale |
| Release Checklist | Package preflight, publish dry run, and post-publish smoke checks |
| Long-Context Chunking | Chunking strategy for long documents |
Beta: Smart Memory v1.1.0
Status: Beta — available via
npm i memory-lancedb-pro@beta. Stable users onlatestare not affected.
| Feature | Description |
|---|---|
| Smart Extraction | LLM-powered 6-category extraction with L0/L1/L2 metadata. Falls back to regex when disabled. |
| Lifecycle Scoring | Weibull decay integrated into retrieval — high-frequency and high-importance memories rank higher. |
| Tier Management | Three-tier system (Core → Working → Peripheral) with automatic promotion/demotion. |
Feedback: GitHub Issues · Revert: npm i memory-lancedb-pro@latest
Dependencies
| Package | Purpose |
|---|---|
@lancedb/lancedb ≥0.26.2 |
Vector database (ANN + FTS) |
openai ≥6.21.0 |
OpenAI-compatible Embedding API client |
@sinclair/typebox 0.34.48 |
JSON Schema type definitions |
Contributors
Full list: Contributors
Star History
License
MIT
My WeChat QR Code
Overview (`examples/new-session-distill/README.md`)
New Session Distillation (Recommended)
This example shows a non-blocking /new distillation pipeline:
- Trigger:
command:new(when you type/new) - Hook: enqueue a small JSON task file (fast, no LLM calls)
- Worker: a user-level systemd service watches the inbox and runs Gemini Map-Reduce over the session JSONL transcript
- Storage: write high-signal, atomic lessons into LanceDB Pro via
openclaw memory-pro import - Notify: send a notification message (optional)
Files included:
hook/enqueue-lesson-extract/— OpenClaw workspace hookworker/lesson-extract-worker.mjs— Map-Reduce extractor + importer + notifierworker/systemd/lesson-extract-worker.service— user systemd unit
You must provide:
GEMINI_API_KEYin an env file loaded by systemd
Install steps are documented in the main repo README.
CHANGELOG V1.1.0 (`docs/CHANGELOG-v1.1.0.md`)
memory-lancedb-pro v1.1.0 — 智能记忆增强
日期: 2026-03-06
作者: CJY
概述: 基于对 AI Agent 记忆系统的深入理解,对记忆的写入质量、生命周期管理和去重能力进行了全面改进与完善
一、改进动机
原有记忆系统在检索侧表现优异(Vector+BM25 混合检索、cross-encoder 重排序、多维评分),但在以下方面存在提升空间:
- 记忆写入质量:依赖正则表达式触发捕获,容易漏捕有价值信息或误捕噪声
- 记忆结构层次:扁平文本存储,缺乏分层索引能力
- 记忆生命周期:简单时间衰减,无法模拟人类记忆的遗忘与强化规律
- 去重能力:仅基于向量相似度的粗粒度去重,缺乏语义级判断
本次改进针对这三个维度进行了系统性增强。
二、变更摘要
| 改进维度 | 核心变更 | 效果 |
|---|---|---|
| 智能提取 | LLM 驱动的 6 类别提取 + L0/L1/L2 分层存储 | 记忆写入更精准、结构更丰富 |
| 生命周期管理 | Weibull 衰减模型 + 三层晋升/降级 | 重要记忆持久保留,过时记忆自然淡化 |
| 智能去重 | 向量预过滤 + LLM 语义决策 | 避免冗余记忆,支持信息演化合并 |
当前落地状态(2026-03-06)
以下能力已接入运行主路径,而不再只是"模块存在":
SmartExtractor已挂到agent_end,新写入默认产出memory_category、tier、l0_abstract、l1_overview、l2_contentbefore_agent_start自动召回后会回写access_count与last_accessed_atsrc/retriever.ts已接入decayEngine.applySearchBoost(),检索结果按生命周期分数重排tierManager已接入 recall 后维护流程,根据 recall 计数和 lifecycle score 回写 tier 变更memory_store、regex fallback、迁移、session memory、upgrade 都统一写入 smart metadataopenclaw.plugin.json已暴露decay/tier配置项- 生命周期回归测试已加入
npm test
仍保留的兼容路径:
- 当 lifecycle decay 未启用或不可用时,retriever 仍可回退到旧的
Recency Boost → Importance Weight → Time Decay排序链 - 旧格式数据仍可读取,并可通过
openclaw memory-pro upgrade统一补齐 metadata
三、新增文件
1. `src/memory-categories.ts` — 6 类别分类系统
设计了语义明确的记忆分类体系,将记忆分为两大类六小类:
- 用户记忆:
profile(身份属性)、preferences(偏好习惯)、entities(持续存在的实体)、events(发生的事件) - Agent 记忆:
cases(问题-解决方案对)、patterns(可复用的处理流程)
每个类别有不同的合并策略:
profile→ 始终合并(用户身份信息持续累积)preferences/entities/patterns→ 支持智能合并events/cases→ 仅新增或跳过(独立记录,保留历史完整性)
2. `src/llm-client.ts` — LLM 客户端
封装了 LLM 调用接口,专注于结构化 JSON 输出:
- 复用现有 OpenAI SDK 依赖,零新增包
- 内置 JSON 容错解析:支持 markdown 代码块包裹和平衡大括号提取
- 低温度 (0.1) 保证输出一致性
- 30 秒超时保护,失败时优雅降级
3. `src/extraction-prompts.ts` — 记忆提取提示模板
精心设计了 3 个提示模板:
| 函数 | 用途 |
|---|---|
buildExtractionPrompt() |
从对话中提取 6 类别 L0/L1/L2 记忆,含 few-shot 示例 |
buildDedupPrompt() |
CREATE / MERGE / SKIP 去重决策 |
buildMergePrompt() |
将新旧记忆合并为三层结构 |
提取提示包含完整的记忆价值判断标准、类别决策逻辑表、常见混淆澄清规则和 6 个 few-shot 示例。
4. `src/smart-extractor.ts` — 智能提取管线
实现了完整的 LLM 驱动提取流水线:
对话文本 → LLM 提取 → 候选记忆 → 向量去重 → LLM 决策 → 持久化核心设计:
- 两阶段去重:先用向量相似度(阈值 0.7)快速筛选候选,再用 LLM 进行语义级判断
- 类别感知合并:不同类别应用不同合并策略
- L0/L1/L2 三层存储:L0 一句话索引用于检索注入,L1 结构化摘要用于精读,L2 完整叙述用于深度回顾
- 向后兼容:新增的 6 类别自动映射到已有的 5 类别存储,L0/L1/L2 存储在 metadata JSON 中
- 按类别设定重要度:profile (0.9) > patterns (0.85) > cases/preferences (0.8) > entities (0.7) > events (0.6)
5. `src/decay-engine.ts` — Weibull 衰减引擎
基于认知心理学中的记忆遗忘曲线研究,实现了复合衰减模型:
复合分数 = 时效权重 × 时效 + 频率权重 × 频率 + 内在权重 × 内在价值
三个分量:
| 分量 | 机制 | 含义 |
|---|---|---|
| 时效 (recency) | Weibull 拉伸指数衰减 exp(-λt^β) |
越久远的记忆衰减越快 |
| 频率 (frequency) | 对数饱和曲线 + 时间加权 | 越常被访问的记忆越活跃 |
| 内在价值 (intrinsic) | importance × confidence |
高价值记忆天然抵抗遗忘 |
层级特定的衰减形状 (β 参数):
- Core (β=0.8):亚指数衰减 → 遗忘极慢,衰减地板 0.9
- Working (β=1.0):标准指数衰减,衰减地板 0.7
- Peripheral (β=1.3):超指数衰减 → 遗忘加速,衰减地板 0.5
关键特性:
- 重要性调制半衰期:
effectiveHL = halfLife × exp(μ × importance),重要记忆持续更久 - 搜索结果加权:检索时自动应用衰减加权,让活跃记忆排名更高
- 过期识别:识别 composite < 0.3 的过期记忆
6. `src/tier-manager.ts` — 三层晋升/降级管理器
模拟人类记忆的多级存储模型:
Peripheral(外围) ⟷ Working(工作) ⟷ Core(核心)晋升条件:
| 方向 | 条件 |
|---|---|
| Peripheral → Working | 访问次数 ≥ 3 且 衰减分数 ≥ 0.4 |
| Working → Core | 访问次数 ≥ 10 且 衰减分数 ≥ 0.7 且 重要度 ≥ 0.8 |
降级条件:
| 方向 | 条件 |
|---|---|
| Working → Peripheral | 衰减分数 < 0.15 或(年龄 > 60 天且访问次数 < 3) |
| Core → Working | 衰减分数 < 0.15 且 访问次数 < 3(极少触发) |
7. `src/smart-metadata.ts` — Smart metadata 归一化辅助模块
统一新老写入入口的生命周期字段,确保所有记忆路径产出一致的 metadata 结构:
- 统一补齐
memory_category、tier、l0_abstract、l1_overview、l2_content - 统一处理
access_count、confidence、last_accessed_at - 将存储记录转换为 lifecycle scoring 所需的
DecayableMemory - 为迁移、upgrade、tool-store、regex fallback 提供同一套默认值与兼容逻辑
8. `src/memory-upgrader.ts` — 旧记忆升级器
将旧格式记忆(无 L0/L1/L2 / 5 类别)批量升级为新智能记忆格式,统一生命周期管理:
- 反向类别映射:
fact→profile/cases(含启发式+LLM 判断)、preference→preferences、entity→entities、decision→events、other→patterns - L0/L1/L2 生成:LLM 模式(推荐)或 无 LLM 模式(首句截取+原文保留)
- 元数据补全:自动填充
tier: "working"、access_count: 0、confidence: 0.7 - 批量处理:支持
--batch-size、--limit、--dry-run控制 - 启动检测:插件启动 5 秒后自动检测旧记忆数量,日志提示升级
四、修改文件
`index.ts` — 插件入口
新增导入
import { SmartExtractor } from "./src/smart-extractor.js";
import { createLlmClient } from "./src/llm-client.js";
import { createDecayEngine, DEFAULT_DECAY_CONFIG } from "./src/decay-engine.js";
import { createTierManager, DEFAULT_TIER_CONFIG } from "./src/tier-manager.js";新增配置项
smartExtraction?: boolean; // 是否启用 LLM 智能提取(默认 true)
llm?: {
apiKey?: string; // LLM API Key(默认复用 embedding.apiKey)
model?: string; // LLM 模型(默认 gpt-4o-mini)
baseURL?: string; // LLM API 端点
};
extractMinMessages?: number; // 最少消息数才触发提取(默认 2)
extractMaxChars?: number; // 送入 LLM 的最大字符数(默认 8000)`agent_end` 钩子改进
- 当
smartExtraction启用时,优先使用 SmartExtractor 进行 LLM 6 类别提取 - 当消息数不足或 SmartExtractor 未初始化时,降级回原有正则触发逻辑
- 提取完成后输出统计日志:
smart-extracted N created, M merged, K skipped
`before_agent_start` 钩子改进
- 注入的记忆上下文现在显示 L0 摘要而非原始文本
- 新增 6 类别标签(如
[preferences:global]) - 新增层级标记(
[C]ore /[W]orking /[P]eripheral) - 自动召回后回写
access_count与last_accessed_at
启动时旧记忆检测
- 插件启动 5 秒后异步扫描旧格式记忆数量
- 如发现旧格式记忆,在日志中输出提示:
Run 'openclaw memory-pro upgrade' to convert them.
`src/retriever.ts` — 检索器
- 接入
decayEngine.applySearchBoost(),检索结果按生命周期分数重排 - 当 lifecycle decay 未启用或不可用时,可回退到旧的
Recency Boost → Importance Weight → Time Decay排序链
`openclaw.plugin.json` — 插件配置清单
- 暴露
decay/tier配置项,允许用户自定义衰减参数和晋升阈值
`cli.ts` — CLI 命令
新增 `memory-pro upgrade` 命令
openclaw memory-pro upgrade [--dry-run] [--batch-size N] [--no-llm] [--limit N] [--scope SCOPE]--dry-run:仅统计旧记忆数量,不修改数据--batch-size:每批处理数量(默认 10)--no-llm:不调用 LLM,使用简单规则生成 L0/L1/L2--limit:最大升级数量--scope:仅升级指定 scope 的记忆
五、配置指南
最简配置(复用已有 API Key)
{
"embedding": {
"apiKey": "${OPENAI_API_KEY}",
"model": "text-embedding-3-small"
},
"smartExtraction": true
}完整配置
{
"embedding": {
"apiKey": "${OPENAI_API_KEY}",
"model": "text-embedding-3-small"
},
"smartExtraction": true,
"llm": {
"apiKey": "${OPENAI_API_KEY}",
"model": "gpt-4o-mini",
"baseURL": "https://api.openai.com/v1"
},
"extractMinMessages": 2,
"extractMaxChars": 8000
}禁用智能提取
{
"smartExtraction": false
}六、向后兼容性
| 方面 | 兼容方式 |
|---|---|
| LanceDB Schema | 新字段存储在 metadata JSON 中,不修改表结构 |
| 记忆类别 | 新 6 类别自动映射到原有 5 类别 |
| 混合检索 | Vector+BM25 检索管线完全保留 |
| 去重逻辑 | 仅在 smartExtraction: true 时生效 |
| 已有数据 | 旧记忆正常读取,新记忆额外携带 L0/L1/L2 元数据 |
| 配置 | 全部新增配置项均有默认值,零配置即可使用 |
| 旧记忆升级 | memory-pro upgrade 命令一键升级为新格式 |
Lock Management (`docs/lock-management.md`)
Lock Management
memory-lancedb-pro protects LanceDB writes with a cross-process file lock based onproper-lockfile. The lock target is .memory-write.lock inside the configured
database directory, and the transient lock artifact is .memory-write.lock.lock.
When The Built-In File Lock Is Enough
Use the default file lock for:
- a single OpenClaw gateway process
- multiple agents writing through the same gateway process
- multiple local processes that share the same local filesystem path
The store also batches concurrent bulkStore() calls before taking the write
lock, so high-throughput auto-capture paths avoid one lock acquisition per
memory item.
Multi-Machine Or Container Deployments
The file lock only coordinates processes that can see the same lock target on a
filesystem with reliable lock-directory semantics. For multi-machine,
multi-container, or network-filesystem deployments, verify this before relying on
the default lock:
openclaw memory-pro stats --json
ls -la "$(dirname "$MEMORY_LANCEDB_PRO_DB_PATH")"If each process has its own local database directory, no lock can protect writes
across those processes because they are not writing to the same LanceDB store.
Redis Status
Redis is not required for single-gateway or same-filesystem deployments. The
plugin enables Redis locking when locking.redis.enabled is true, whenredisUrl/locking.redis.url is set, or when MEMORY_LANCEDB_REDIS_URL is
present in that process environment. Every writer that shares a LanceDB store
must use the same Redis lock configuration; mixing Redis-locked writers with
writers that only use the local file lock creates separate lock domains.
When Redis locking is enabled, every LanceDB write and index-maintenance
mutation uses the Redis lock domain. Redis connection or lock-client
availability failures fail writes closed instead of falling back to a local file
lock.
If you operate multiple independent writers, prefer one of these approaches:
- route writes through one OpenClaw gateway
- place the LanceDB directory on a filesystem whose lock-directory behavior is
known to work withproper-lockfile - add an explicit external write coordinator before enabling multiple writers
Do not use a no-op lock fallback for write paths. If an external coordinator is
required but unavailable, fail the write and retry after the coordinator is
healthy rather than switching that writer into a separate local lock domain.
Troubleshooting Lock Contention
Symptoms of lock contention include slow memory writes, delayed auto-capture, or
warnings about stale .memory-write.lock.lock artifacts.
Checklist:
- Confirm all writers use the same
dbPath. - Confirm old
.memory-write.lock.lockartifacts are cleaned up by the store. - Prefer
bulkStore()for batch writes instead of repeatedstore()calls. - Avoid multiple independent gateway processes writing to separate copies of the
same intended memory corpus.
Long Context Chunking (`docs/long-context-chunking.md`)
Long Context Chunking
Overview
The long context chunking system automatically handles documents that exceed embedding model context limits by splitting them into manageable chunks and computing averaged embeddings.
Problem Solved
When embedding very long documents or messages, you might encounter errors like:
Input length exceeds context length: 12453 tokens. Maximum length: 8192 tokens.This plugin now handles such cases gracefully by:
- Detecting context length errors before they cause failures
- Automatically splitting the document into overlapping chunks
- Embedding each chunk separately
- Computing an averaged embedding that preserves semantic meaning
How It Works
Chunking Strategy
The chunker uses a semantic-aware approach:
- Splits at sentence boundaries when possible (better for preserving meaning)
- Configurable overlap (default: 200 characters) to maintain context across chunks
- Adapts to model context limits based on the embedding model
- Forced splits at hard limits if sentence boundaries are not found
Chunking Flow
Long Document
│
├── 8192+ characters ──┐
│
▼
┌─────────────────┐
│ Detect Overflow │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Split into │
│ Overlapping │
│ Chunks │
└────────┬────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ Chunk 1│ │ Chunk 2│ │ Chunk 3│
│ [1-2k]│ │[1.8k-3.8k]│ │[3.6k-5.6k]│
└───┬────┘ └───┬────┘ └───┬────┘
│ │ │
▼ ▼ ▼
Embedding Embedding Embedding
│ │ │
└──────────────────┼──────────────────┘
│
▼
Compute Average
│
▼
Final EmbeddingConfiguration
Default Settings
The chunker automatically adapts to your embedding model:
- maxChunkSize: 70% of model context limit (e.g., 5734 for 8192-token model)
- overlapSize: 5% of model context limit
- minChunkSize: 10% of model context limit
- semanticSplit: true (prefer sentence boundaries)
- maxLinesPerChunk: 50 lines
Disabling Auto-Chunking
If you prefer to handle chunking manually or want the model to fail on long documents:
{
"plugins": {
"entries": {
"memory-lancedb-pro": {
"enabled": true,
"config": {
"embedding": {
"apiKey": "${JINA_API_KEY}",
"model": "jina-embeddings-v5-text-small",
"chunking": false // Disable auto-chunking
}
}
}
}
}
}Custom Chunking Parameters
For advanced users who want to tune chunking behavior:
{
"plugins": {
"entries": {
"memory-lancedb-pro": {
"enabled": true,
"config": {
"embedding": {
"autoChunk": {
"maxChunkSize": 2000, // Characters per chunk
"overlapSize": 500, // Overlap between chunks
"minChunkSize": 500, // Minimum acceptable chunk size
"semanticSplit": true, // Prefer sentence boundaries
"maxLinesPerChunk": 100 // Max lines before forced split
}
}
}
}
}
}
}Supported Models
The chunker automatically adapts to these embedding models:
| Model | Context Limit | Chunk Size | Overlap |
|---|---|---|---|
| Jina jina-embeddings-v5-text-small | 8192 | 5734 | 409 |
| OpenAI text-embedding-3-small | 8192 | 5734 | 409 |
| OpenAI text-embedding-3-large | 8192 | 5734 | 409 |
| Gemini gemini-embedding-001 | 2048 | 1433 | 102 |
Performance Considerations
Token Savings
- Without chunking: 1 failed embedding (retries required)
- With chunking: 3-4 chunk embeddings (1 avg result)
- Net cost increase: ~3x for long documents (>8k tokens)
- Trade-off: Gracefully handling vs. processing smaller documents
Caching
Chunked embeddings are cached by their original document hash, so:
- Subsequent requests for the same document get the cached averaged embedding
- Cache hit rate improves as long documents are processed repeatedly
Processing Time
- Small documents (<4k chars): No chunking, same as before
- Medium documents (4k-8k chars): No chunking, same as before
- Long documents (>8k chars): ~100-200ms additional chunking overhead
Logging & Debugging
Enable Debug Logging
To see chunking in action, you can check the logs:
Document exceeded context limit (...), attempting chunking...
Split document into 3 chunks for embedding
Successfully embedded long document as 3 averaged chunksCommon Scenarios
Scenario 1: Long memory text
- When a user's message or system prompt is very long
- Automatically chunked before embedding
- No error thrown, memory is still stored and retrievable
Scenario 2: Batch embedding long documents
- If some documents in a batch exceed limits
- Only the long ones are chunked
- Successful documents processed normally
Troubleshooting
Chunking Still Fails
If you still see context length errors:
- Verify model: Check which embedding model you're using
- Increase minChunkSize: May need smaller chunks for some models
- Disable autoChunk: Handle chunking manually with explicit split
Too Many Small Chunks
If chunking creates many tiny fragments:
- Increase minChunkSize: Larger minimum chunk size
- Reduce overlap: Less overlap between chunks means more efficient chunks
Embedding Quality Degradation
If chunked embeddings seem less accurate:
- Increase overlap: More context between chunks preserves relationships
- Use smaller maxChunkSize: Split into more, smaller overlapping pieces
- Consider hierarchical approach: Use a two-pass retrieval (chunk → document → full text)
Future Enhancements
Planned improvements:
- Hierarchical chunking: Chunk → document-level embedding
- Sliding window: Different overlap strategies per document complexity
- Smart summarization: Summarize chunks before averaging for better quality
- Context-aware overlap: Dynamic overlap based on document complexity
- Async chunking: Process chunks in parallel for batch operations
Technical Details
Algorithm
- Detect overflow: Check if document exceeds maxChunkSize
- Split semantically: Find sentence boundaries within target range
- Create overlap: Include overlap with previous chunk's end
- Embed in parallel: Process all chunks simultaneously
- Average the result: Compute mean embedding across all chunks
Complexity
- Time: O(n × k) where n = number of chunks, k = average chunk processing time
- Space: O(n × d) where d = embedding dimension
Edge Cases
| Case | Handling |
|---|---|
| Empty document | Returns empty embedding immediately |
| Very small documents | No chunking, normal processing |
| Perfect boundaries | Split at sentence ends, no truncation |
| No boundaries found | Hard split at max position |
| Single oversized chunk | Process as-is, let provider error |
| All chunks too small | Last chunk takes remaining text |
References
This feature was added to handle long-context documents gracefully without losing memory quality.
Memory Architecture Analysis (`docs/memory_architecture_analysis.md`)
`memory-lancedb-pro` 记忆架构分析
更新时间:2026-03-09
基准:当前仓库中的README.md、openclaw.plugin.json、index.ts、src/*、cli.ts
结论:当前版本已经形成完整的“写入 -> 存储 -> 检索 -> 生命周期维护 -> 运维工具”闭环;智能提取、嵌入噪声检测、生命周期衰减、Tier 晋升/降级、迁移升级、CLI 与 Agent Tools 都已纳入同一主架构。
一、架构判断摘要
1.1 当前真实主路径
当前版本不是“在旧向量记忆插件上补了几个实验模块”,而是一个完整的 OpenClaw Memory Plugin:
index.ts负责插件注册、配置解析、Hook 装配、CLI 装配、后台服务装配src/store.ts负责 LanceDB 表初始化、CRUD、向量检索、FTS/BM25、metadata 局部回写src/embedder.ts负责统一 Embedding Provider 适配、任务感知 embedding、长文本 chunking、缓存src/retriever.ts负责混合检索、rerank、长度归一化、生命周期重排、噪声过滤、去重多样性src/smart-extractor.ts负责 LLM 智能提取、嵌入噪声预过滤、两阶段去重、语义合并、新格式写入src/noise-prototypes.ts负责嵌入噪声原型库(语言无关噪声检测 + LLM 反馈学习闭环)src/decay-engine.ts+src/tier-manager.ts负责 recall 后的生命周期评分与 tier 演化src/tools.ts和cli.ts分别提供 Agent Tool 面与运维 CLI 面
1.2 当前版本最重要的架构特征
- 智能提取已经进入默认写入主路径,regex 仅作为兜底
- 生命周期衰减已经进入默认检索主路径,不再是“代码里有对象但没接上”
- smart metadata 已成为全系统的统一中间层
- 旧 5 类 store category 与新 6 类 memory category 处于“双层兼容模型”
- auto-recall、tool recall、CLI、迁移、升级、session memory 都共享同一份 LanceDB 数据平面
1.3 仍保留的兼容层
- 无 FTS 时自动回退到 vector-only / lexical fallback
- 无 lifecycle decay 时回退到旧的
recency boost + importance weight + time decay - legacy memory 仍能读;可通过
memory-pro upgrade补齐 smart metadata - 存储表 schema 未拆分成多张新表,而是保留单表 +
metadataJSON 扩展
二、总体架构图
/* Detailed source-code truncated for AI context efficiency. */三、入口层:`index.ts` 是总装配器
index.ts 不是简单导出插件对象,而是整个系统的总装配器,负责把各模块接入 OpenClaw:
- 解析配置并做 env var 展开
- 创建
MemoryStore、Embedder、MemoryRetriever、ScopeManager - 可选初始化
SmartExtractor - 注册 Agent Tools
- 注册
memory-proCLI - 注册
before_agent_start、agent_end、command:new - 注册后台 service:启动检查、legacy upgrade 提示、自动备份
3.1 运行时默认值
按当前实现,关键默认行为如下:
smartExtraction: 默认开启extractMinMessages: 默认2autoCapture: 默认开启autoRecall: 默认关闭captureAssistant: 默认关闭enableManagementTools: 默认关闭sessionMemory: 只有显式sessionMemory.enabled === true才注册 Hook,运行时默认关闭
3.2 服务层职责
插件 registerService().start() 不是业务核心链路,但它负责运维闭环:
- 异步执行
embedder.test()与retriever.test(),避免阻塞 Gateway 启动 - 启动后约 5 秒检查 legacy memory 数量并输出 upgrade 提示
- 启动后 1 分钟做一次 JSONL 备份,此后每 24 小时做一次
- 停止时清理定时器
这意味着该插件不仅有“读写能力”,也有“自检 + 自提示 + 备份”的运维能力。
四、写入架构:从对话到长期记忆
4.1 写入入口清单
当前写入来源不止一条:
agent_end自动捕获memory_storeAgent Tool 手工写入memory_updateAgent Tool 原地更新command:new的 session summary 写入memory-pro importmemory-pro migrate runmemory-pro upgradememory-pro reembed
其中自动捕获是最核心的在线写入链路。
4.2 自动捕获写入主路径
当前自动捕获的真实入口已经不是“裸 agent_end.messages 直读”,而是一个轻量的运行时适配层:
message_received
-> 归一化实时入站文本(去 addressing / 去 OpenClaw 注入前缀)
-> 按 conversationKey 暂存最近少量原始用户文本
agent_end
-> 从 event.messages 提取 user/assistant 文本
-> 再做同一套归一化(去 recall block / inbound metadata / session reset prompt / addressing)
-> 优先消费 pending ingress texts
-> 若无 pending ingress,则退回到 session snapshot 的“新增文本增量”
-> 若只有显式 remember 指令,则可补上一条最近真实文本形成最小上下文
-> 进入 smart extraction / regex fallback 主链进入写入主链后的执行顺序是:
抽取并归一化文本(默认仅 `user`;当 `captureAssistant === true` 时也包含 `assistant`)
-> 若 smartExtractor 可用:
嵌入噪声预过滤 filterNoiseByEmbedding(texts)
若所有文本被过滤 -> return(纯噪声输入)
若清洗后消息数 >= extractMinMessages:
SmartExtractor.extractAndPersist()
若 created > 0 或 merged > 0,则直接 return
否则继续走 regex fallback
-> shouldCapture() + detectCategory() + regex fallback
-> buildSmartMetadata()
-> store.store()几个关键点:
- 当前实现增加了一层“OpenClaw runtime 适配层”,用来消解
prependContext、inbound metadata、addressing、session snapshot 粒度等上游差异 - 智能提取只有在产出持久化结果时,才会接管整个自动捕获路径
- regex fallback 仍存在,但已经不再输出“半旧格式数据”
- fallback 写入前仍做噪声过滤与重复检查
- 每轮对话最多写入 3 条 fallback memory
- 当前插件不会主动回读 session JSONL 或 LanceDB 历史来拼装捕获输入;运行时上下文只来自:
message_received的短暂内存队列agent_end.event.messages- 当前进程内的极小 recent-text 缓存
- 这层适配是 OpenClaw runtime 通用策略,不绑定 Discord/Telegram 等具体渠道协议字段
4.3 SmartExtractor 主链
src/smart-extractor.ts 的核心流程是:
texts
-> filterNoiseByEmbedding() 嵌入噪声预过滤
-> conversationText
-> LLM 抽取 CandidateMemory[]
-> 逐条向量预筛
-> LLM 判定 CREATE / MERGE / SKIP
-> buildSmartMetadata()
-> store.store() / store.update()
-> 若 zero candidates -> learnAsNoise() 反馈到噪声库当前特征:
- 候选记忆最多处理 5 条
- 第一阶段去重使用
vectorSearch(..., threshold=0.7) - 第二阶段去重交给 LLM 做语义决策
profile类记忆永远优先走 mergeevents/cases更偏 append-only
4.4 6 类智能分类与 5 类存储分类并存
这是当前架构最重要的兼容设计之一。
智能分类
定义在 src/memory-categories.ts:
profilepreferencesentitieseventscasespatterns
存储分类
底层 LanceDB 主字段 category 仍保留旧 5 类:
preferencefactdecisionentityother
映射关系
SmartExtractor 写入时会做兼容映射:
| 智能分类 | 存储分类 |
|---|---|
profile |
fact |
preferences |
preference |
entities |
entity |
events |
decision |
cases |
fact |
patterns |
other |
因此:
- 结构化语义分类保存在
metadata.memory_category - 向后兼容的粗粒度分类保存在
entry.category
也正因为如此,CLI / Tool 里的 category 过滤目前仍以旧 5 类为准。
4.5 `memory_update` 的定位
memory_update 是新版里值得单独强调的能力:
- 支持按完整 UUID 或 8+ 前缀定位 memory
- 文本更新时自动重新 embedding
- 保留原始
timestamp - 适合修正陈旧事实,而不是“删旧建新”
这意味着系统现在支持“记忆更正”而不只是“记忆追加”。
4.6 嵌入噪声检测:NoisePrototypeBank
src/noise-prototypes.ts 提供了语言无关的噪声检测能力,替代基于正则的方式:
- 内置 ~15 条多语言噪声原型(回忆查询、agent 否认、问候语)
- 插件启动时嵌入所有原型并缓存向量(异步非阻塞)
- auto-capture 管道中,SmartExtractor 的
filterNoiseByEmbedding()在 LLM 提取前执行 - 文本长度分层策略:<=8 字符跳过(防误判)、8-300 字符做嵌入检查、>300 字符跳过(长文本非噪声)
- 默认相似度阈值
0.82
LLM 反馈闭环:
当 LLM 提取返回零候选时,learnAsNoise() 将该文本的嵌入向量加入噪声库:
文本 -> 嵌入检查 -> [未命中] -> LLM 提取 -> 返回 {memories: []}
|
将该文本向量加入噪声库
|
下次类似文本直接被嵌入检查拦截- 去重:新向量与已有原型相似度 >= 0.95 则跳过
- 容量上限:最多学习 200 条,超限淘汰最旧的学习原型(保留内置原型)
- 仅在
smartExtraction !== false时激活,不影响纯 regex 路径
五、统一元数据层:`smart-metadata.ts` 是系统中枢
src/smart-metadata.ts 是整套架构的真正收敛点。
它负责:
- 解析 legacy metadata
- 用 entry 本身补齐缺省字段
- 将新旧 memory 归一化成统一 metadata 结构
- 将 entry 转换为 lifecycle scoring 所需的
LifecycleMemory
5.1 当前 metadata 常见字段
| 字段 | 含义 |
|---|---|
memory_category |
新 6 类语义分类 |
tier |
core / working / peripheral |
l0_abstract |
短句索引,默认也是主搜索文本 |
l1_overview |
结构化摘要 |
l2_content |
长叙述内容 |
access_count |
被 recall 的次数 |
confidence |
抽取/合并置信度 |
last_accessed_at |
最近被 recall 时间 |
source_session |
来源 session key |
type |
特殊类型,如 session-summary |
tier_updated_at |
tier 最近更新时间 |
migratedFrom / originalId |
迁移/升级来源信息 |
5.2 为什么 metadata 是核心设计
当前实现没有把 L0/L1/L2、tier、access_count 单独提升为 LanceDB 表字段,而是统一放进 metadata JSON。这样做带来四个结果:
- 不需要重建 LanceDB 主表
- legacy entry 能平滑升级
- store 层的 CRUD 复杂度保持可控
- lifecycle、smart extraction、迁移、session memory 可以共享同一格式
六、存储层:`MemoryStore` 不只是 CRUD
src/store.ts 的职责比 README 表里写的更重。
6.1 初始化阶段
MemoryStore 是 lazy-init 的:
- 首次访问时连接 LanceDB
- 若表不存在则创建
memories - 创建或检测 FTS index
- 校验 vector dimension 是否匹配
因此 store 既是数据库访问层,也是 schema 守门层。
6.2 查询能力
它提供三种检索能力:
vectorSearch()bm25Search()lexicalFallbackSearch()
其中 BM25 路径是:
有 FTS index -> LanceDB search(query, "fts")
无 FTS / FTS 失败 -> lexicalFallbackSearch()lexical fallback 不只匹配 entry.text,还会参考:
l0_abstractl1_overviewl2_content
这意味着即使 FTS 不可用,smart metadata 仍然参与词法命中。
6.3 更新能力
当前 LanceDB 不支持真正的 in-place update,所以 store.update() 采用:
读旧行 -> 构造新 entry -> delete old -> add new而 patchMetadata() 则是在这层之上封装的 metadata 局部更新入口,被以下链路复用:
- recall 访问计数更新
- tier 回写
- 未来的 lifecycle 扩展字段更新
6.4 运维相关能力
store 层还承接了多项运维需求:
delete()支持 UUID 与前缀删除bulkDelete()强制要求 filter,避免误删全库importEntry()保留源id/timestamp,用于 reembed / migrationstats()为 CLI 和管理工具提供聚合统计hasId()用于过滤 BM25 ghost entry
七、Embedding 层:Provider 适配 + Chunking + Cache
src/embedder.ts 在当前架构里不是简单的 OpenAI SDK 包装,而是完整的 embedding 抽象层。
7.1 主要能力
- OpenAI-compatible provider 统一接入
taskQuery/taskPassage任务感知 embeddingdimensions透传normalized透传- LRU + TTL embedding cache
- 长文本自动 chunking
7.2 长文本 chunking 的角色
src/chunker.ts 为 embedding 超长文本提供模型感知分块:
- 超过上下文限制时触发
- 按语义边界切块并带 overlap
- 分块 embedding 后做平均向量聚合
这条能力对以下场景尤其重要:
- session summary
- 导入的长文档 memory
- reembed/import 场景
从实现上看,embedder 当前默认开启 auto-chunking。
八、检索架构:混合检索已经是默认主线
src/retriever.ts 是当前系统的在线 recall 核心。
8.1 检索入口
当前有三类读取入口共用 retriever:
before_agent_start自动召回memory_recallAgent Toolmemory-pro searchCLI
8.2 混合检索主链
在有 FTS 支持时,默认路径是:
embedQuery(query)
-> vectorSearch
-> bm25Search
-> fusion
-> rerank
-> length normalization
-> hard min score
-> lifecycle decay boost / legacy time decay
-> noise filter
-> MMR diversity更具体地说:
- 向量检索和 BM25 并行执行
fuseResults()以向量分数为主,BM25 命中提供确认性加权- 可选 Cross-Encoder rerank,失败则降级为 cosine rerank
- 长文本进行长度惩罚
- 过低语义相关度结果直接硬过滤
- 生命周期分数再做最终重排
- 去噪与近重复打散
8.3 当前融合策略不是教科书式 RRF
README 把它描述为 hybrid fusion,但代码中的实际策略更偏“向量分数主导 + BM25 奖励”:
- 命中向量时,以向量分数为主
- BM25 命中可提供额外 boost
- 纯 BM25 命中允许直接进入结果集
- 对高 BM25 精确词法命中设置 preservation floor,避免被 reranker 错杀
这是为了照顾:
- 配置项、ID、token、环境变量等符号型检索
- 中英混合 query
- reranker 对符号查询不稳定的现实问题
8.4 当前排序链上的关键实现细节
hardMinScore发生在 decay/time-decay 之前- lifecycle decay 在有
decayEngine时替代旧的 recency/importance/time-decay 路径 applyMMRDiversity()不是删除相似项,而是把相似项延后- BM25-only 结果会先用
store.hasId()检查,避免 FTS 残留 ghost entry
九、生命周期闭环:现在已经接入业务运行时
src/decay-engine.ts 与 src/tier-manager.ts 在当前版本里已经不再是离线概念模型,而是运行时逻辑。
9.1 Decay Engine
Decay 的复合分数公式是:
composite = recencyWeight * recency
+ frequencyWeight * frequency
+ intrinsicWeight * intrinsic其中:
recency: Weibull 拉伸指数衰减,半衰期受 importance 调制frequency: 访问次数的对数饱和 + 最近访问模式奖励intrinsic:importance * confidence
Tier 还会影响衰减形状:
| Tier | beta | floor | 含义 |
|---|---|---|---|
core |
0.8 |
0.9 |
衰减最慢,搜索最低保留高 |
working |
1.0 |
0.7 |
中性 |
peripheral |
1.3 |
0.5 |
衰减最快 |
9.2 Tier Manager
Tier 迁移规则大致如下:
graph LR
P["Peripheral"] -->|"access >= 3 且 composite >= 0.4"| W["Working"]
W -->|"access >= 10 且 composite >= 0.7 且 importance >= 0.8"| C["Core"]
W -->|"composite < 0.15 或 高龄低访问"| P
C -->|"极低 composite 且低访问"| W9.3 生命周期触发点
当前需要特别区分两个 recall 路径:
auto-recall 路径
before_agent_start 在拿到 recall 结果后会执行完整闭环:
patchMetadata(access_count + 1, last_accessed_at = now)- 读取同 scope 的近期记忆
decayEngine.scoreAll()tierManager.evaluateAll()- 将
tier/tier_updated_at回写
`memory_recall` Tool 路径
memory_recall 当前会:
- 更新
access_count - 更新
last_accessed_at
但不会调用 runRecallLifecycle(),也就是说:
- Tool recall 会积累访问数据
- 真正的 tier 迁移维护目前仍只挂在 auto-recall 主链上
这是当前架构里一个重要而容易被忽略的边界。
9.4 session-summary 的特殊处理
sessionMemory 写入的 memory 会带 metadata.type = "session-summary"。
在 auto-recall 生命周期维护中,这类 memory 会被排除在 tier 评估之外,避免会话摘要挤占核心长期记忆层级。
十、读取注入层:auto-recall 的上下文安全模型
当 autoRecall === true 时,before_agent_start 会把 recall 结果注入到:
<relevant-memories>
...
</relevant-memories>几个值得注意的设计点:
- 默认关闭,避免模型直接回显 memory block
- 注入前先走
shouldSkipRetrieval(),避免问候语、小确认、emoji、slash 命令触发检索 - 注入文本带
[UNTRUSTED DATA]提示,防止把 memory 当指令执行 - 显示内容优先使用
l0_abstract - 显示时会附上 category、scope、tier、分数与来源标记
因此 auto-recall 实际上已经包含:
- 召回判断
- 召回结果格式化
- prompt injection 安全隔离
- recall 后 lifecycle 驱动
十一、Scope 隔离:这是多 Agent 记忆的边界层
src/scopes.ts 负责 scope 体系与访问控制。
支持的 scope 形态:
globalagent:project:user:custom:<name>
运行时规则:
- agent 默认可见
global + agent: - 可通过
scopes.agentAccess细化访问范围 - Tool 与 Hook 都会在运行时解析 agentId,再做 scope 过滤
这意味着该插件已经是“多租户记忆系统”,而不是单用户单库的简单记忆表。
十二、工具面与 CLI 面:这不是附属功能,而是第二操作平面
12.1 Agent Tools
核心工具现在是 4 个:
memory_recallmemory_storememory_forgetmemory_update
可选管理工具:
memory_statsmemory_list
注意:
- 核心 4 个默认注册
- 管理工具只有
enableManagementTools === true才注册
12.2 CLI
memory-pro 当前已经具备完整运维面:
versionlistsearchstatsdeletedelete-bulkexportimportreembedupgrademigrate checkmigrate runmigrate verify
其中几条尤其关键:
upgrade: 把 legacy memory 升级成 smart formatmigrate: 从旧memory-lancedb迁移reembed: 用新 embedding 模型重建向量但保留 ID/时间delete-bulk: 带 scope/before 保护条件的批量删除
从架构角度看,这些 CLI 不是外部脚本,而是插件运行面的一部分。
十三、兼容与演进:迁移、升级、备份已经内建
13.1 迁移
src/migrate.ts 负责从旧版 memory-lancedb 导入数据:
- 自动搜索常见 legacy DB 路径
- 读取旧
memories表 - 迁移到新库
- 同时补 smart metadata,而不是简单复制旧字段
13.2 升级
src/memory-upgrader.ts 负责对“已经在 Pro 库里但仍是旧格式”的 memory 做升级:
- 统计 legacy memory 数量
- 支持 LLM 模式与 no-LLM 模式
- 为旧数据补全 L0/L1/L2、category、tier、confidence 等
13.3 自动备份
当前 service 会定时导出 JSONL 备份:
- 启动后 1 分钟首次执行
- 后续每 24 小时执行
- 默认保留最近 7 份
这份备份更像“内容与 metadata 快照”,不是完整向量副本,因为 store.list() 默认不带 vectors。
十四、会话记忆与批处理蒸馏:两条扩展型摄入链路
14.1 Session Memory
command:new Hook 在启用时会:
- 查找上一段 session JSONL
- 抽取最近 N 条消息
- 生成 session summary memory
- 写入 LanceDB,并打上
type = session-summary
但当前 README 与代码都明确表达了一个操作建议:
- 这条能力默认不启用
- 因为大段 session summary 容易污染高质量检索
14.2 `jsonl_distill.py`
README 新增的批处理方案是另一条非常值得记录的架构支线:
- 通过
scripts/jsonl_distill.py增量读取 session JSONL - 过滤噪声
- 用专门 distiller agent 提炼高信号 lesson
- 最终通过
memory_store或memory-pro import回灌主库
这条链路说明本项目现在已经从“在线对话记忆插件”延伸到“离线记忆蒸馏平台”。
十五、测试覆盖说明
当前与新架构强相关的测试包括:
test/smart-memory-lifecycle.mjstest/retriever-rerank-regression.mjstest/smart-extractor-branches.mjstest/cli-smoke.mjs
这些测试分别覆盖:
- legacy metadata 归一化
- decay-aware retrieval 排序正确性
- tier promotion / demotion
- rerank 对强词法命中的保护
- smart extractor 的 merge / skip 分支
- CLI 的基础闭环
说明这套新架构已经不只是 README 层叙事,而是被纳入回归验证。
十六、核心文件职责索引
| 文件 | 当前职责 |
|---|---|
index.ts |
插件总装配器:配置解析、Hook、Tool、CLI、Service、生命周期闭环 |
src/store.ts |
LanceDB 存储层:初始化、FTS、vector/BM25、CRUD、metadata patch |
src/embedder.ts |
Embedding 抽象层:provider 适配、task embedding、chunking、cache |
src/chunker.ts |
长文本分块器 |
src/retriever.ts |
混合检索、rerank、length norm、decay boost、MMR |
src/smart-extractor.ts |
LLM 提取、嵌入噪声预过滤、两阶段去重、merge/create/skip、持久化 |
src/smart-metadata.ts |
metadata 归一化、兼容映射、lifecycle 视图转换 |
src/decay-engine.ts |
Weibull 衰减模型、搜索分数 boost |
src/tier-manager.ts |
三层记忆晋升/降级 |
src/scopes.ts |
多 scope 隔离与 agent 访问控制 |
src/tools.ts |
Agent Tools 平面 |
cli.ts |
运维 CLI 平面 |
src/migrate.ts |
从旧插件迁移 |
src/memory-upgrader.ts |
同库旧格式升级 |
src/noise-filter.ts |
写入/检索噪声过滤(regex 规则) |
src/noise-prototypes.ts |
嵌入噪声原型库:语言无关噪声检测 + LLM 反馈学习 |
src/adaptive-retrieval.ts |
auto-recall 检索守卫 |
十七、一句话总结
memory-lancedb-pro 当前的真实架构可以概括为:
用 smart-metadata 把新旧 memory 统一到一套数据平面,用 SmartExtractor 提升写入质量,用 Retriever + Decay + Tier 提升召回质量,再用 Tools / CLI / Migration / Backup 把它补成一个可运营的长期记忆子系统。
Openclaw Dream Retrofit Report (`docs/openclaw-dream-retrofit-report.md`)
OpenClaw Dream Retrofit Final Report
Date: 2026-05-23
Artifact path: docs/openclaw-dream-retrofit-report.md
No explicit output artifact path was present in the environment or repository metadata, so this report is written as a versioned repo artifact under docs/.
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Phase 0: memory capability bootstrap | Complete | Registered api.registerMemoryCapability with runtime, promptBuilder, flushPlanResolver, and publicArtifacts; retained legacy runtime fallback. |
| Phase 1: runtime contract parity | Complete | Added MemorySearchManager-compatible runtime returning grounded path/startLine/endLine/snippet/source/citation results and scoped retrieval. |
| Phase 2: canonical corpus + indexer foundation | Complete | Added canonical file/session/dream corpus discovery and LanceDB upsert indexing while keeping files as source of truth. |
| Phase 3: dreaming compatibility glue | Complete | Exposed dream reports and memory/.dreams/events.jsonl public artifacts; expanded dreaming schema to match memory-core execution/source config. |
| Phase 4/5: hardening and docs | Complete for this pass | Added focused tests, CI manifest coverage, README/playbook updates, and ran the core regression group. |
Implemented Outcomes
memory-lancedb-pronow registersapi.registerMemoryCapabilitywith:runtimepromptBuilderflushPlanResolverpublicArtifacts
- Plugin config schema now supports:
canonicalCorpusdreaming.enabled/frequency/model/timezone/storage/execution/phases- memory-core-compatible execution knobs:
speed,thinking,budget,maxOutputTokens,temperature,timeoutMs - phase source enums for light/deep/rem dreaming.
- Runtime search now returns grounded results with:
pathstartLineendLinesnippetsourcecitation
- Canonical corpus indexing now covers:
MEMORY.mdmemory/**/*.mdmemory/dreaming/**/*.md- recent
~/.openclaw/agents/<agentId>/sessions/*.jsonl
- LanceDB is used as the semantic index; canonical files remain source of truth.
- Dream/public artifact compatibility includes:
- dream reports as
dream-report memory/.dreams/events.jsonlasevent-log- public artifacts for
MEMORY.mdandmemory/**/*.md
- dream reports as
- Tests were added/updated for:
- capability registration
- runtime grounded results and source filtering
- canonical corpus discovery/indexing/read fallback
- dreaming schema compatibility
- public artifact discovery
- Docs were updated:
README.mddocs/openclaw-integration-playbook.md
Changed Files
README.mddocs/openclaw-integration-playbook.mdindex.tsopenclaw.plugin.jsonpackage.jsonscripts/ci-test-manifest.mjssrc/corpus-indexer.tssrc/openclaw-memory-capability.tssrc/store.tstest/corpus-indexer.test.mjstest/memory-capability-runtime.test.mjstest/plugin-manifest-regression.mjsdocs/openclaw-dream-retrofit-report.md
Commits Created
25f3522 feat: bootstrap OpenClaw memory capability8259e9a feat: add OpenClaw memory runtime adapter9f010a4 feat: index canonical OpenClaw memory corpus304ac34 feat: expose dreaming compatibility artifacts7cefffd docs: document OpenClaw memory capability modecdbf643 fix: harden canonical corpus indexing9e76b0c build: sync dist for OpenClaw runtime smoke
Backup Paths
Phase 0:
/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/index.ts.bak.20260523-105050/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/openclaw.plugin.json.bak.20260523-105050/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/plugin-manifest-regression.mjs.bak.20260523-105050
Phase 1:
/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/openclaw-memory-capability.ts.bak.20260523-105543/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/index.ts.bak.20260523-105543/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/package.json.bak.20260523-105749/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/ci-test-manifest.mjs.bak.20260523-105749/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/plugin-manifest-regression.mjs.bak.20260523-105849
Phase 2:
/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/store.ts.bak.20260523-110018/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/openclaw-memory-capability.ts.bak.20260523-110018/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/index.ts.bak.20260523-110018/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/package.json.bak.20260523-110018/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/ci-test-manifest.mjs.bak.20260523-110018/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/openclaw.plugin.json.bak.20260523-110119/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/plugin-manifest-regression.mjs.bak.20260523-110119/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/memory-capability-runtime.test.mjs.bak.20260523-110717
Phase 3:
/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/openclaw-memory-capability.ts.bak.20260523-111545/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/memory-capability-runtime.test.mjs.bak.20260523-111545/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/openclaw.plugin.json.bak.20260523-111706/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/plugin-manifest-regression.mjs.bak.20260523-111706
Phase 4/5:
/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/README.md.bak.20260523-111933/Users/choucheyu/.openclaw/workspace/memory/backups/2026-05-23/openclaw-integration-playbook.md.bak.20260523-111933
Checks Run
Baseline:
npm install- completed.npx tsc --noEmit- passed.node test/plugin-manifest-regression.mjs- passed.
Phase 0:
npx tsc --noEmit- passed.node test/plugin-manifest-regression.mjs- passed.
Phase 1:
npx tsc --noEmit- passed.node test/memory-capability-runtime.test.mjs- passed.node test/plugin-manifest-regression.mjs- passed.node scripts/verify-ci-test-manifest.mjs- passed.
Phase 2:
npx tsc --noEmit- passed.node test/corpus-indexer.test.mjs- passed.node test/memory-capability-runtime.test.mjs- passed.node test/plugin-manifest-regression.mjs- passed.node scripts/verify-ci-test-manifest.mjs- passed.git diff --check- passed.
Phase 3:
node -e "JSON.parse(require('node:fs').readFileSync('openclaw.plugin.json','utf8')); console.log('OK manifest JSON')"- passed.npx tsc --noEmit- passed.node test/plugin-manifest-regression.mjs- passed.node test/memory-capability-runtime.test.mjs- passed.git diff --check- passed.
Phase 4/5:
npx tsc --noEmit- passed.node test/corpus-indexer.test.mjs- passed.node test/memory-capability-runtime.test.mjs- passed.node test/plugin-manifest-regression.mjs- passed.node scripts/verify-ci-test-manifest.mjs- passed.npm run test:core-regression- passed.git diff --check- passed.
Live OpenClaw smoke:
- Isolated no-channel config validation - passed.
- Production gateway health check after smoke - passed.
- Production Telegram accounts health check after smoke - passed.
- Embedded OpenClaw agent memory tool registration - passed.
memory_store+memory_recallsmoke - passed.- CRUD smoke (
memory_store,memory_recall,memory_update,memory_forget) - passed. - Public artifacts provider live listing against isolated workspace - passed.
/dreamingplugin command registration in isolated runtime inventory - passed./dreaming statushandler smoke - passed.- Real Telegram inbound
/dreaming statusdispatch - passed. node --test test/recall-text-cleanup.test.mjs test/auto-recall-query-length.test.mjs test/auto-recall-timeout.test.mjs test/per-agent-auto-recall.test.mjs test/auto-capture-cleanup.test.mjs test/governance-metadata.test.mjs test/plugin-manifest-regression.mjs- passed.
Live Integration Smoke Matrix
| Surface | Status | Evidence |
|---|---|---|
| Isolated OpenClaw config | Pass | openclaw.nochannels.dreaming.test.json and openclaw.nochannels.autohooks.test.json validated with valid: true. |
| Production safety | Pass | Only production gateway on 18789 remained after smoke; no 19889, smoke-dreaming, or openclaw agent leftovers. |
| Production health | Pass | Gateway health returned ok: true; Telegram accounts were running: true, connected: true, lastError: null. |
| Tool registration | Pass | Embedded agent prompt report exposed memory_recall, memory_store, memory_forget, memory_update. |
| Store/recall | Pass | Agent smoke returned stored: true, recalled: true. |
| Update/forget | Pass | CRUD smoke returned stored/recalledOriginal/updated/recalledUpdated/forgotten/absentAfterForget: true. |
| Public artifacts | Pass | Isolated workspace listed MEMORY.md as memory-root and memory/2026-05-23.md as daily-note. |
/dreaming registration |
Pass | Isolated runtime registered /dreaming from memory-core and created the managed dreaming cron sidecar. |
/dreaming status handler |
Pass | Handler returned enabled status, 0 3 * * * cadence, and promotion policy. |
| Auto-recall logic | Pass | Targeted regression tests passed, including cleanup, governance, timeout, query length, per-agent policy, and before-prompt hook behavior. |
| Auto-capture cleanup/schema | Pass | Targeted auto-capture cleanup and plugin-manifest tests passed. |
| Real inbound slash dispatch | Pass | Telegram inbound /dreaming status produced bot reply message 36015: enabled on, cadence 0 3 * * *, promotion policy score>=0.8, recalls>=3, uniqueQueries>=3; Gateway log also recorded telegram sendMessage ok ... message=36015. |
| Embedded CLI prompt injection | Not proven | openclaw agent --local exposes memory tools, but did not demonstrate before_prompt_build auto-recall injection in the live smoke path. |
Reviewer Notes
- The runtime adapter keeps existing
memory_recall/tool behavior intact and adds OpenClaw memory-host runtime compatibility. - Canonical corpus entries are stored with
openclaw_corpusmetadata and deterministiccorpus:<hash>ids, so repeated syncs update the semantic index entry for the same canonical artifact. MemoryStore.upsert()was added as a serialized delete/add path because LanceDB is used as an index over canonical artifacts, not the canonical source.- Session transcript parsing is deliberately conservative and best-effort: JSONL role/content blocks are rendered into searchable text and exposed as
source: "sessions". - Public artifact behavior now matches memory-core's important surfaces:
MEMORY.md, markdown memory files, dream reports, and the dreaming event log.
Remaining Risks And Edge Cases
- A full real inbound
/dreaming statusdispatch was later executed through Telegram and passed. OpenClaw 2026.5.18 still exposes only command inventory throughcommands.listover CLI/RPC, not a direct CLI/RPC command execution method; therefore the verified path is real provider inbound dispatch, not a synthetic Gateway RPC call. openclaw agent --local --message "/dreaming status"is not a valid slash-command smoke because plugin slash commands are Gateway command-dispatch features, not ordinary agent prompt text.- Embedded
openclaw agent --localsuccessfully exposes and runs memory tools, but did not prove livebefore_prompt_buildauto-recall prompt injection. Auto-recall behavior remains covered by targeted regression tests. - Canonical corpus sync is opportunistic through runtime search/sync, not a filesystem watcher.
- Session transcript classification does not yet reuse OpenClaw's internal dreaming/cron transcript classifier; users can disable transcript indexing with
canonicalCorpus.includeSessionTranscripts: falseif needed. - Full
npm testwas not run because the relevant broader gate isnpm run test:core-regression; focused gates and core regressions passed.
Openclaw Integration Playbook (`docs/openclaw-integration-playbook.md`)
OpenClaw Integration Playbook
This guide turns the integration and test findings for memory-lancedb-pro into a reusable checklist for two audiences:
- OpenClaw users who want a stable first deployment
- Maintainers who need a practical regression guide for future iterations
It is intentionally generic. It focuses on verifiable behavior, failure signatures, and operating rules instead of local machine paths.
0. Start with the correct user path
Before following the rest of this guide, classify your current state:
- new OpenClaw user or first-time memory setup
- existing OpenClaw user adding this plugin later
- existing
memory-lancedb-prouser upgrading from a pre-v1.1.0 release
The operating rule is:
upgradeis for oldermemory-lancedb-prodatamigrateis for built-inmemory-lancedbdatareembedis for embedding rebuilds, not routine upgrades
If you mix those paths, debugging becomes much harder because storage-format issues and retrieval-quality issues get conflated.
1. Recommended Deployment Modes
Choose one of these modes explicitly.
Mode A: Retrieval-first memory
Use this when you want:
memory_store/memory_recall- hybrid search (
vector + BM25) - auto-capture / auto-recall
- smart extraction and lifecycle ranking
Keep plugin session summaries disabled unless you have a concrete retrieval need for prior sessions.
Mode B: Retrieval + session-summary search
Use this when you also want /new to write a searchable session summary into LanceDB.
In this mode:
- set plugin
sessionStrategy: "memoryReflection"for LLM-powered reflection (structured extraction, dedup, lifecycle scoring) - decide whether OpenClaw built-in
session-memoryshould also remain enabled
Note: The legacy
sessionMemory.enabled = truemaps tosystemSessionMemory(simple session summary stored directly in LanceDB), notmemoryReflection. If you need the full reflection pipeline, usesessionStrategyexplicitly.
If both are enabled, /new can produce two outputs:
- built-in workspace/session summary files
- LanceDB session-summary memories written by
memory-lancedb-pro
That is valid, but it is a double-write design. If you do not want duplicated session summarization paths, keep only one.
Mode C: Retrieval + OpenClaw memory runtime and dreaming
Use this when memory-lancedb-pro owns plugins.slots.memory and OpenClaw should treat the plugin as the active memory capability.
In this mode:
- the plugin registers
runtime,promptBuilder,flushPlanResolver, andpublicArtifactsthroughapi.registerMemoryCapability canonicalCorpus.enabledindexesMEMORY.md,memory/**/*.md, recent session JSONL transcripts, andmemory/dreaming/**/*.mdinto LanceDB- the files remain the source of truth; LanceDB is the semantic index for grounded search
- runtime search results must include
path,startLine,endLine,snippet,source, andcitation - dream reports are exposed as
dream-reportpublic artifacts, andmemory/.dreams/events.jsonlis exposed as the dreaming event log
If dreaming.enabled is true, OpenClaw may load the built-in memory-core dreaming sidecar while keeping memory-lancedb-pro as the selected memory slot owner. Keep the dreaming config under the memory-lancedb-pro plugin entry so OpenClaw resolves the sidecar against the active memory plugin.
2. Recommended Session Memory Strategy
For most users, use one of these patterns.
Option 1: Disabled (no plugin session hooks)
Choose this when you mainly want transcript persistence and workspace summaries without plugin involvement.
- plugin
sessionStrategy: "none"(or omitsessionStrategyentirely) - OpenClaw built-in
hooks.internal.entries.session-memory.enabled = true
Option 2: Plugin only (LLM reflection)
Choose this when you want session summaries to participate in LanceDB retrieval with LLM-powered structured extraction, dedup, and lifecycle scoring.
- plugin
sessionStrategy: "memoryReflection" - OpenClaw built-in
hooks.internal.entries.session-memory.enabled = false
Option 3: Plugin only (simple summary)
Choose this when you want session summaries stored in LanceDB but do not need the full LLM reflection pipeline.
- plugin
sessionStrategy: "systemSessionMemory" - OpenClaw built-in
hooks.internal.entries.session-memory.enabled = false
This writes a plain session summary directly into LanceDB as fact / peripheral tier entries, without LLM-driven dedup or lifecycle scoring.
Option 4: Dual write
Choose this only if you explicitly want both:
- workspace markdown/session artifacts (via built-in session-memory)
- LanceDB-searchable session memories (via plugin
sessionStrategy)
If you use dual write, document it for your team. Otherwise it will look like duplicate behavior during debugging.
Strategy comparison
| Configuration | Strategy | Behavior |
|---|---|---|
sessionStrategy: "memoryReflection" |
memoryReflection | LLM-powered reflection: structured extraction, dedup, lifecycle scoring |
sessionStrategy: "systemSessionMemory" |
systemSessionMemory | Simple session summary stored directly in LanceDB as fact/peripheral |
sessionMemory: { enabled: true } |
systemSessionMemory | Legacy shorthand, same as systemSessionMemory above |
sessionStrategy: "none" or omitted |
none | Plugin session hooks disabled |
3. Baseline Verification Checklist
Run this before debugging retrieval quality.
openclaw config validate
openclaw status
openclaw gateway status
openclaw plugins info memory-lancedb-pro
openclaw hooks list --jsonConfirm:
- plugin is loaded from the expected path
plugins.slots.memorypoints tomemory-lancedb-pro- the plugin registers a memory capability, not only legacy hooks/tools
- the expected hooks are enabled
- the gateway has been restarted after config changes
- for multi-agent or multi-process write tests, the deployment matches the
lock-management requirements
If you use plugin session memory, openclaw hooks list --json should show the plugin hook:
memory-lancedb-pro-session-memory
If you want plugin-only session summaries, also confirm:
- built-in
session-memoryis disabled
4. Fresh-Agent Bootstrap Checks
When a newly created agent fails on its first real turn, do not start with retrieval debugging. Verify agent bootstrap first.
Typical symptom:
Unknown model: openai-codex/gpt-5.4
Common root cause:
- the new agent has not been initialized with agent-local model/auth indexes
Verify these files exist under the new agent directory:
~/.openclaw/agents/<agentId>/agent/models.json~/.openclaw/agents/<agentId>/agent/auth-profiles.json
Also verify the agent can resolve at least one usable model before testing memory behavior.
Practical rule:
- if a fresh agent cannot complete a plain text turn, memory tests on that agent are not meaningful yet
5. Retrieval Quality Rules
Short CJK keyword queries need explicit validation
Short Chinese keywords are a common false-negative case in hybrid retrieval systems.
Observed pattern during testing:
- unique identifiers or full sentences recall well
- short CJK keywords may depend on BM25/lexical matching quality
- lowering
minScorecan improve recall but often increases noise
Recommended tuning order:
- verify BM25 / lexical fallback behavior first
- verify hybrid fusion behavior second
- tune
minScore/hardMinScorelast
Do not start by aggressively lowering thresholds. That often converts a retrieval-quality problem into a relevance-noise problem.
Lifecycle scoring must not suppress strong fresh hits
If you use lifecycle decay and tiering:
- apply relevance filtering before lifecycle/time decay demotion
- ensure new
workingmemories are not pushed belowhardMinScoresimply because decay was applied too early
Regression target:
- a fresh, high-relevance working-tier memory must remain retrievable
6. Functional Smoke Tests
These tests cover the core closed loop.
CLI and storage
openclaw memory-pro stats
openclaw memory-pro list --scope global --limit 5
openclaw memory-pro search "your test keyword" --scope global --limit 5Validate:
- stats returns usable counts
- list returns stored items in the expected scope
- search returns deterministic results for at least one exact identifier and one natural-language query
Tool loop
Validate at least once:
memory_storememory_recallmemory_updatememory_forgetmemory_listmemory_stats
OpenClaw memory runtime loop
When canonicalCorpus.enabled is true, create a temporary markdown note under memory/YYYY-MM-DD.md and verify runtime memory search can return it with:
source: "memory"- a real workspace-relative path, not only a
memory-lancedb-pro/.mdvirtual path - line numbers and a snippet that match the file
For session transcript coverage, verify a recent ~/.openclaw/agents/<agentId>/sessions/*.jsonl entry can be returned with source: "sessions" when session transcript indexing is enabled.
For dreaming coverage, verify that memory/dreaming/*.md appears as a dream-report public artifact and that memory/.dreams/events.jsonl appears as an event-log public artifact when present.
Public X/Twitter source capture
Use this optional recipe when an OpenClaw agent gathers public X/Twitter context through TweetClaw and you want a reviewed source summary to become searchable memory.
Allowed source actions:
- search public tweets or replies
- look up a public user profile
- export public follower or media metadata when the workflow needs it
- consume monitors or webhooks that report public tweet events
Before calling memory_store, review the source result and keep only durable research context:
- tweet URL
- author handle
- published timestamp
- short text excerpt or human-written summary
- relevant metrics, if needed for the research task
- query or monitor that found the source
- capture date
Store the reviewed summary as category: "fact" for source evidence or category: "decision" when the team has made a decision from that evidence. Include the public source URL and capture date in the memory text or metadata so later recall can cite where the information came from.
Never store secrets or private account material from this flow:
- API keys, cookies, bearer tokens, or account credentials
- direct-message content
- draft post or reply text
- non-public profile, follower, or media data
Keep visible X/Twitter actions outside the memory plugin. Posting tweets, posting replies, sending direct messages, uploading media, and downloading media require explicit user approval in the tool workflow that performs the action. memory-lancedb-pro should only persist the reviewed summary after that workflow has produced safe public source context.
Verification checklist:
- the stored memory contains the public URL and capture date
- the text is a summary or short excerpt, not a raw transcript dump
- no credentials, cookies, direct messages, or draft text appear in the memory
- any visible action on X/Twitter was approved outside the memory plugin
Scope isolation
Validate at least:
main -> mainhitsmain -> workmisswork -> globalallowed if intendedlife -> workmiss unless explicitly permitted
Smart extraction stability
Validate the three semantic branches:
createmergeskip
Then run a multi-turn sequence such as:
create -> skip -> merge -> skip
Expected result:
- one stable memory record
- duplicates suppressed
- new facts merged without unbounded duplication
7. Real `/new` Session Test
If plugin session memory is enabled, run one real /new validation after the basic smoke tests.
Check for three facts:
- the active session changes
- the expected hook fires
- the summary lands in the intended storage path
Plugin evidence should look like:
- a log entry that the session summary was stored for the previous session
If built-in session memory is also enabled, you should additionally see the built-in workspace/session artifact.
If built-in session memory is disabled, do not treat the absence of a workspace session-summary markdown file as a plugin failure.
8. Recommended Regression Matrix
Run this matrix before release candidates or after major retrieval changes.
Integration
- plugin loads successfully
- gateway restart preserves plugin registration
hooks listshows expected hook state
Retrieval
- exact identifier recall
- short CJK keyword recall
- full sentence semantic recall
- rerank fallback behavior when reranker is unavailable
Memory lifecycle
- fresh
workingmemory remains retrievable - tier promotion/demotion does not erase useful recall
Extraction
createmergeskip- multi-turn duplicate suppression
Session flow
/newtriggers the intended hook path- plugin-only mode does not rely on built-in session artifacts
- dual-write mode is explicit and understood
Canonical corpus and dreaming
MEMORY.mdandmemory/**/*.mdstay readable as files- LanceDB contains indexed corpus entries with
openclaw_corpusmetadata - session transcript indexing can be disabled independently with
canonicalCorpus.includeSessionTranscripts - dreaming config validates under the
memory-lancedb-proplugin entry - public artifacts include dream reports and the dreaming event log when files exist
Agent bootstrap
- newly added agent can complete its first turn
- new agent has usable model/auth indexes
9. Troubleshooting Patterns
Search returns empty, but the store contains data
Check in this order:
- scope mismatch
minScore/hardMinScore- BM25 / lexical fallback availability
- rerank endpoint health
- lifecycle decay ordering
`/new` appears to do nothing
Check:
- plugin
sessionStrategyis set to"memoryReflection"or"systemSessionMemory"(not"none") - plugin hook is actually registered and named
- gateway has been restarted after the hook/config change
- built-in hook state matches your intended design
Results became noisy after tuning
Likely cause:
- threshold reduction solved recall at the cost of precision
Preferred fix order:
- lexical/BM25 improvement
- hybrid-fusion tuning
- rerank tuning
- threshold change
10. Upgrade and Maintenance Notes
If you maintain local patches against the OpenClaw installation itself, treat them as temporary operational fixes, not durable plugin behavior.
After any openclaw update, re-check:
- fresh-agent bootstrap
- model provider resolution for newly added agents
- hook registration state
/newbehavior
If your team depends on local installation patches, keep them in a repeatable patch or automation script outside the plugin repo.
11. Recommended Documentation Policy for Future Changes
When changing retrieval or hook behavior, update all three artifacts together:
- user-facing README summary
- this integration playbook
- regression tests that prove the changed behavior
That keeps operational guidance aligned with actual behavior and prevents README drift.
Openclaw Integration Playbook.Zh CN (`docs/openclaw-integration-playbook.zh-CN.md`)
OpenClaw 集成与迭代手册
这份文档把 memory-lancedb-pro 在真实 OpenClaw 环境中的集成、联调和回归测试经验整理成一套可复用说明,面向两类读者:
- 初次接入 OpenClaw 的新用户
- 后续继续迭代检索、Hook、生命周期逻辑的维护者
目标不是记录某一台机器的细节,而是沉淀可验证的行为、常见故障特征和维护规则。
0. 先选对自己的使用路径
在继续看后面的章节前,先判断你目前属于哪一类:
- 新 OpenClaw 用户,或第一次接入记忆能力
- 已经用了 OpenClaw 一段时间,现在再接入本插件
- 已经在用旧版
memory-lancedb-pro,准备从 v1.1.0 之前升级
必须先分清三条命令的用途:
upgrade:针对旧版memory-lancedb-pro数据migrate:针对内置memory-lancedb数据reembed:针对向量重建,不是常规升级步骤
如果把这三条路径混在一起,后续很容易把“数据格式问题”和“检索质量问题”混为一谈。
1. 推荐部署模式
建议先明确采用哪一种模式,再开始调参。
模式 A:以检索为主
适用场景:
- 使用
memory_store/memory_recall - 需要混合检索(
vector + BM25) - 开启 auto-capture / auto-recall
- 使用 smart extraction 和 lifecycle ranking
这类场景下,除非你确实需要“把旧 session 摘要也作为可检索记忆”,否则不建议默认开启插件侧 session summary。
模式 B:检索 + session summary 可检索
适用场景:
- 除常规长期记忆外,还希望
/new时把上一个 session 摘要写入 LanceDB,参与后续检索
这时需要:
- 设置插件
sessionStrategy: "memoryReflection"(LLM 结构化反思:去重、错误追踪、lifecycle 评分) - 明确决定是否保留 OpenClaw 内置
session-memory
注意: 旧版
sessionMemory.enabled = true实际映射为systemSessionMemory(简单摘要直存 LanceDB),而非memoryReflection。如需完整反思管线,请显式使用sessionStrategy。
如果两者同时开启,/new 可能产生两类结果:
- OpenClaw 内置的 workspace/session 摘要文件
memory-lancedb-pro写入 LanceDB 的 session-summary 记忆
这不是错误,但属于双写设计。若不希望排障时出现“看起来重复”的现象,应只保留一种路径。
2. Session Memory 选型建议
大部分场景推荐三选一,而不是默认双开。
方案 1:禁用(不启用插件 session hook)
适合:
- 主要想保留会话摘要文件
- 不要求 session summary 参与 LanceDB 检索
建议配置:
- 插件
sessionStrategy: "none"(或不设置sessionStrategy) - OpenClaw
hooks.internal.entries.session-memory.enabled = true
方案 2:只用插件(LLM 反思模式)
适合:
- 希望 session summary 进入 LanceDB
- 需要 LLM 结构化提取、去重、lifecycle 评分
建议配置:
- 插件
sessionStrategy: "memoryReflection" - OpenClaw
hooks.internal.entries.session-memory.enabled = false
方案 3:只用插件(简单摘要模式)
适合:
- 希望 session summary 存入 LanceDB
- 不需要 LLM 反思管线
建议配置:
- 插件
sessionStrategy: "systemSessionMemory" - OpenClaw
hooks.internal.entries.session-memory.enabled = false
此模式将会话摘要直接写入 LanceDB,存为 fact / peripheral 层级条目,不经过 LLM 去重或 lifecycle 评分。
方案 4:双写
只在你明确需要以下两类产物时使用:
- workspace 中的摘要文件(通过内置 session-memory)
- LanceDB 中可检索的 session 记忆(通过插件
sessionStrategy)
若采用双写,建议在团队文档中写清楚,否则后续维护者容易把它误判成重复存储问题。
策略对照表
| 配置方式 | 策略 | 行为 |
|---|---|---|
sessionStrategy: "memoryReflection" |
memoryReflection | LLM 结构化反思:提取、去重、lifecycle 评分 |
sessionStrategy: "systemSessionMemory" |
systemSessionMemory | 简单会话摘要直存 LanceDB(fact/peripheral 层级) |
sessionMemory: { enabled: true } |
systemSessionMemory | 旧版简写,等同于上面的 systemSessionMemory |
sessionStrategy: "none" 或不设置 |
none | 插件 session hook 不启用 |
3. 基线检查清单
在开始调检索质量之前,先确认基础集成是通的。
openclaw config validate
openclaw status
openclaw gateway status
openclaw plugins info memory-lancedb-pro
openclaw hooks list --json至少确认:
- 插件从预期路径加载
plugins.slots.memory指向memory-lancedb-pro- 预期 Hook 处于启用状态
- 改完配置后 Gateway 已重启
如果启用了插件侧 session memory,openclaw hooks list --json 里应能看到:
memory-lancedb-pro-session-memory
如果目标是插件单写模式,还应同时确认:
- 内置
session-memory已禁用
4. 新 Agent 引导检查
新 Agent 首轮真实对话失败时,不要先怀疑检索。先检查 Agent 启动链路。
典型症状:
Unknown model: openai-codex/gpt-5.4
常见根因:
- 新 Agent 没有初始化本地模型/认证索引
建议检查以下文件是否存在:
~/.openclaw/agents/<agentId>/agent/models.json~/.openclaw/agents/<agentId>/agent/auth-profiles.json
并确认该 Agent 至少能先跑通一次普通文本对话,再做记忆相关测试。
工程上可以直接采用这条规则:
- 如果新 Agent 连普通 turn 都跑不通,那么该 Agent 上的 memory 测试结论没有意义
5. 检索质量规则
短中文关键词必须单独验证
短中文词是混合检索里最常见的假阴性场景之一。
实测经验通常是:
- 唯一代号、完整句子更容易召回
- 短中文词更依赖 BM25 / 词法匹配质量
- 直接降低
minScore能提召回,但常常同时带来明显噪声
推荐调优顺序:
- 先确认 BM25 / 词法兜底是否有效
- 再确认 hybrid fusion 是否把强词法命中保留下来
- 最后再调
minScore/hardMinScore
不要把“先大幅降阈值”当成默认修复方案。那通常只是把“召回问题”换成了“精度问题”。
生命周期排序不能误杀高相关新记忆
如果启用了 lifecycle decay 和 tiering,需要保证:
- 先按相关性裁剪,再施加 lifecycle/time decay
- 新写入的
working记忆不会因为衰减顺序不当,被压到hardMinScore以下
建议把下面这条作为回归目标:
- 新鲜且高相关的
working记忆必须可召回
6. 功能烟测清单
以下检查能覆盖主要闭环。
CLI 与存储
openclaw memory-pro stats
openclaw memory-pro list --scope global --limit 5
openclaw memory-pro search "your test keyword" --scope global --limit 5至少验证:
stats能返回统计信息list能看到预期 scope 下的数据search对“唯一标识符”和“自然语言查询”都至少有一个稳定命中
工具闭环
至少完整测一轮:
memory_storememory_recallmemory_updatememory_forgetmemory_listmemory_stats
Scope 隔离
至少验证以下方向:
main -> main命中main -> work不命中work -> global若设计允许,应命中life -> work除非显式授权,否则不命中
Smart Extraction 稳定性
至少验证三种语义分支:
createmergeskip
然后再做一组多轮序列:
create -> skip -> merge -> skip
预期结果:
- 库里仍只有一条稳定记忆
- 重复内容被抑制
- 新信息被合并,而不是无限新增重复条目
7. 真实 `/new` 会话测试
如果启用了插件侧 session memory,基础烟测后应再做一次真实 /new 验证。
重点确认三件事:
- 活跃 session 确实切换
- 预期 Hook 确实触发
- 摘要写到了你期望的存储路径
插件侧的有效证据应表现为:
- 日志里出现“已为上一会话保存 session summary”的记录
如果同时保留内置 session-memory,还应看到内置 workspace/session 摘要产物。
如果内置 session-memory 已禁用,那么“没有看到 workspace session-summary markdown”不能直接判定为插件失败。
8. 推荐回归矩阵
每次准备发布、或修改检索 / Hook / 生命周期逻辑后,建议至少跑下面这组回归。
集成
- 插件可正常加载
- Gateway 重启后 Hook 注册状态不丢失
hooks list与预期一致
检索
- 唯一标识符召回
- 短中文关键词召回
- 完整句子语义召回
- rerank 服务不可用时的降级路径
生命周期
- fresh
working记忆仍能召回 - tier 升降不会导致有用记忆被过早过滤
提取
createmergeskip- 多轮重复抑制
Session 流程
/new触发到预期 Hook- plugin-only 模式不依赖内置 session 文件
- dual-write 模式是显式设计,而不是误配
Agent 引导
- 新增 Agent 首轮真实对话可成功
- 新 Agent 模型/认证索引完整
9. 常见排障模式
search 返回空,但库里明明有数据
按这个顺序排查:
- scope 是否错了
minScore/hardMinScore是否过高- BM25 / 词法兜底是否有效
- rerank endpoint 是否可用
- lifecycle decay 排序顺序是否合理
`/new` 看起来没生效
优先检查:
- 插件
sessionStrategy是否设为"memoryReflection"或"systemSessionMemory"(而非"none") - 插件 Hook 是否真的注册成功且有名字
- 改完配置后 Gateway 是否已重启
- 内置 Hook 状态是否符合当前设计
调参后召回上去了,但噪声变多
这通常意味着:
- 你用降阈值解决了召回,但牺牲了精度
优先修复顺序建议是:
- 词法 / BM25 能力
- hybrid fusion 规则
- rerank 策略
- 阈值调整
10. 升级与维护说明
如果你对 OpenClaw 安装本体做过本地补丁,请把它视为运行时修复,而不是插件自身的长期保证。
每次执行 openclaw update 之后,至少重新检查:
- 新 Agent 引导是否正常
- 新 Agent 的模型 provider 是否能解析
- Hook 注册状态是否仍正确
/new行为是否符合预期
如果团队依赖这些安装侧补丁,建议把补丁过程整理成独立 patch 或脚本,不要只依赖手工修改。
11. 后续文档维护建议
以后凡是修改以下行为之一:
- 检索逻辑
- Hook 注册方式
- 生命周期排序
- session summary 路径
建议同步更新三处内容:
- README 中的用户级摘要
- 本文档
- 对应回归测试
这样可以避免“实现已变,但文档和测试还停留在旧行为”的漂移问题。
Release Checklist (`docs/release-checklist.md`)
Release Checklist
Use this checklist before publishing a new memory-lancedb-pro package. It is
intended for the release tracked in #812 and future beta/stable cuts.
Release Target
- Current package version:
1.1.0-beta.11 - Recommended first publish: beta dist-tag
- Stable channel decision: maintainer-owned after beta smoke testing
The current release driver is that npm users are still behind repositorymaster: merged fixes are not available from the published latest package,
and the beta dist-tag still points at an older beta package.
Preflight
Run these from a clean checkout:
npm ci
npm run test:packaging-and-workflow
npm run build
npm pack --dry-runConfirm:
package.jsonandopenclaw.plugin.jsonversions matchpackage.json mainpoints atdist/index.jspackage.json openclaw.extensionspoints at./dist/index.jspackage.json filesincludesdist/**/*CHANGELOG.mdandCHANGELOG-v1.1.0.mdstart with the package versionnpm pack --dry-runincludes compileddistoutput and excludes test files
Publish Dry Run
npm publish --tag beta --dry-runReview the file list and package metadata before publishing.
Publish
npm publish --tag betaAfter publish, verify the public registry state:
npm view memory-lancedb-pro dist-tags version versions --json
npm view memory-lancedb-pro@beta version main openclaw files --jsonThe beta dist-tag should point at the newly published version, and the package
runtime entries should point at compiled JavaScript under dist/.
Post-Publish Smoke
On a machine with a current OpenClaw install:
openclaw plugins registry --refresh
openclaw plugins install memory-lancedb-pro@beta
openclaw plugins doctorConfirm OpenClaw installs the package without falling back to TypeScript source
entrypoints.
Notes Reflection Write Path Findings (`docs/notes/reflection-write-path-findings.md`)
Reflection write-path findings
Findings from a code-plus-trace audit of the reflection persistence paths.
Kept here as discussion material; each item states what the code does today
and what remains open.
Two writers, different gates
The reflection distiller output is persisted by two independent writers:
Writer 1 (mapped rows). Four headings of the reflection markdown
(User model deltas, Agent model deltas, Lessons & pitfalls, Decisions)
are parsed into individual rows (extractInjectableReflectionMappedMemoryItems)
and bulk-stored as ordinary memories withmetadata.type = "memory-reflection-mapped". Until the accompanying change, this path had
no admission gate and no gating knob;reflectionStoreToLanceDBgates
only writer 2. Mapped rows now route through the same AdmissionController
as extraction candidates when admission control is enabled (passthrough
when disabled, fail-open on infra errors). Scoring category mapping:preference(user/agent model deltas) scores aspreferences,fact
(lessons) ascases,decisionasevents.Writer 2 (reflection documents).
storeReflectionToLanceDBpersists
sliced reflection documents under categoryreflection, gated by thereflectionStoreToLanceDBconfig knob. Unchanged by this work.
Dead reader
loadReflectionMappedRowsFromEntries (reflection-store) was built to read
mapped rows back for a dedicated injection path, but it has no production
callers (only a test imports it). The only living read path for mapped rows
is generic semantic recall. A code comment now marks this. Open question:
either wire the dedicated reader or consider retiring mapped rows in favor
of writer 2 plus recall.
Cross-writer double-store
"Decisions (durable)" bullets can be persisted twice: once by writer 1 as adecision row, and once inside writer 2's document slices (invariant
fallback). There is no cross-lane dedup between the two writers. Any future
dedup would need to compare across metadata.type values.
memory_layer parity question
The auto-recall governance filter drops entries with memory_layer in{archive, reflection}, but only the dreaming engine sets layerreflection. Mapped rows carry layer semantics of ordinary confirmed
memories, so they pass recall filters that reflection-layer content does
not. If mapped rows are conceptually reflection output, they may deserve
the same layer tag; if they are conceptually ordinary memories, the
admission gate added here is the appropriate control. Left as a design
question.
Auto-capture watermark
The per-session auto-capture cursor (autoCaptureSeenTextCount) is reset
to zero after every successful smart extraction, which makes the next
capture of the same session re-read the whole history instead of the
delta. Analysis and fix (recording the consumed length instead) are on the
dedicated watermark fix branch.
Residual gap
The mapped-row admission gate reuses the SmartExtractor's controller
instance. When smart extraction is disabled while admission control is
enabled, mapped rows still pass ungated (no controller exists to borrow).
This mirrors the pre-change behavior and is called out here for
completeness.
--- METRICS ---
- Files Extracted: 11
- Estimated Token Budget: ~30327 tokens
- Canonical Reference: https://codewiki.google/github.com/CortexReach/memory-lancedb-pro