OpenClaw memory plugin that augments local memory with Mem0 capture and recall.
README
Memory Braid
Memory Braid is an OpenClaw kind: "memory" plugin that augments local memory search (core/QMD) with Mem0.
Ownership model
Memory Braid is intentionally hybrid, but not with shared ownership.
- OpenClaw prompt context + compaction are the source of truth for the live session.
- Core/QMD is the source of truth for written documents, notes, and canonical project knowledge.
- Mem0 is the source of truth for learned cross-session memory such as preferences, recurring decisions, and procedural learnings.
The goal is hybrid retrieval with single ownership per memory class. Memory Braid should not re-own markdown knowledge, and Mem0 should not be treated as the canonical store for documents.
Features
- Hybrid recall with split ownership: local memory + Mem0, merged with weighted RRF.
- Layered Mem0 memory: episodic captures, semantic compendium memories, and procedural agent learnings.
- Capture-first Mem0 memory: plugin writes only captured memories to Mem0 (no markdown/session indexing).
- Capture pipeline modes:
local,hybrid,ml. - Deterministic memory selection policy: ML may suggest candidates, but plugin code decides
ignore|episodic|procedural|semanticusing local thresholds and heuristics. - Optional entity extraction: local multilingual NER or OpenAI NER with canonical
entity://...URIs in memory metadata. - Lightweight taxonomy on captured and semantic memories:
people,places,organizations,projects,tools,topics. - Time-aware retrieval for month-style prompts such as
in June,this month, andlast month. - Automatic consolidation loop that promotes repeated episodic memories into semantic compendium memories.
- Structured debug logs for troubleshooting and tuning.
- Debug-only LLM usage observability: per-turn cache usage, rolling windows, and rising/stable/improving trend logs.
Hardening update
This release hardens capture and remediation for historical installs.
- Bug class: historical prompt or transcript content could be captured as Mem0 memories and later re-injected.
- Impact: inflated prompt size, noisier recall, and potentially higher Anthropic cache-write costs.
- Fix: new captures are assembled from the trusted current turn instead of mining the full
agent_endtranscript. - Metadata: new captured memories now include additive provenance fields such as
captureOrigin,captureMessageHash,captureTurnHash,capturePath, andpluginCaptureVersion. - Historical installs: no startup mutation is performed automatically. Operators should audit first, then explicitly quarantine or delete suspicious captured memories.
Command surface
Memory Braid exposes audit, search, consolidation, and remediation commands:
/memorybraid search standups --layer semantic --kind preference
/memorybraid search "What did we discuss in June?" --layer episodic
/memorybraid consolidate
/memorybraid audit
/memorybraid remediate audit
/memorybraid remediate quarantine
/memorybraid remediate quarantine --apply
/memorybraid remediate delete --apply
/memorybraid remediate purge-all-captured --apply
Notes:
searchis Mem0-only and intended for validating plugin-managed memory rather than local markdown memory.searchsupports--limit,--layer,--kind,--from,--to, and--include-quarantined.consolidateruns one compendium synthesis pass immediately and reports how many semantic memories were created or updated.- New capture metadata includes deterministic selection fields such as
selectionDecision,rememberabilityScore, andrememberabilityReasons. - Dry-run is the default for remediation commands. Nothing mutates until you pass
--apply. auditreports counts bysourceType,captureOrigin, andpluginCaptureVersion, plus suspicious legacy samples.quarantine --applyexcludes suspicious captured memories from future Mem0 injection. It records quarantine state locally and also tags Mem0 metadata where supported.delete --applydeletes suspicious captured memories only.purge-all-captured --applydeletes all plugin-captured Mem0 records for the current workspace scope without touching local markdown memory.- Optional flags:
--limit Ncontrols how many Mem0 records are fetched during audit/remediation.--sample Ncontrols how many suspicious samples are shown in the audit report.
Debug cost observability
When debug.enabled is true, Memory Braid also emits debug-only LLM usage observability logs from the llm_output hook:
memory_braid.cost.turn: per-turn input/output/cache tokens, cache ratios, and a best-effort estimated USD cost when the provider/model has a known pricing profile.memory_braid.cost.window: rolling 5-turn and 20-turn averages plusrising|stable|improvingtrend labels for prompt size, cache-write rate, cache-hit rate, and estimated cost.memory_braid.cost.alert: emitted only when recent cache writes, prompt size, or estimated cost rise materially above the previous short window.
Important:
estimatedCostUsdis intentionally labeled as an estimate.- Unknown models still log token and cache trends, but the cost basis becomes
token_only.
Self-hosted reset option
If you are self-hosting and prefer a full reset instead of selective remediation, you can clear Memory Braid's OSS Mem0 state and restart OpenClaw:
rm -rf ~/.openclaw/memory-braid
openclaw gateway restart
This is intentionally not done by the plugin itself. It is an operator choice.
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 OpenClaw prompt context as the source of truth for the live session.
- Keep core/QMD as the source of truth for markdown and canonical written knowledge.
- Use Memory Braid + Mem0 for learned cross-session memory, consolidation, and lifecycle management.
Install
Install from npm (recommended)
On the target machine:
- Install from npm:
openclaw plugins install memory-braid@0.8.0
- Rebuild native dependencies inside the installed extension:
cd ~/.openclaw/extensions/memory-braid
npm rebuild sqlite3 sharp
Why 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-braid
Expected:
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 restart
If 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 restart
Note:
- 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 + entity extraction
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": "openai",
"model": "gpt-4o-mini",
"timeoutMs": 2500,
"minScore": 0.65,
"maxEntitiesPerMemory": 8,
"startup": {
"downloadOnStartup": false,
"warmupText": "John works at Acme in Berlin."
}
},
"consolidation": {
"enabled": true,
"startupRun": false,
"intervalMinutes": 360,
"opportunisticNewMemoryThreshold": 5,
"opportunisticMinMinutesSinceLastRun": 30,
"minSupportCount": 2,
"minRecallCount": 2,
"semanticMaxSourceIds": 20,
"timeQueryParsing": true
},
"debug": {
"enabled": true
}
}
Local-model alternative (fully backward compatible):
{
"entityExtraction": {
"enabled": true,
"provider": "multilingual_ner",
"model": "Xenova/bert-base-multilingual-cased-ner-hrl"
}
}
Then restart:
openclaw gateway restart
Verification checklist
- Check runtime status:
openclaw plugins info memory-braid
openclaw gateway status
- Trigger/inspect entity 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 80
Expected events:
memory_braid.startupmemory_braid.entity.model_load(localmultilingual_nerprovider only)memory_braid.entity.warmupmemory_braid.capture.extractmemory_braid.capture.ml(forcapture.mode=hybrid|ml)memory_braid.entity.extractmemory_braid.capture.selectionmemory_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": 4,
"user": {
"enabled": true,
"injectTopK": 4
},
"agent": {
"enabled": true,
"injectTopK": 2,
"minScore": 0.78,
"onlyPlanning": true
},
"merge": {
"rrfK": 60,
"localWeight": 1,
"mem0Weight": 1
}
},
"capture": {
"enabled": true,
"mode": "hybrid",
"includeAssistant": false,
"maxItemsPerRun": 6,
"assistant": {
"enabled": true,
"autoCapture": false,
"explicitTool": true,
"maxItemsPerRun": 2,
"minUtilityScore": 0.8,
"minNoveltyScore": 0.85,
"maxWritesPerSessionWindow": 3,
"cooldownMinutes": 5
},
"ml": {
"provider": "openai",
"model": "gpt-4o-mini",
"timeoutMs": 2500
}
},
"entityExtraction": {
"enabled": true,
"provider": "openai",
"model": "gpt-4o-mini",
"timeoutMs": 2500,
"minScore": 0.65,
"maxEntitiesPerMemory": 8,
"startup": {
"downloadOnStartup": false,
"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(legacy alias forcapture.assistant.autoCapture)capture.selection.minPreferenceDecisionScore:0.45capture.selection.minFactScore:0.52capture.selection.minTaskScore:0.72capture.selection.minOtherScore:0.82capture.selection.minProceduralScore:0.58capture.maxItemsPerRun:6capture.assistant.enabled:truecapture.assistant.autoCapture:falsecapture.assistant.explicitTool:truecapture.assistant.maxItemsPerRun:2capture.assistant.minUtilityScore:0.8capture.assistant.minNoveltyScore:0.85capture.assistant.maxWritesPerSessionWindow:3capture.assistant.cooldownMinutes:5recall.user.injectTopK:5(legacyrecall.injectTopKstill works)recall.agent.injectTopK:2recall.agent.minScore:0.78recall.agent.onlyPlanning:truecapture.ml.provider: unsetcapture.ml.model: unsetcapture.ml.timeoutMs:2500timeDecay.enabled:falselifecycle.enabled:falselifecycle.captureTtlDays:90consolidation.minSelectionScore:0.56lifecycle.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.- New memories are persisted by
workspace + agent, not by session.sessionKeyis kept only as metadata and for assistant-learning cooldown/window logic. - Recall still performs a legacy dual-read fallback for older session-scoped Mem0 records, without rewriting them.
capture.includeAssistant = false(default): assistant auto-capture is off.capture.includeAssistant = trueorcapture.assistant.autoCapture = true: assistant messages are eligible for strict agent-learning auto-capture.capture.assistant.explicitTool = true: exposes theremember_learningtool.recall.user.*controls injected user memories.recall.agent.*controls injected agent learnings.- 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.
Agent learnings
Memory Braid v2 adds explicit and implicit agent learnings.
remember_learningstores compact reusable heuristics, lessons, and strategies for future runs.- Use it for operational guidance that helps the agent avoid repeated mistakes or reduce tool cost/noise.
- Do not use it for long summaries, transient details, or raw reasoning.
- Assistant auto-capture is still available, but it is stricter than user-memory capture and only persists compact learnings that pass utility, novelty, and cooldown checks.
Recall is now split into two dynamic blocks:
<user-memories>: user facts, preferences, decisions, and tasks.<agent-learnings>: reusable agent heuristics, lessons, and strategies.
Cache safety:
- Tool awareness for
remember_learningis injected through a stablesystemPrompt. - Retrieved memories stay in dynamic
prependContext, not in the stable prompt body. - Agent learnings use low
top-k, high relevance thresholds, and deterministic formatting to avoid unnecessary prompt churn.
Entity extraction defaults
Entity extraction defaults are:
entityExtraction.enabled:falseentityExtraction.provider:"multilingual_ner"entityExtraction.model:"Xenova/bert-base-multilingual-cased-ner-hrl"(or"gpt-4o-mini"whenprovider: "openai"and model is unset)entityExtraction.timeoutMs:2500entityExtraction.minScore:0.65entityExtraction.maxEntitiesPerMemory:8entityExtraction.startup.downloadOnStartup:falseentityExtraction.startup.warmupText:"John works at Acme in Berlin."
When enabled:
- Local NER 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 warmup is opt-in (
downloadOnStartup: false) so model prewarm does not land on the critical gateway startup path.
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.capture.selectionmemory_braid.consolidation.plan|run|supersedememory_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.selectionincludes the deterministic routing decision, numeric rememberability score, and reasons used forignore|episodic|procedural.memory_braid.consolidation.planincludes the compendium drafts that passed deterministic promotion, including promotion score and reasons.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 120
Tests
npm test
Capabilities
- configSchema
- Yes
- Executes code
- Yes
- HTTP routes
- 0
- Plugin kind
- memory
- Runtime ID
- memory-braid
Compatibility
- Built With Open Claw Version
- 0.8.0
- Plugin Api Range
- >=2026.2.18
Verification
- Tier
- source linked
- Scope
- artifact only
- Summary
- Validated package structure and linked the release to source metadata.
- Commit
- https://gith
- Tag
- https://github.com/rodrigouroz/memory-braid/releases/tag/0.8.0
- Provenance
- No
- Scan status
- clean
Tags
- latest
- 0.8.0
