feat(memory): add multi-slot memory role architecture#88504
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed July 18, 2026, 11:16 PM ET / July 19, 2026, 03:16 UTC. Summary Reproducibility: no. high-confidence current-main reproduction was established in this read-only review. The central change is a new configuration and plugin-routing model, while the concrete upgrade concern is source-visible in the proposed branch. Review metrics: 2 noteworthy metrics.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review findings
Review detailsBest possible solution: Obtain maintainer approval for a minimal durable memory-role contract, then land it with a tested Doctor-led migration that converts existing legacy memory selectors before canonical runtime routing can change user behavior. Do we have a high-confidence way to reproduce the issue? No high-confidence current-main reproduction was established in this read-only review. The central change is a new configuration and plugin-routing model, while the concrete upgrade concern is source-visible in the proposed branch. Is this the best way to solve the issue? Unclear. Role separation may address real composition needs, but this branch is not yet the best merge path until maintainers choose the permanent API and the Doctor-led upgrade contract is made consistent with runtime behavior. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against ed546bdcf540. Label changesLabel justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (47 earlier review cycles; latest 8 shown)
|
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@kklouzal This is a really clear and complete explanation — thank you for taking the time to write it out. The boundary you drew makes a lot of sense: the PR delivers the role-slot foundation (which plugin owns the dreaming role), while the actual dreaming lifecycle/context contract is left to the plugin. That is the right decomposition: you cannot define a good dreaming API until you have a stable way to select which component runs it. Your note about running per-agent crons instead of relying on managed dreaming resonates directly with my setup. I run a dedicated "Dream Cycle" cron job that fires at 2 AM: it scans recent episodic memory, consolidates high-value entries into a core memory layer, and writes a structured nightly report. It works well in isolation, but it runs as a separate cron sub-agent with no hooks into the session lifecycle — so any per-session context (recent tool calls, decision rationale, partial work) that has not been explicitly written to a file is simply not available to it. What I had been hoping Given your description of the PR scope, that would be a follow-on: richer dreaming lifecycle semantics (event triggers, context provenance). But you are right that the role-slot foundation needs to exist first before any of that is worth specifying. The "jack of all trades" framing is apt. A dreaming-focused plugin that does not also have to implement recall lookups and mid-session capture will be significantly simpler to reason about and test in isolation. Context: Running OpenClaw with a layered episodic/core memory architecture, using scheduled Dream Cycle consolidation as an external cron sub-agent. |
|
A potential solution is to modify api. What do you think? |
|
Have been running this for multiple weeks with multiple agents - zero issues across multiple rebases to newer openclaw versions. Will continue keeping it merge-ready as time permits.. If any maintainer can give direction here I can pivot shape or whatever needs to be done. |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review keep this open clawsweeper:human-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: feat(memory): add multi-slot memory role architecture This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: feat(memory): add multi-slot memory role architecture This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
Summary
This PR fixes a memory-plugin architecture flaw: OpenClaw currently has one exclusive
plugins.slots.memoryowner even though the product, docs, bundled plugins, and runtime behavior already treat “memory” as several different responsibilities.Today, factual recall, auto-capture, compaction, dreaming/consolidation, and user/session modeling are all forced through the same global selector. That makes documented memory stacks impossible or brittle: selecting one memory provider can unintentionally displace another provider that owns a different responsibility.
This PR corrects that mismatch by introducing purpose-specific memory role slots:
memory.recallmemory.capturememory.compactionmemory.dreamingmemory.userModelThe new role slots are the mechanism. The fix is that OpenClaw can now represent the memory architecture it already documents and partially implements.
What Problem This Solves
This is a flaw fix, not just a feature request.
OpenClaw’s memory ecosystem is already multi-role:
memory-core/ QMD provide local factual recall/search over project memory, session transcripts, and Markdown/QMD corpora.The current
plugins.slots.memorycontract cannot express that architecture. It treats everykind: "memory"provider as competing for one owner slot, even when the providers are designed to do different jobs. That leads to three concrete problems:So while this PR adds new public config keys, the intent is corrective: make the config/runtime contract match the memory system OpenClaw already exposes.
User Impact / Intended Outcome
After this PR, OpenClaw can express memory stacks that were previously documented or implied but not cleanly configurable:
memory-coreor QMD can own factual recall while Honcho owns user/session modeling.memory.recallprovider instead of depending on hard-coded assumptions.plugins.slots.memorycontinue to work as recall selection.openclaw doctor --fixcan migrate/canonicalize non-conflicting legacy memory-slot config while preserving the legacy key for plugin compatibility.Linked Context
Closes #60572.
Directly related memory-composition requests and prior proposals:
Dreaming and memory-role separation context:
memory-corememory plugins. This PR adds thememory.dreamingslot contract but does not implement that full protocol.Runtime/diagnostic slot handling context:
plugins.slots.*references could leave config unrecoverable until doctor cleanup was broadened.Context-engine compatibility context:
legacycontext engine not registered in CLI compaction lifecycle worker — dreaming diary subagent fails silently (follow-up to #76576) #81843: context-engine registration and LosslessClaw-adjacent failures shaped the compatibility review for preserving the existing globalplugins.slots.contextEnginebehavior while rejecting unsupported per-agentcontextEngineconfig.Future API/RFC context:
plugins.slots.<slot>.owner#70823: future machine-readable slot ownership/provenance. This PR intentionally keeps scalar plugin IDs and solves the memory role composition layer first.Memory-plugin interop research: the supporting research document validates this PR as necessary architecture work, not optional extensibility: OpenClaw's own documentation already describes memory as a composable ecosystem where builtin/QMD recall, Honcho user/session modeling, LanceDB recall/capture, Active Memory orchestration, dreaming/consolidation, and Memory Wiki compilation can coexist, but current
origin/maincollapses everykind: "memory"provider into one exclusiveplugins.slots.memoryowner, making those documented combinations impossible or dependent on brittle exceptions. PR #88504 closes that product/docs/runtime gap by replacing the single memory owner with explicit role slots —memory.recall,memory.capture,memory.compaction,memory.dreaming, andmemory.userModel— while preserving legacymemoryas a recall shorthand, so the documented memory-plugin interop story becomes actually representable in config and runtime behavior.What Changes
memory.recall,memory.capture,memory.compaction,memory.dreaming, andmemory.userModel.plugins.slots.memoryas a backward-compatible shorthand formemory.recallduring an extended migration window.agents.list[*].plugins.slots, limited to memory roles plus legacymemory.plugins.slots.contextEnginepath for LosslessClaw and other context-engine plugins.agents.list[*].plugins.slots.contextEngineoverrides because agent-scoped context-engine semantics are outside this PR.Implementation Notes
src/plugins/slot-resolution.tsas the shared role-slot helper layer for canonical memory role keys, defaults, normalization, effective per-agent resolution, and configured selection collection.PluginSlotsConfig.contextEnginefor global plugin slots, and adds an agent-slot type/schema that omitscontextEngine.doctor --fixcanonicalizes tomemory.recallwhile retaining legacymemoryduring the compatibility window.memory-corefallback with a user-selected plugin under restrictive allowlists.memory.recallowner.memory.compactionoverrides in both normal session runs and manual/queued compaction paths.Tests / Verification
Current PR branch:
kklouzal:feat/multi-slot-memory-architectureopenclaw/openclaw:main9040ece51de5aae8178225cf5d6e8f82dde1886dUNSTABLE.Latest validation at current pushed head:
pnpm vitest run test/scripts/plugin-prerelease-test-plan.test.ts: passed before the inheritance repair follow-up.node scripts/run-vitest.mjs src/plugins/slots.test.ts src/plugins/uninstall.test.ts src/commands/doctor/shared/stale-plugin-config.test.ts: passed after the inheritance repair follow-up.origin/main: completed with one conflict intest/scripts/plugin-prerelease-test-plan.test.ts, resolved to the canonicaltimeoutMs: 1_500_000expectation.git status --short --branch: clean and onpr-88504-ci-remediation...fork/feat/multi-slot-memory-architecture.Earlier exact-head proof gates carried forward by current head:
pnpm check:test-types: passed.pnpm format:check src/plugins/memory-runtime.ts: passed.node scripts/check-no-conflict-markers.mjs: passed.git diff --check: passed.v2026.5.28to PR head3f1f547042220aee42b3e39b8cb7ecb15cfac993: passed for release install/status/valid doctor-fix, expected old-release config rejection of future PR-era slot keys, PR install/config/doctor/status/plugins/models/agents/slots, focused runtime tests, focused doctor/legacy tests, conflict-marker check, and diff check.Evidence
Rebase/Squash/Proof
13ecca5408cbc94e66105608bfe770d0fc660d76(origin/main,fix(telegram): back off session init spool retries)9040ece51de5aae8178225cf5d6e8f82dde1886daaa40f2ad50ca4ab1e5a5171f3de34d844e6fe8f--force-with-lease.ClawSweeper Requested Real Behavior Proof Coverage
ClawSweeper requested redacted real behavior proof for the durable memory role-slot surface before merge: migration/upgrade compatibility, config/schema and plugin loader behavior, memory runtime role-slot selection, doctor migration/repair, status/models output, legacy
plugins.slots.memorycompatibility, canonical role slots, per-agent overrides, disabled/none recall slots, live CLI agent turns, and gateway service-dispatched live agent execution.The proof below covers those requested areas with redacted rollback/upgrade output, focused config/doctor/status/plugin-loader gates, live CLI agent-turn markers, exact-head gateway service install/restart/status/health checks, gateway-dispatched live agent execution, and additional automation/plugin-subagent bookkeeping validation. Private host/path/token/session/network values are redacted while preserving commands, markers, artifact names, and commit hashes.
Caveat: the full runtime rollback/upgrade/gateway proof is carried forward from PR head
3f1f547042220aee42b3e39b8cb7ecb15cfac993, while later focused validation covers current pushed head7fe86ce04ec6df8a571dba1465507ab35be963ba. If the branch changes materially before merge, refresh the exact-head runtime proof as ClawSweeper requested.Real / Live Behavior Proof
Latest tested PR commit:
Latest validation at this commit:
origin/main, squashed, then updated with fix commit7fe86ce6aeddcc55ca41762f16fd19b798f3042dfor per-agent memory slot inheritance repair.scripts/plugin-sdk-surface-report.mjs.origin/mainchanged SDK surface budgets while this PR branch added memory role-slot SDK surface area.OPENCLAW_PLUGIN_SDK_MAX_PUBLIC_ENTRYPOINTS:321OPENCLAW_PLUGIN_SDK_MAX_PUBLIC_EXPORTS:10338OPENCLAW_PLUGIN_SDK_MAX_PUBLIC_FUNCTION_EXPORTS:5187OPENCLAW_PLUGIN_SDK_MAX_PUBLIC_DEPRECATED_EXPORTS:32467fe86ce6aeddcc55ca41762f16fd19b798f3042d:node scripts/run-vitest.mjs src/plugins/slots.test.ts src/plugins/uninstall.test.ts src/commands/doctor/shared/stale-plugin-config.test.tspassed.git merge-tree --write-tree HEAD origin/maincompleted cleanly with no conflict output.Earlier exact-head proof carried forward by the merge commit:
c447e22033ca104cb9d5292edf4313bcb74f81cffixed the PR-ownedcheck-prod-typesfailure by removing the now-unused active-memory config parameter/helper after the memory tool allowlist behavior change.pnpm tsgo:prodpassing before push.3f1f547042220aee42b3e39b8cb7ecb15cfac993covered memory role-slot contract, per-agent overrides, legacyplugins.slots.memorycompatibility, disablednonerecall slots, doctor migration/repair behavior, role-slot-selected plugin activation/validation, upgrade behavior from the last public release, exact-head gateway service install/restart, gateway health, gateway-dispatched live agent execution, and plugin subagent completion bookkeeping.Proof environment:
3f1f547042220aee42b3e39b8cb7ecb15cfac993, rolled back to public releasev2026.5.28, then upgraded directly back to the same PR head.Dev-01 exact-head deterministic gateway/plugin-subagent gates:
Nano auth-preserving rollback/upgrade matrix:
Nano clean live source CLI turns after re-auth:
Nano exact-head gateway service proof:
Nano focused exact-head source gates after upgrade:
Verified role-slot matrix:
Observed result:
9040ece51de5aae8178225cf5d6e8f82dde1886d.origin/mainrebase, and the squashed PR history.gateway install --force; a non-forced install left the already-installed unit in place, which was explicitly caught and corrected before claiming gateway proof.What was not tested:
Proof limitations or environment constraints:
Compatibility and Risk
Backward compatibility preserved:
plugins.slots.memoryconfigs continue to resolve as recall selection.doctor --fixkeeps the legacyplugins.slots.memorykey in place after copying tomemory.recall, so third-party plugins that still read only the legacy key do not hit an immediate flag day.memory-coreunless explicitly disabled or overridden.plugins.enabled = false, denylist behavior, and explicitplugins.entries.<id>.enabled = falseremain respected.plugins.slots.contextEngineremains separate from memory roles and continues to select context engines such as LosslessClaw.Compatibility changes reviewers should inspect:
memory.recall,memory.capture,memory.compaction,memory.dreaming, andmemory.userModelbecome durable public config keys after merge.agents.list[*].plugins.slots.contextEngineis intentionally rejected until a future PR defines and implements agent-scoped context-engine semantics.plugins.slots.memoryis still deprecated as a canonical authoring target even though it remains supported and retained for compatibility.Primary risks:
memory.recall, but the retained legacy key avoids forcing that ecosystem update immediately.PR/Commit Surface Breakdown
Source: 67 files, +2216 / -782
Tests: 37 files, +2639 / -98
Total: 104 files, +4855 / -880
Reviewer Checklist
plugins.slots.memoryconfigs.Maintenance update (2026-06-25): rebased/squashed cleanup to head
60783bc0a577dc5201210da488f28eed70475df6; removed duplicated gateway watch CI/test remediation hunks from standalone PR #95473 so that #95473 remains the sole carrier of that fix.Clawsweeper remediation update — 2026-06-26
60783bc0a577dc5201210da488f28eed70475df64e4d3b190ea2c510ce51e0dd5dbd27296c6e95a3memory.recallrole slot instead of only the legacy scalarmemoryslot.plugins.slots["memory.recall"]and per-agentmemory.recalloverrides insrc/agents/harness/runtime-plugin.test.ts.git diff --check HEAD^..HEAD,pnpm exec oxlint src/agents/harness/runtime-plugin.ts src/agents/harness/runtime-plugin.test.ts, andnode scripts/run-vitest.mjs run --config test/vitest/vitest.agents-support.config.ts src/agents/harness/runtime-plugin.test.ts --reporter verboseall passed.