Minne¶
OpenClaw minne är vanligt markdown i agentutrymmet. Filerna är sanningskällan; modellen bara "minnas" vad som skrivs till disken.
Minnessökverktyg tillhandahålls av det aktiva minnestillägget (standard:
memory-core). Inaktivera minnesplugins med plugins.slots.memory = "none".
Minnesfiler (Markdown)¶
Standardlayouten för arbetsytan använder två minneslager:
memory/YYYY-MM-DD.md- Daglig logg (endast tillägg).
- Läs idag + igår vid sessionsstart.
MEMORY.md(valfri)- Kurerat långtidsminne.
- Läs endast i den huvudsakliga, privata sessionen (aldrig i gruppsammanhang).
Dessa filer lever under arbetsytan (agents.defaults.workspace, standard
~/.openclaw/workspace). Se Agentens arbetsyta för den fullständiga layouten.
När ska minne skrivas¶
- Beslut, preferenser och varaktiga fakta hör hemma i
MEMORY.md. - Dagliga anteckningar och löpande kontext hör hemma i
memory/YYYY-MM-DD.md. - Om någon säger ”kom ihåg detta”, skriv ner det (behåll det inte i RAM).
- Detta område utvecklas fortfarande. Det hjälper till att påminna modellen för att lagra minnen; det kommer att veta vad man ska göra.
- Om du vill att något ska bestå, be boten att skriva det till minnet.
Automatisk minnesspolning (förkompakterings-ping)¶
När en session är nära automatisk komprimering, utlöser OpenClaw en tyst,
agentic turn som påminner modellen att skriva hållbart minne innan sammanhanget
är kompakt. Standardprompten säger explicit att modellen may reply,
men brukar NO_REPLY är det rätta svaret så att användaren aldrig ser denna tur.
Detta styrs av agents.defaults.compaction.memoryFlush:
{
agents: {
defaults: {
compaction: {
reserveTokensFloor: 20000,
memoryFlush: {
enabled: true,
softThresholdTokens: 4000,
systemPrompt: "Session nearing compaction. Store durable memories now.",
prompt: "Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store.",
},
},
},
},
}
Detaljer:
- Mjuk tröskel: spolning triggas när sessionens token-estimat passerar
contextWindow - reserveTokensFloor - softThresholdTokens. - Tyst som standard: prompter inkluderar
NO_REPLYså inget levereras. - Två prompter: en användarprompt plus en systemprompt lägger till påminnelsen.
- En spolning per kompakteringscykel (spåras i
sessions.json). - Arbetsytan måste vara skrivbar: om sessionen körs sandboxad med
workspaceAccess: "ro"eller"none", hoppas spolningen över.
För hela kompakteringslivscykeln, se Session management + compaction.
Vektorminnesökning¶
OpenClaw kan bygga ett litet vektorindex över MEMORY.md och memory/*.md så
semantiska frågor kan hitta relaterade anteckningar även när formuleringar skiljer sig.
Standardvärden:
- Aktiverad som standard.
- Bevakar minnesfiler efter ändringar (debounce).
- Använder fjärrinbäddning som standard. Om
memorySearch.providerinte är satt, är OpenClaw auto-selects: 1.localom enmemorySearch.local.modelPathär konfigurerad och filen finns. 2.openaiom en OpenAI-nyckel kan lösas. 3.geminiom en Gemini-nyckel kan lösas. 4.voyageom en Voyage-nyckel kan lösas. 5. Annars förblir minnessökning inaktiverad tills den konfigureras. - Lokalt läge använder node-llama-cpp och kan kräva
pnpm approve-builds. - Använder sqlite-vec (när tillgängligt) för att accelerera vektorsökning i SQLite.
Fjärrbäddningar kräver en API-nyckel för inbäddningsleverantören. OpenClaw
löser nycklar från auth profiler, models.providers.*.apiKey, eller miljö
variabler. Codex OAuth täcker endast chatt/kompletteringar och uppfyller inte
inbäddning för minnessökning. För Gemini, använd GEMINI_API_KEY eller
models.providers.google.apiKey. För resor använder du VOYAGE_API_KEY eller
models.providers.voyage.apiKey. När du använder en egen OpenAI-kompatibel slutpunkt, sätt
memorySearch.remote.apiKey (och valfritt memorySearch.remote.headers).
QMD-backend (experimentell)¶
Ange minne. ackend = "qmd" för att byta den inbyggda SQLite-indexeraren mot
QMD: en lokal första söksida som kombinerar
BM25 + vektorer + reranking. Markdown förblir källan till sanning; OpenClaw skal
ut till QMD för hämtning. Viktiga punkter:
Förutsättningar
- Inaktiverad som standard. Opt in per-config (
memory.backend = "qmd"). - Installera QMD CLI separat (
bun install -g https://github.com/tobi/qmdeller hämta en release) och säkerställ attqmd-binären finns på gatewayensPATH. - QMD behöver en SQLite-byggnad som tillåter tillägg (
brew install sqlitepå macOS). - QMD kör helt lokalt via Bun +
node-llama-cppoch laddar automatiskt ner GGUF- modeller från HuggingFace vid första användning (ingen separat Ollama-daemon krävs). - Gatewayen kör QMD i ett självbärande XDG-hem under
~/.openclaw/agents/<agentId>/qmd/genom att sättaXDG_CONFIG_HOMEochXDG_CACHE_HOME. - OS-stöd: macOS och Linux fungerar ur lådan när Bun + SQLite är installerade. Windows stöds bäst via WSL2.
Hur sidecaren körs
- Gatewayen skriver ett självbärande QMD-hem under
~/.openclaw/agents/<agentId>/qmd/(konfig + cache + sqlite-DB). - Samlingar skapas via
qmd collection addfrånmemory.qmd.paths(plus standardminnesfiler i arbetsytan), därefter körsqmd update+qmd embedvid uppstart och på ett konfigurerbart intervall (memory.qmd.update.interval, standard 5 m). - Uppstartsuppdatering kör nu i bakgrunden som standard så att chattstart inte blockeras; sätt
memory.qmd.update.waitForBootSync = trueför att behålla tidigare blockerande beteende. - Sökningar som körs via
qmd fråga --json. Om QMD misslyckas eller binären saknas, faller OpenClaw automatiskt tillbaka till den inbyggda SQLite-hanteraren så minnesverktygen fungerar. - OpenClaw exponerar inte justering av QMD:s inbäddningsbatchstorlek i nuläget; batchbeteende styrs av QMD självt.
- Första sökningen kan vara långsam: QMD kan ladda ner lokala GGUF-modeller (reranker/frågeexpansion) vid första
qmd query-körningen. - OpenClaw sätter
XDG_CONFIG_HOME/XDG_CACHE_HOMEautomatiskt när QMD körs. -
Om du vill förladda modeller manuellt (och värma samma index som OpenClaw använder), kör en engångsfråga med agentens XDG-kataloger.
OpenClaws QMD-tillstånd lever under din state dir (standard är
~/.openclaw). Du kan pekaqmdpå exakt samma index genom att exportera samma XDG vars OpenClaw använder:```bash
Pick the same state dir OpenClaw uses¶
STATE_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}" if [ -d "$HOME/.moltbot" ] && [ ! -d "$HOME/.openclaw" ] \ && [ -z "${OPENCLAW_STATE_DIR:-}" ]; then STATE_DIR="$HOME/.moltbot" fi
export XDG_CONFIG_HOME="$STATE_DIR/agents/main/qmd/xdg-config" export XDG_CACHE_HOME="$STATE_DIR/agents/main/qmd/xdg-cache"
(Optional) force an index refresh + embeddings¶
qmd update qmd embed
Warm up / trigger first-time model downloads¶
qmd query "test" -c memory-root --json >/dev/null 2>&1 ```
Konfigyta (memory.qmd.*)
command(standardqmd): åsidosätt körbar sökväg.includeDefaultMemory(standardtrue): autoindexeraMEMORY.md+memory/**/*.md.paths[]: lägg till extra kataloger/filer (path, valfripattern, valfri stabilname).sessions: välj in indexering av sessioners JSONL (enabled,retentionDays,exportDir).update: styr uppdateringskadens och underhållskörning: (interval,debounceMs,onBoot,waitForBootSync,embedInterval,commandTimeoutMs,updateTimeoutMs,embedTimeoutMs).limits: begränsa återkallningspayload (maxResults,maxSnippetChars,maxInjectedChars,timeoutMs).scope: samma schema somsession.sendPolicy. Standard är endast DM-(denyall,allowdirektchattar); lossa den till ytan QMD träffar i grupper/kanaler.- When
scopedenies a search, OpenClaw logs a warning with the derivedchannel/chatTypeso empty results are easier to debug. - Utdrag hämtade utanför arbetsytan visas som
qmd/<collection>/<relative-path>imemory_search-resultat;memory_getförstår prefixet och läser från den konfigurerade QMD-samlingens rot. - När
memory.qmd.sessions.enabled = true, exporterar OpenClaw sanerade sessionsutskrifter (Användar-/Assistent-turer) till en dedikerad QMD-samling under~/.openclaw/agents/<id>/qmd/sessions/, så attmemory_searchkan återkalla senaste konversationer utan att röra den inbyggda SQLite-indexen. memory_search-utdrag inkluderar nu enSource: <path#line>-sidfot närmemory.citationsärauto/on; sättmemory.citations = "off"för att hålla sökvägsmetadata intern (agenten får fortfarande sökvägen förmemory_get, men utdragstexten utelämnar sidfoten och systemprompten varnar agenten att inte citera den).
Exempel
memory: {
backend: "qmd",
citations: "auto",
qmd: {
includeDefaultMemory: true,
update: { interval: "5m", debounceMs: 15000 },
limits: { maxResults: 6, timeoutMs: 4000 },
scope: {
default: "deny",
rules: [{ action: "allow", match: { chatType: "direct" } }]
},
paths: [
{ name: "docs", path: "~/notes", pattern: "**/*.md" }
]
}
}
Citat & fallback
memory.citationsgäller oavsett backend (auto/on/off).- När
qmdkörs taggar vistatus().backend = "qmd"så diagnostik visar vilken motor som tjänade resultatet. Om QMD delprocessen avslutas eller JSON utdata inte kan tolkas, sökhanteraren loggar en varning och returnerar den inbyggda leverantören (befintliga Markdown inbäddar) tills QMD återställs.
Ytterligare minnesvägar¶
Om du vill indexera Markdown-filer utanför standardlayouten för arbetsytan, lägg till explicita sökvägar:
agents: {
defaults: {
memorySearch: {
extraPaths: ["../team-docs", "/srv/shared-notes/overview.md"]
}
}
}
Noteringar:
- Sökvägar kan vara absoluta eller arbetsyterelativa.
- Kataloger skannas rekursivt efter
.md-filer. - Endast Markdown-filer indexeras.
- Symlänkar ignoreras (filer eller kataloger).
Gemini-embeddings (native)¶
Sätt leverantören till gemini för att använda Gemini-embeddings-API:t direkt:
agents: {
defaults: {
memorySearch: {
provider: "gemini",
model: "gemini-embedding-001",
remote: {
apiKey: "YOUR_GEMINI_API_KEY"
}
}
}
}
Noteringar:
remote.baseUrlär valfri (standard är Geminis API-bas-URL).remote.headerslåter dig lägga till extra headers vid behov.- Standardmodell:
gemini-embedding-001.
Om du vill använda en anpassad OpenAI-kompatibel endpoint (OpenRouter, vLLM eller en proxy),
kan du använda konfigurationen remote med OpenAI-leverantören:
agents: {
defaults: {
memorySearch: {
provider: "openai",
model: "text-embedding-3-small",
remote: {
baseUrl: "https://api.example.com/v1/",
apiKey: "YOUR_OPENAI_COMPAT_API_KEY",
headers: { "X-Custom-Header": "value" }
}
}
}
}
Om du inte vill sätta en API-nyckel, använd memorySearch.provider = "local" eller sätt
memorySearch.fallback = "none".
Fallbacks:
memorySearch.fallbackkan varaopenai,gemini,localellernone.- Fallback-leverantören används endast när den primära embeddingsleverantören misslyckas.
Batchindexering (OpenAI + Gemini):
- Aktiverad som standard för inbäddning av OpenAI och Gemini. Ange
agents.defaults.memorySearch.remote.batch.enabled = falseför att inaktivera. - Standardbeteendet väntar på batchslutförande; justera
remote.batch.wait,remote.batch.pollIntervalMsochremote.batch.timeoutMinutesvid behov. - Sätt
remote.batch.concurrencyför att styra hur många batchjobb som skickas parallellt (standard: 2). - Batchläge gäller när
memorySearch.provider = "openai"eller"gemini"och använder motsvarande API-nyckel. - Gemini-batchjobb använder den asynkrona embeddings-batchendpointen och kräver tillgänglighet för Gemini Batch API.
Varför OpenAI-batch är snabbt + billigt:
- För stora återfyllnader är OpenAI vanligtvis det snabbaste alternativet vi stöder eftersom vi kan skicka många embeddingsförfrågningar i ett enda batchjobb och låta OpenAI bearbeta dem asynkront.
- OpenAI erbjuder rabatterad prissättning för Batch API-arbetslaster, så stora indexeringskörningar är oftast billigare än att skicka samma förfrågningar synkront.
- Se OpenAI Batch API-dokumentationen och prissättning för detaljer:
- https://platform.openai.com/docs/api-reference/batch
- https://platform.openai.com/pricing
Konfigexempel:
agents: {
defaults: {
memorySearch: {
provider: "openai",
model: "text-embedding-3-small",
fallback: "openai",
remote: {
batch: { enabled: true, concurrency: 2 }
},
sync: { watch: true }
}
}
}
Verktyg:
memory_search— returnerar utdrag med fil- och radintervall.memory_get— läser minnesfilens innehåll via sökväg.
Lokalt läge:
- Sätt
agents.defaults.memorySearch.provider = "local". - Ange
agents.defaults.memorySearch.local.modelPath(GGUF ellerhf:-URI). - Valfritt: sätt
agents.defaults.memorySearch.fallback = "none"för att undvika fjärr-fallback.
Hur minnesverktygen fungerar¶
memory_searchsemantiskt söker Markdown chunks (~400 token target, 80-token overlap) frånMEMORY.md+memory/**/*.md. Den returnerar textutdrag (capped ~700 tecken), filsökväg, linjesortiment, poäng, leverantör / modell, och om vi föll tillbaka från lokala → fjärranslutningar. Ingen full nyttolast för filen returneras.memory_getläser en specifik minnesmarkdown-fil (arbetsyta-relativ), alternativt från en startlinje och för N-linjer. Sökvägar utanförMEMORY.md/minne/avvisas.- Båda verktygen är aktiverade endast när
memorySearch.enabledlöses till true för agenten.
Vad som indexeras (och när)¶
- Filtyp: endast Markdown (
MEMORY.md,memory/**/*.md). - Indexlagring: per-agent SQLite på
~/.openclaw/memory/<agentId>.sqlite(konfigurerbar viaagents.defaults.memorySearch.store.path, stöder{agentId}-token). - Freshness: betraktare på
MEMORY.md+minne/markerar indexet smutsigt (debounce 1.5s). Synkronisering är schemalagd vid start av sessionen, vid sökning eller på ett intervall och körs asynkront. Sessionsutskrifter använder deltatrösklar för att utlösa bakgrundssynkronisering. - Reindex triggers: index lagrar inbäddning leverantör/modell + endpoint fingeravtryck + chunking params. Om någon av dessa ändringar, återställer och indexerar OpenClaw automatiskt hela butiken.
Hybridsökning (BM25 + vektor)¶
När den är aktiverad kombinerar OpenClaw:
- Vektorsimilaritet (semantisk match, formulering kan skilja)
- BM25-nyckelordsrelevans (exakta tokens som ID:n, miljövariabler, kodsymboler)
Om fulltextsökning inte är tillgänglig på din plattform faller OpenClaw tillbaka till endast vektorsökning.
Varför hybrid?¶
Vektorsökning är bra på ”detta betyder samma sak”:
- ”Mac Studio gateway-värd” vs ”maskinen som kör gatewayen”
- ”debounce filuppdateringar” vs ”undvik indexering vid varje skrivning”
Men den kan vara svag på exakta, högsignalstokens:
- ID:n (
a828e60,b3b9895a…) - kodsymboler (
memorySearch.query.hybrid) - felsträngar (“sqlite-vec unavailable”)
BM25 (fulltext) är motsatsen: stark vid exakta tokens, svagare vid parafraser. Hybrid search är den pragmatiska mittfältet: använd båda hämtningssignaler så att du får bra resultat för både “naturspråk” frågor och “nål i en haystack” frågor.
Hur vi slår ihop resultat (nuvarande design)¶
Implementationsskiss:
- Hämta en kandidatpool från båda sidor:
- Vektor: topp
maxResults * candidateMultiplierefter cosinuslikhet. - BM25: topp
maxResults * candidateMultiplierefter FTS5 BM25-rankning (lägre är bättre).
- Konvertera BM25-rankning till ett 0..1-liknande betyg:
textScore = 1 / (1 + max(0, bm25Rank))
- Slå ihop kandidater efter chunk-id och beräkna ett viktat betyg:
finalScore = vectorWeight * vectorScore + textWeight * textScore
Noteringar:
vectorWeight+textWeightnormaliseras till 1,0 i konfigupplösning, så vikter beter sig som procenttal.- Om embeddings inte är tillgängliga (eller om leverantören returnerar en nollvektor) kör vi ändå BM25 och returnerar nyckelordsträffar.
- Om FTS5 inte kan skapas behåller vi endast vektorsökning (inget hårt fel).
Detta är inte “IR-teori perfekt”, men det är enkelt, snabbt och tenderar att förbättra återkallande/precision på verkliga anteckningar. Om vi vill få finare senare, vanliga nästa steg är Reciprocal Rank Fusion (RRF) eller poäng normalisering (min/max eller z-poäng) innan blandning.
Konfig:
agents: {
defaults: {
memorySearch: {
query: {
hybrid: {
enabled: true,
vectorWeight: 0.7,
textWeight: 0.3,
candidateMultiplier: 4
}
}
}
}
}
Inbäddningscache¶
OpenClaw kan cache:a chunk-embeddings i SQLite så att omindexering och frekventa uppdateringar (särskilt sessionsutskrifter) inte återinbäddar oförändrad text.
Konfig:
agents: {
defaults: {
memorySearch: {
cache: {
enabled: true,
maxEntries: 50000
}
}
}
}
Sessionsminnessökning (experimentell)¶
Du kan eventuellt indexera sessionsutskrifter och ytbehandla dem via memory_search.
Detta är gated bakom en experimentell flagga.
agents: {
defaults: {
memorySearch: {
experimental: { sessionMemory: true },
sources: ["memory", "sessions"]
}
}
}
Noteringar:
- Sessionsindexering är opt-in (avstängd som standard).
- Sessionsuppdateringar debouncas och indexeras asynkront när de passerar deltatrösklar (best effort).
memory_searchblockerar aldrig på indexering; resultat kan vara något inaktuella tills bakgrundssynk är klar.- Resultat innehåller fortfarande endast utdrag;
memory_getförblir begränsad till minnesfiler. - Sessionsindexering är isolerad per agent (endast den agentens sessionsloggar indexeras).
- Sessionsloggar live på disk (
~/.openclaw/agents/<agentId>/sessions/*.jsonl). Alla process/användare med filsystemsåtkomst kan läsa dem, så behandla diskåtkomst som förtroendegränsen. För strängare isolering, kör agenter under separata OS-användare eller värdar.
Deltatrösklar (standardvärden visas):
agents: {
defaults: {
memorySearch: {
sync: {
sessions: {
deltaBytes: 100000, // ~100 KB
deltaMessages: 50 // JSONL lines
}
}
}
}
}
SQLite-vektoracceleration (sqlite-vec)¶
När sqlite-vec tillägget är tillgängligt, lagrar OpenClaw inbäddning i en
SQLite virtuell tabell (vec0) och utför vektordistansfrågor i databasen
. Detta håller sökandet snabbt utan att ladda varje inbäddning i JS.
Konfiguration (valfri):
agents: {
defaults: {
memorySearch: {
store: {
vector: {
enabled: true,
extensionPath: "/path/to/sqlite-vec"
}
}
}
}
}
Noteringar:
enabledär true som standard; när den inaktiveras faller sökningen tillbaka till in-process cosinuslikhet över lagrade embeddings.- Om sqlite-vec-tillägget saknas eller inte kan laddas loggar OpenClaw felet och fortsätter med JS-fallback (ingen vektortabell).
extensionPathåsidosätter den medföljande sqlite-vec-sökvägen (användbart för anpassade byggen eller icke-standardiserade installationsplatser).
Lokal inbäddnings-autonedladdning¶
- Standardmodell för lokala embeddings:
hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf(~0,6 GB). - När
memorySearch.provider = "local",node-llama-cpplösermodelPath; om GGUF saknar det auto-downloads till cachen (ellerlocal.modelCacheDirom set), laddar sedan den. Nedladdningar återupptas vid återförsök. - Krav för native-build: kör
pnpm approve-builds, väljnode-llama-cpp, därefterpnpm rebuild node-llama-cpp. - Fallback: om lokal konfiguration misslyckas och
memorySearch.fallback = "openai", byter vi automatiskt till fjärr-embeddings (openai/text-embedding-3-smallom inte åsidosatt) och registrerar orsaken.
Exempel på anpassad OpenAI-kompatibel endpoint¶
agents: {
defaults: {
memorySearch: {
provider: "openai",
model: "text-embedding-3-small",
remote: {
baseUrl: "https://api.example.com/v1/",
apiKey: "YOUR_REMOTE_API_KEY",
headers: {
"X-Organization": "org-id",
"X-Project": "project-id"
}
}
}
}
}
Noteringar:
remote.*har företräde framförmodels.providers.openai.*.remote.headerssammanfoga med OpenAI-huvuden; fjärråtkomst på nyckelkonflikter. Utelämnaremote.headersför att använda OpenAI-standarderna.