Skip to content

Commit ce2ecbb

Browse files
committed
feat(memory): add multi-slot memory architecture
1 parent 047232b commit ce2ecbb

112 files changed

Lines changed: 5754 additions & 1014 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/cli/memory.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ title: "Memory"
1111

1212
Manage semantic memory indexing, search, and promotion into `MEMORY.md`.
1313
Provided by the bundled `memory-core` plugin, available when
14-
`plugins.slots.memory` selects `memory-core` (the default). Other memory
14+
`plugins.slots["memory.recall"]` selects `memory-core` (the default). Other memory
1515
plugins expose their own CLI namespaces.
1616

1717
Related: [Memory](/concepts/memory) concept, [Dreaming](/concepts/dreaming),

docs/cli/plugins.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ openclaw plugins uninstall <id> --keep-files
416416
openclaw plugins uninstall <id> --force
417417
```
418418

419-
`uninstall` removes plugin records from `plugins.entries`, the persisted plugin index, plugin allow/deny list entries, and linked `plugins.load.paths` entries when applicable. Unless `--keep-files` is set, uninstall also removes the tracked managed install directory, but only when it resolves inside OpenClaw's plugin extensions root. If the plugin currently owns the `memory` or `contextEngine` slot, that slot resets to its default (`memory-core` for memory, `legacy` for context engine).
419+
`uninstall` removes plugin records from `plugins.entries`, the persisted plugin index, plugin allow/deny list entries, and linked `plugins.load.paths` entries when applicable. Unless `--keep-files` is set, uninstall also removes the tracked managed install directory, but only when it resolves inside OpenClaw's plugin extensions root. If the plugin currently owns `plugins.slots.contextEngine`, that slot resets to `legacy`; if it owns an active memory role slot such as `plugins.slots["memory.recall"]`, that role slot resets to `memory-core`.
420420

421421
`uninstall` prints a preview of what will be removed, then prompts `Uninstall plugin "<id>"?` before making changes. Pass `--force` to skip the confirmation prompt (useful for scripts and non-interactive runs); without it, uninstall requires an interactive TTY. `--dry-run` prints the same preview and exits without prompting or changing anything.
422422

docs/cli/status.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ and `openclaw memory status --deep`.
9595
## Memory
9696

9797
`status --json --all` reports memory details from the active memory plugin
98-
runtime selected by `plugins.slots.memory`. Custom memory plugins can leave
98+
runtime selected by `plugins.slots["memory.recall"]`. Custom memory plugins can leave
9999
built-in `agents.defaults.memorySearch.enabled` disabled and still report
100100
their own files, chunks, vector, and FTS state.
101101

docs/concepts/context-engine.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ The slot is exclusive at run time - only one registered context engine is resolv
359359
</Note>
360360

361361
<Note>
362-
**Plugin uninstall:** when you uninstall the plugin currently selected as `plugins.slots.contextEngine`, OpenClaw resets the slot back to the default (`legacy`). The same reset behavior applies to `plugins.slots.memory`. No manual config edit is required.
362+
**Plugin uninstall:** when you uninstall the plugin currently selected as `plugins.slots.contextEngine`, OpenClaw resets the slot back to the default (`legacy`). The same reset behavior applies to the memory role slots, including `plugins.slots["memory.recall"]`. No manual config edit is required.
363363
</Note>
364364

365365
## Relationship to compaction and memory
@@ -369,7 +369,7 @@ The slot is exclusive at run time - only one registered context engine is resolv
369369
Compaction is one responsibility of the context engine. The legacy engine delegates to OpenClaw's built-in summarization. Plugin engines can implement any compaction strategy (DAG summaries, vector retrieval, etc.).
370370
</Accordion>
371371
<Accordion title="Memory plugins">
372-
Memory plugins (`plugins.slots.memory`) are separate from context engines. Memory plugins provide search/retrieval; context engines control what the model sees. They can work together - a context engine might use memory plugin data during assembly. Plugin engines that want the active memory prompt path should prefer `buildMemorySystemPromptAddition(...)` from `openclaw/plugin-sdk/core`, which converts the active memory prompt sections into a ready-to-prepend `systemPromptAddition`. If an engine needs lower-level control, it can still pull raw lines from `openclaw/plugin-sdk/memory-host-core` via `buildActiveMemoryPromptSection(...)`.
372+
Memory recall plugins (`plugins.slots["memory.recall"]`) are separate from context engines. Memory plugins provide search/retrieval; context engines control what the model sees. They can work together - a context engine might use memory plugin data during assembly. Plugin engines that want the active memory prompt path should prefer `buildMemorySystemPromptAddition(...)` from `openclaw/plugin-sdk/core`, which converts the active memory prompt sections into a ready-to-prepend `systemPromptAddition`. If an engine needs lower-level control, it can still pull raw lines from `openclaw/plugin-sdk/memory-host-core` via `buildActiveMemoryPromptSection(...)`.
373373
</Accordion>
374374
<Accordion title="Session pruning">
375375
Trimming old tool results in-memory still runs regardless of which context engine is active.

docs/gateway/configuration-reference.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,9 @@ read, account-wide exposure fails closed.
385385
- `memory.qmd.*`
386386
- `plugins.entries.memory-core.config.dreaming`
387387
- Enabled Claude bundle plugins can also contribute embedded OpenClaw defaults from `settings.json`; OpenClaw applies those as sanitized agent settings, not as raw OpenClaw config patches.
388-
- `plugins.slots.memory`: pick the active memory plugin id, or `"none"` to disable memory plugins.
388+
- `plugins.slots["memory.recall"]`: pick the active factual memory recall plugin id, or `"none"` to disable recall. The legacy `plugins.slots.memory` selector is deprecated; run `openclaw doctor --fix` to migrate it when possible.
389+
- `plugins.slots["memory.compaction"]`, `plugins.slots["memory.capture"]`, `plugins.slots["memory.dreaming"]`, and `plugins.slots["memory.userModel"]`: optional role-specific memory plugin slots for memory-aware compaction, capture hooks, dreaming/consolidation, and user modeling.
390+
- `agents.list[].plugins.slots`: optional per-agent overrides for the same memory role slots.
389391
- `plugins.slots.contextEngine`: pick the active context engine plugin id; defaults to `"legacy"` unless you install and select another engine.
390392

391393
See [Plugins](/tools/plugin).

docs/plugins/memory-lancedb.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ openclaw plugins install @openclaw/memory-lancedb
2323

2424
The plugin is published to npm; it is not bundled into the OpenClaw runtime
2525
image. Installing it writes the plugin entry, enables it, and switches
26-
`plugins.slots.memory` to `memory-lancedb`. If another plugin currently owns
27-
the memory slot, that plugin is disabled with a warning.
26+
`plugins.slots["memory.recall"]` to `memory-lancedb`. If another plugin currently owns
27+
the memory recall slot, that plugin is disabled with a warning.
2828

2929
<Note>
3030
Companion plugins such as `memory-wiki` can run alongside `memory-lancedb`,
31-
but only one plugin owns the active memory slot at a time.
31+
but only one plugin owns the active memory recall slot at a time.
3232
</Note>
3333

3434
<Note>
@@ -46,7 +46,7 @@ with the current memory provider.
4646
{
4747
plugins: {
4848
slots: {
49-
memory: "memory-lancedb",
49+
"memory.recall": "memory-lancedb",
5050
},
5151
entries: {
5252
"memory-lancedb": {
@@ -163,7 +163,7 @@ URL rules as the [Ollama](/providers/ollama) provider.
163163
{
164164
plugins: {
165165
slots: {
166-
memory: "memory-lancedb",
166+
"memory.recall": "memory-lancedb",
167167
},
168168
entries: {
169169
"memory-lancedb": {
@@ -225,7 +225,7 @@ capture, even when the plugin-level `autoRecall`/`autoCapture` flags are on.
225225
## Commands
226226

227227
`memory-lancedb` registers the `ltm` CLI namespace whenever it is installed
228-
(not only when it owns the active memory slot):
228+
(not only when it owns the active memory recall slot):
229229

230230
```bash
231231
openclaw ltm list [--agent <id>] [--limit <n>] [--order-by-created-at]
@@ -374,7 +374,7 @@ model, set `embedding.dimensions` to the vector size that model reports.
374374

375375
### Plugin loads but no memories appear
376376

377-
Confirm `plugins.slots.memory` points at `memory-lancedb`, then run:
377+
Confirm `plugins.slots["memory.recall"]` points at `memory-lancedb`, then run:
378378

379379
```bash
380380
openclaw ltm stats

docs/tools/plugin.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ The common plugin config shape is:
169169
allow: ["voice-call"],
170170
deny: ["untrusted-plugin"],
171171
load: { paths: ["~/Projects/oss/voice-call-plugin"] },
172-
slots: { memory: "memory-core" },
172+
slots: { "memory.recall": "memory-core" },
173173
entries: {
174174
"voice-call": { enabled: true, config: { provider: "twilio" } },
175175
},
@@ -194,11 +194,18 @@ Key policy rules:
194194
allowlist them before using local workspace code.
195195
- Bundled plugins follow their built-in default-on/default-off metadata
196196
unless config explicitly overrides it.
197-
- `plugins.slots.<slot>` (`memory` or `contextEngine`) picks one plugin for an
198-
exclusive category. Slot selection counts as explicit activation and
197+
- `plugins.slots.<slot>` chooses one plugin for an exclusive category such as
198+
memory and context engines. Slot selection counts as explicit activation and
199199
force-enables the selected plugin for that slot, even if it would otherwise
200200
be opt-in. `plugins.deny` and `plugins.entries.<id>.enabled: false` still
201201
block it.
202+
- Memory also supports purpose-specific role slots: `memory.recall`,
203+
`memory.compaction`, `memory.capture`, `memory.dreaming`, and
204+
`memory.userModel`. The legacy `memory` slot remains accepted as deprecated
205+
shorthand for `memory.recall`; run `openclaw doctor --fix` to migrate
206+
non-conflicting legacy selectors. Use role slots when composing
207+
complementary memory providers. Per-agent overrides can set the same role
208+
slots under `agents.list[].plugins.slots`.
202209
- Bundled opt-in plugins can auto-activate when config names one of their
203210
owned surfaces, such as a provider/model ref, channel config, CLI backend,
204211
or agent harness runtime.

extensions/active-memory/config.ts

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import {
1313
DEFAULT_ACTIVE_MEMORY_TOOLS_ALLOW,
1414
DEFAULT_CACHE_TTL_MS,
1515
DEFAULT_CIRCUIT_BREAKER_COOLDOWN_MS,
16-
DEFAULT_CLI_RUNTIME_RECALL_TIMEOUT_MS,
1716
DEFAULT_CIRCUIT_BREAKER_MAX_TIMEOUTS,
17+
DEFAULT_CLI_RUNTIME_RECALL_TIMEOUT_MS,
1818
DEFAULT_MAX_SUMMARY_CHARS,
1919
DEFAULT_MIN_TIMEOUT_MS,
2020
DEFAULT_QMD_SEARCH_MODE,
@@ -26,7 +26,6 @@ import {
2626
DEFAULT_SETUP_GRACE_TIMEOUT_MS,
2727
DEFAULT_TIMEOUT_MS,
2828
DEFAULT_TRANSCRIPT_DIR,
29-
LANCEDB_ACTIVE_MEMORY_TOOLS_ALLOW,
3029
MAX_ACTIVE_MEMORY_TOOLS_ALLOW,
3130
MAX_SETUP_GRACE_TIMEOUT_MS,
3231
MAX_TIMEOUT_MS,
@@ -121,16 +120,12 @@ function isReservedActiveMemoryToolsAllowEntry(value: string): boolean {
121120
return normalized.startsWith("group:") || ACTIVE_MEMORY_RESERVED_TOOLS_ALLOW.has(normalized);
122121
}
123122

124-
function resolveDefaultToolsAllow(cfg: OpenClawConfig | undefined): string[] {
125-
return cfg?.plugins?.slots?.memory === "memory-lancedb"
126-
? [...LANCEDB_ACTIVE_MEMORY_TOOLS_ALLOW]
127-
: [...DEFAULT_ACTIVE_MEMORY_TOOLS_ALLOW];
123+
function resolveDefaultToolsAllow(): string[] {
124+
return [...DEFAULT_ACTIVE_MEMORY_TOOLS_ALLOW];
128125
}
129126

130-
function resolveToolsAllow(params: { pluginToolsAllow: unknown; cfg?: OpenClawConfig }): string[] {
131-
return (
132-
normalizeConfiguredToolsAllow(params.pluginToolsAllow) ?? resolveDefaultToolsAllow(params.cfg)
133-
);
127+
function resolveToolsAllow(params: { pluginToolsAllow: unknown }): string[] {
128+
return normalizeConfiguredToolsAllow(params.pluginToolsAllow) ?? resolveDefaultToolsAllow();
134129
}
135130

136131
function normalizePromptConfigText(value: unknown): string | undefined {
@@ -213,10 +208,7 @@ function isMissingRegisteredMemoryToolsError(
213208
return sourceParts.includes(runtimeSource);
214209
}
215210

216-
function normalizePluginConfig(
217-
pluginConfig: unknown,
218-
cfg?: OpenClawConfig,
219-
): ResolvedActiveRecallPluginConfig {
211+
function normalizePluginConfig(pluginConfig: unknown): ResolvedActiveRecallPluginConfig {
220212
const raw = (
221213
pluginConfig && typeof pluginConfig === "object" ? pluginConfig : {}
222214
) as ActiveRecallPluginConfig;
@@ -243,7 +235,7 @@ function normalizePluginConfig(
243235
thinking: resolveThinkingLevel(raw.thinking),
244236
fastMode: normalizeActiveMemoryFastMode(raw.fastMode),
245237
promptStyle: resolvePromptStyle(raw.promptStyle, raw.queryMode),
246-
toolsAllow: resolveToolsAllow({ pluginToolsAllow: raw.toolsAllow, cfg }),
238+
toolsAllow: resolveToolsAllow({ pluginToolsAllow: raw.toolsAllow }),
247239
promptOverride: normalizePromptConfigText(raw.promptOverride),
248240
promptAppend: normalizePromptConfigText(raw.promptAppend),
249241
timeoutMs: clampInt(

0 commit comments

Comments
 (0)