memory-braid
v0.4.4
Published
OpenClaw memory plugin that augments local memory with Mem0 capture and recall.
Downloads
1,026
Maintainers
Readme
Memory Braid
Memory Braid is an OpenClaw kind: "memory" plugin that augments local memory search (core/QMD) with Mem0.
Features
- Hybrid recall: local memory + Mem0, merged with weighted RRF.
- Capture-first Mem0 memory: plugin writes only captured memories to Mem0 (no markdown/session indexing).
- Capture pipeline modes:
local,hybrid,ml. - Optional entity extraction: multilingual NER with canonical
entity://...URIs in memory metadata. - Structured debug logs for troubleshooting and tuning.
Breaking changes in 0.4.0
Memory Braid 0.4.0 is intentionally simplified to capture/recall-only mode.
- Removed managed indexing features:
bootstrapconfig block removed.reconcileconfig block removed.- startup bootstrap/reconcile flows removed.
- Mem0 is now used only for captured memories.
- markdown and session indexing is no longer done by this plugin.
- local markdown/session retrieval remains in core/QMD via
memory_search.
/memorybraid statsnow reports capture + lifecycle only (no reconcile section).- Legacy Mem0 records with
metadata.sourceTypeofmarkdownorsessionare ignored during Mem0 recall merge.
Migration:
- If you relied on bootstrap/reconcile mirroring, pin to
<0.4.0. - For
0.4.0+, removebootstrapandreconcilefrom your plugin config. - Keep core/QMD as the source for markdown/sessions, and use Memory Braid for capture/mem0 recall/lifecycle.
Install
Install from npm (recommended)
On the target machine:
- Install from npm:
openclaw plugins install [email protected]- Rebuild native dependencies inside the installed extension:
cd ~/.openclaw/extensions/memory-braid
npm rebuild sqlite3 sharpWhy this step exists:
- OpenClaw plugin installs run
npm install --omit=dev --ignore-scriptsfor safety. - This behavior is currently not user-overridable from
openclaw plugins install. memory-braidneeds native artifacts forsqlite3(required by Mem0 OSS) andsharp(used by@xenova/transformers).
- Enable and set as active memory slot:
openclaw plugins enable memory-braid
openclaw config set plugins.slots.memory memory-braid- Restart gateway:
openclaw gateway restart- Confirm plugin is loaded:
openclaw plugins info memory-braidExpected:
Status: loadedTools: memory_search, memory_getServices: memory-braid-service
Install from local path (development)
openclaw plugins install --link /absolute/path/to/memory-braid
openclaw plugins enable memory-braid
openclaw config set plugins.slots.memory memory-braid
openclaw gateway restartIf you install from npm and see native module errors like:
Could not locate the bindings file(sqlite3).../node_modules/jiti/.../node_sqlite3.nodein the stack/error textCannot find module ... sharp-*.node
run:
cd ~/.openclaw/extensions/memory-braid
npm rebuild sqlite3 sharp
openclaw gateway restartNote:
- The
jiti/.../node_sqlite3.nodeerror is still a sqlite native artifact/runtime loading issue. memory-braidnow preloads sqlite via nativerequireto avoid that path, but you still neednpm rebuild sqlite3 sharpafter--ignore-scriptsinstalls.- When this happens, startup logs now include
memory_braid.mem0.errorwith:sqliteBindingsError: truefixCommand(copy/paste command for that machine)pluginDir(resolved extension directory when available)
Quick start: hybrid capture + multilingual NER
Add this under plugins.entries["memory-braid"].config in your OpenClaw config:
{
"mem0": {
"mode": "oss",
"ossConfig": {
"version": "v1.1",
"embedder": {
"provider": "openai",
"config": {
"apiKey": "${OPENAI_API_KEY}",
"model": "text-embedding-3-small"
}
},
"vectorStore": {
"provider": "memory",
"config": {
"collectionName": "memories",
"dimension": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"apiKey": "${OPENAI_API_KEY}",
"model": "gpt-4o-mini"
}
},
"enableGraph": false
}
},
"capture": {
"enabled": true,
"mode": "hybrid",
"includeAssistant": false,
"maxItemsPerRun": 6,
"ml": {
"provider": "openai",
"model": "gpt-4o-mini",
"timeoutMs": 2500
}
},
"entityExtraction": {
"enabled": true,
"provider": "multilingual_ner",
"model": "Xenova/bert-base-multilingual-cased-ner-hrl",
"minScore": 0.65,
"maxEntitiesPerMemory": 8,
"startup": {
"downloadOnStartup": true,
"warmupText": "John works at Acme in Berlin."
}
},
"debug": {
"enabled": true
}
}Then restart:
openclaw gateway restartVerification checklist
- Check runtime status:
openclaw plugins info memory-braid
openclaw gateway status- Trigger/inspect NER warmup:
openclaw agent --agent main --message "/memorybraid warmup" --json- Send a message that should be captured:
openclaw agent --agent main --message "Remember that Ana works at OpenClaw and likes ramen." --json- Inspect logs for capture + NER:
rg -n "memory_braid\\.startup|memory_braid\\.capture|memory_braid\\.entity|memory_braid\\.mem0" ~/.openclaw/logs/gateway.log | tail -n 80Expected events:
memory_braid.startupmemory_braid.entity.model_loadmemory_braid.entity.warmupmemory_braid.capture.extractmemory_braid.capture.ml(forcapture.mode=hybrid|ml)memory_braid.entity.extractmemory_braid.capture.persist
Self-hosting quick guide
Memory Braid supports two self-hosted setups:
- API-compatible mode (
mem0.mode: "cloud"+mem0.host): run a Mem0-compatible API service and point the plugin to it. - OSS in-process mode (
mem0.mode: "oss"+mem0.ossConfig): run Mem0 OSS directly in the OpenClaw process.
Option A: self-hosted API-compatible mode
- Deploy your Mem0 API-compatible stack in your infra (Docker/K8s/VM).
- Make sure it is reachable from the OpenClaw host.
- Configure Memory Braid with:
mem0.mode: "cloud"mem0.host: "http://<your-mem0-host>:<port>"mem0.apiKey
- Restart OpenClaw.
- Validate connectivity:
curl -sS http://<your-mem0-host>:<port>/v1/ping/- Then run one OpenClaw turn and confirm logs include
memory_braid.mem0.requestandmemory_braid.mem0.response.
Option B: OSS in-process mode (recommended for local/self-hosted tests)
- Set
mem0.modetooss. - Provide
mem0.ossConfigwith:embedder(provider + credentials/model)vectorStore(provider + connection/config)llm(provider + model; used by Mem0 OSS internals)- Partial
ossConfigis safe: Memory Braid deep-merges your values over OSS defaults.- If a section provider changes (for example
embedder.provider: "ollama"), that section is replaced instead of mixed.
- If a section provider changes (for example
- Restart OpenClaw.
- Send at least one message to trigger capture/recall.
- Check logs for:
memory_braid.startupmemory_braid.mem0.request|response
Smoke test checklist
- Enable debug:
plugins.memory-braid.debug.enabled: true
- Start OpenClaw.
- Send a preference/decision statement.
- Confirm later
memory_searchruns return merged local+Mem0 results. - Run
/memorybraid statsto verify capture counters increase.
Notes
- Memory Braid 0.4.0 is capture/recall-only by design: markdown and session indexing stay in core/QMD.
- If self-hosted infra is down, local memory tools continue working; Mem0 side degrades gracefully.
- For Mem0 platform/API specifics, see official docs: Mem0 OSS quickstart and Mem0 API reference.
Required config (Cloud API mode)
At minimum, provide Mem0 credentials:
{
"plugins": {
"slots": {
"memory": "memory-braid"
},
"memory-braid": {
"mem0": {
"apiKey": "${MEM0_API_KEY}"
}
}
}
}For self-hosted Mem0 API-compatible deployments, also set mem0.host:
{
"plugins": {
"memory-braid": {
"mem0": {
"mode": "cloud",
"host": "http://localhost:8000",
"apiKey": "${MEM0_API_KEY}"
}
}
}
}Required config (OSS self-hosted mode)
If you want mem0ai/oss directly, set mem0.mode to oss and pass an ossConfig.
By default, Memory Braid now auto-creates a state folder at
<OPENCLAW_STATE_DIR>/memory-braid (typically ~/.openclaw/memory-braid) and uses:
mem0-history.dbfor Mem0 history SQLitemem0-vector-store.dbfor Mem0 in-memory vector store SQLite backend (vectorStore.provider: "memory")
You only need to set explicit DB paths if you want non-default locations.
{
"plugins": {
"memory-braid": {
"mem0": {
"mode": "oss",
"ossConfig": {
"version": "v1.1",
"embedder": {
"provider": "openai",
"config": {
"apiKey": "${OPENAI_API_KEY}",
"model": "text-embedding-3-small"
}
},
"vectorStore": {
"provider": "memory",
"config": {
"collectionName": "memories",
"dimension": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"apiKey": "${OPENAI_API_KEY}",
"model": "gpt-4o-mini"
}
},
"enableGraph": false
}
}
}
}
}Ready-made OSS preset: Qdrant + Ollama
Use this preset when:
- Your vector database is Qdrant.
- Your embedding and LLM provider is Ollama.
- OpenClaw can reach both services on your network.
{
"plugins": {
"memory-braid": {
"mem0": {
"mode": "oss",
"ossConfig": {
"version": "v1.1",
"embedder": {
"provider": "ollama",
"config": {
"url": "http://127.0.0.1:11434",
"model": "nomic-embed-text"
}
},
"vectorStore": {
"provider": "qdrant",
"config": {
"url": "http://127.0.0.1:6333",
"collectionName": "openclaw_memory_braid",
"dimension": 768
}
},
"llm": {
"provider": "ollama",
"config": {
"baseURL": "http://127.0.0.1:11434",
"model": "llama3.1:8b"
}
},
"enableGraph": false,
"disableHistory": true
}
}
}
}
}Quick validation for this preset
- Ensure models are available in Ollama:
ollama pull nomic-embed-textollama pull llama3.1:8b
- Ensure Qdrant is reachable:
curl -sS http://127.0.0.1:6333/collections
- Start OpenClaw with
debug.enabled: trueand verify:memory_braid.startupmemory_braid.mem0.responsewithmode: "oss"
Recommended config
{
"plugins": {
"slots": {
"memory": "memory-braid"
},
"memory-braid": {
"recall": {
"maxResults": 8,
"injectTopK": 5,
"merge": {
"rrfK": 60,
"localWeight": 1,
"mem0Weight": 1
}
},
"capture": {
"enabled": true,
"mode": "hybrid",
"includeAssistant": false,
"maxItemsPerRun": 6,
"ml": {
"provider": "openai",
"model": "gpt-4o-mini",
"timeoutMs": 2500
}
},
"entityExtraction": {
"enabled": true,
"provider": "multilingual_ner",
"model": "Xenova/bert-base-multilingual-cased-ner-hrl",
"minScore": 0.65,
"maxEntitiesPerMemory": 8,
"startup": {
"downloadOnStartup": true,
"warmupText": "John works at Acme in Berlin."
}
},
"dedupe": {
"lexical": { "minJaccard": 0.3 },
"semantic": { "enabled": true, "minScore": 0.92 }
},
"timeDecay": {
"enabled": false
},
"lifecycle": {
"enabled": false,
"captureTtlDays": 90,
"cleanupIntervalMinutes": 360,
"reinforceOnRecall": true
},
"debug": {
"enabled": false,
"includePayloads": false,
"maxSnippetChars": 500,
"logSamplingRate": 1
}
}
}
}Capture defaults
Capture defaults are:
capture.enabled:truecapture.mode:"local"capture.includeAssistant:false(default user-only capture)capture.maxItemsPerRun:6capture.ml.provider: unsetcapture.ml.model: unsetcapture.ml.timeoutMs:2500timeDecay.enabled:falselifecycle.enabled:falselifecycle.captureTtlDays:90lifecycle.cleanupIntervalMinutes:360lifecycle.reinforceOnRecall:true
Important behavior:
capture.mode = "local": heuristic-only extraction.capture.mode = "hybrid": heuristic extraction + ML enrichment when ML config is set.capture.mode = "ml": ML-first extraction; falls back to heuristic if ML config/call is unavailable.capture.includeAssistant = false(default): onlyusermessages are considered for capture.capture.includeAssistant = true: bothuserandassistantmessages are considered for capture.- ML calls run only when both
capture.ml.providerandcapture.ml.modelare set. timeDecay.enabled = true: applies temporal decay to Mem0 results using Memory Core'sagents.*.memorySearch.query.hybrid.temporalDecaysettings.- If Memory Core temporal decay is disabled, Mem0 decay is skipped even when
timeDecay.enabled = true. lifecycle.enabled = true: tracks captured Mem0 IDs, applies TTL cleanup, and exposes/memorybraid cleanup.lifecycle.reinforceOnRecall = true: successful recalls refresh lifecycle timestamps, extending TTL survival for frequently used memories.
Entity extraction defaults
Entity extraction defaults are:
entityExtraction.enabled:falseentityExtraction.provider:"multilingual_ner"entityExtraction.model:"Xenova/bert-base-multilingual-cased-ner-hrl"entityExtraction.minScore:0.65entityExtraction.maxEntitiesPerMemory:8entityExtraction.startup.downloadOnStartup:trueentityExtraction.startup.warmupText:"John works at Acme in Berlin."
When enabled:
- Model cache/download path is
<OPENCLAW_STATE_DIR>/memory-braid/models/entity-extraction(typically~/.openclaw/memory-braid/models/entity-extraction). - Captured memories get
metadata.entitiesandmetadata.entityUris(canonical IDs likeentity://person/john-doe). - Startup can pre-download/warm the model (
downloadOnStartup: true).
Warmup command:
/memorybraid status/memorybraid stats/memorybraid cleanup/memorybraid warmup/memorybraid warmup --force
Debugging
Set:
{
"plugins": {
"memory-braid": {
"debug": {
"enabled": true
}
}
}
}Key events:
memory_braid.startupmemory_braid.configmemory_braid.search.local|mem0|merge|inject|skipmemory_braid.search.mem0_decaymemory_braid.capture.extract|ml|persist|skipmemory_braid.lifecycle.reinforce|cleanupmemory_braid.entity.model_load|warmup|extractmemory_braid.mem0.request|response|error
debug.includePayloads=true includes payload fields; otherwise sensitive text fields are omitted.
memory_braid.search.inject now logs injectedTextPreview when payloads are enabled.
Traceability tips:
- Use
runIdto follow one execution end-to-end across capture/search/entity/mem0 events. memory_braid.capture.persistincludes high-signal counters:dedupeSkippedmem0AddAttemptsmem0AddWithIdmem0AddWithoutIdentityAnnotatedCandidatestotalEntitiesAttached
memory_braid.capture.mlincludesfallbackUsedand fallback reasons when ML is unavailable.memory_braid.entity.extractincludesentityTypesandsampleEntityUris.
Example:
rg -n "memory_braid\\.|runId\":\"<RUN_ID>\"" ~/.openclaw/logs/gateway.log | tail -n 120Tests
npm test