openclaw - ✅(Solved) Fix Bug: active-memory still allowlists memory_search/memory_get, incompatible with bundled memory-lancedb tool surface [2 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#73502Fetched 2026-04-29 06:19:07
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
0
Timeline (top)
cross-referenced ×2closed ×1commented ×1referenced ×1

active-memory appears to still allowlist the legacy memory tool names memory_search / memory_get, while the bundled memory-lancedb backend exposes memory_recall / memory_store / memory_forget.

In practice this makes bundled active-memory incompatible with bundled memory-lancedb unless the installed code is patched locally.

This looks like an OpenClaw integration bug between two bundled plugins, not a third-party plugin issue.

Error Message

With memory-lancedb configured as the memory backend, active-memory fails its recall path because it appears to request or allowlist the stale tool names:

Root Cause

With memory-lancedb configured as the memory backend, active-memory fails its recall path because it appears to request or allowlist the stale tool names:

Fix Action

Fix / Workaround

In practice this makes bundled active-memory incompatible with bundled memory-lancedb unless the installed code is patched locally.

A local patch replacing:

PR fix notes

PR #68773: fix(active-memory): skip payload-less memory_search toolResults in tr…

Description (problem / solution / changelog)

fix(active-memory): skip payload-less memory_search toolResults in transcript debug lookup

Summary

  • Problem: readActiveMemorySearchDebug used asRecord(details?.debug) ?? {}, which forced an empty object {} when the debug field was missing. This made the subsequent guard !debug && !warning && !action && !error always falsy (because {} is truthy), so the function would return early on the newest memory_search toolResult even when it had no debug payload, shadowing older entries that did contain real debug data.
  • Why it matters: Memory search debug logs became incomplete or misleading — real debug information from earlier results was hidden by later empty results, making it harder to diagnose memory‑search behavior in production.
  • What changed: Removed the ?? {} fallback. Now debug is undefined when the field is absent, allowing the guard to correctly skip processing and walk back to find the most recent result that actually has debug data.
  • What did NOT change: No change to the actual content or formatting of debug logs when valid data exists. Behavior for results with populated debug remains identical. No other memory or tool execution logic is affected.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: asRecord(details?.debug) ?? {} intentionally defaulted missing debug to an empty object, but the guard that followed was designed to skip only when debug is falsy (undefined or null). An empty object {} is truthy, so the guard never triggered.
  • Missing detection / guardrail: There was no unit test that simulated a transcript with interleaved empty and populated memory_search results. Existing tests only verified happy paths where every result had a debug field.
  • Contributing context (if known): The original ?? {} was likely added to avoid undefined checks later, but it inadvertently broke the guard’s semantics.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: extensions/active-memory/index.test.ts (new test case added)
  • Scenario the test should lock in: A transcript with two memory_search tool results: first result with valid details.debug, second result with details: {} (no debug). The function should return the debug data from the first result, not skip both.
  • Why this is the smallest reliable guardrail: A unit test that directly calls readActiveMemorySearchDebug with a controlled transcript array isolates the exact regression without needing the full memory pipeline or external storage.
  • Existing test that already covers this (if any): None.
  • If no new test is added, why not: N/A – a regression test has been added as part of this PR.

User‑visible / Behavior Changes

None. This only affects internal debug logging used by developers.

Diagram (if applicable)

N/A

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: any
  • Runtime/container: Node.js 20+
  • Model/provider: N/A
  • Integration/channel (if any): N/A
  • Relevant config (redacted): N/A

Steps

  1. Create a transcript .jsonl where:
    • Entry A: memory_search tool result with details.debug = { backend: "qmd", hits: 3 }
    • Entry B (newer): another memory_search tool result with details: {} (no debug)
  2. Call readActiveMemorySearchDebug on this transcript.
  3. Observe the returned debug object.

Expected

The function returns the debug object from entry A (the older entry with real data).

Actual (before fix)

The function returns undefined (or early‑exits without processing), because entry B’s ?? {} created an empty object and the guard failed to skip.

Evidence

  • Failing test before + passing after (included in PR)
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios:
    • Empty debug field (details: {}) followed by a populated one → correct older debug returned.
    • Populated debug only → returns that debug.
    • No memory_search results → returns undefined.
    • Multiple populated results → returns the most recent one (unchanged behavior).
  • Edge cases checked: Empty details object, missing details field, debug set to null, debug set to an array (unlikely but handled gracefully).
  • What I did NOT verify: Interaction with the full memory storage layer (outside readActiveMemorySearchDebug). The change is isolated to this helper function.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

None.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/active-memory/index.test.ts (modified, +48/-0)
  • extensions/active-memory/index.ts (modified, +1/-1)

PR #73584: fix(active-memory): use bundled recall tool

Description (problem / solution / changelog)

Summary

Fixes #73502.

Active Memory was still wiring its hidden recall sub-agent to the legacy memory-core tools:

memory_search
memory_get

But the bundled memory-lancedb backend exposes the current recall surface as:

memory_recall
memory_store
memory_forget

That made the bundled Active Memory + bundled Memory LanceDB integration a plug/socket mismatch: when memory-lancedb was selected as the memory slot, Active Memory prompted and allowlisted only the legacy tools, so recall could fail even though LanceDB itself was configured and working.

This PR aligns Active Memory with both bundled memory contracts by:

  • allowing the hidden recall sub-agent to use memory_recall, memory_search, or memory_get
  • updating the prompt to prefer memory_recall when available, and fall back to memory_search/memory_get when that is the backend surface
  • keeping debug transcript parsing compatible with existing legacy memory_search tool-result traces
  • updating the QA mock provider flow to exercise the memory_recall path
  • updating the Active Memory docs/fixtures so they no longer describe only the legacy memory_search/memory_get path

Why this shape: using only memory_recall fixes LanceDB but regresses memory-core; using only memory_search/memory_get preserves memory-core but leaves LanceDB broken. Allowing both tool families and instructing the sub-agent to prefer the available current recall tool preserves both bundled paths.

I also scanned the other memory-related prompt/docs references. The remaining memory_search/memory_get references are intentionally memory-core-specific docs/tests, generic tool-policy docs, or QA scenarios that explicitly exercise the legacy memory-core flow.

Validation

Passed:

pnpm test extensions/active-memory/index.test.ts
pnpm test extensions/qa-lab/src/providers/mock-openai/server.test.ts
pnpm exec oxfmt --check extensions/active-memory/index.ts extensions/active-memory/index.test.ts extensions/qa-lab/src/providers/mock-openai/server.ts extensions/qa-lab/src/providers/mock-openai/server.test.ts

Also passed:

rg -n 'only calls `memory_search` and `memory_get`|The blocking memory sub-agent can use only:|Use only memory_search and memory_get|Use only memory_recall|normal `memory_search` pipeline' docs/concepts/active-memory.md extensions/active-memory extensions/qa-lab/src/providers/mock-openai/server.test.ts

The rg command exits 1 because it finds no remaining stale Active Memory-only phrasing.

Also run earlier:

pnpm check

pnpm check currently fails in tsgo:prod on latest origin/main with unrelated broad type/dependency errors outside this patch, including TypeBox resolution from /Users/thoffman/node_modules, model compat typing errors, and missing @vincentkoc/qrcode-tui. The focused changed-surface tests above pass.

Manual testing: none; covered by focused automated tests.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • docs/concepts/active-memory.md (modified, +7/-5)
  • extensions/active-memory/index.test.ts (modified, +7/-2)
  • extensions/active-memory/index.ts (modified, +11/-5)
  • extensions/qa-lab/src/providers/mock-openai/server.test.ts (modified, +14/-14)
  • extensions/qa-lab/src/providers/mock-openai/server.ts (modified, +23/-26)

Code Example

["memory_search", "memory_get"]

---

["memory_recall"]
RAW_BUFFERClick to expand / collapse

Summary

active-memory appears to still allowlist the legacy memory tool names memory_search / memory_get, while the bundled memory-lancedb backend exposes memory_recall / memory_store / memory_forget.

In practice this makes bundled active-memory incompatible with bundled memory-lancedb unless the installed code is patched locally.

This looks like an OpenClaw integration bug between two bundled plugins, not a third-party plugin issue.

Environment

  • OpenClaw: 2026.4.25
  • Install: npm/global install on Linux x64
  • Active memory plugin: bundled active-memory
  • Memory backend: bundled memory-lancedb

Observed behavior

With memory-lancedb configured as the memory backend, active-memory fails its recall path because it appears to request or allowlist the stale tool names:

  • memory_search
  • memory_get

But the actual tool surface available from the LanceDB backend is:

  • memory_recall
  • memory_store
  • memory_forget

A local patch replacing:

["memory_search", "memory_get"]

with:

["memory_recall"]

in:

/home/ubuntu/.npm-global/lib/node_modules/openclaw/dist/extensions/active-memory/index.js

was required to make the integration line up.

Expected behavior

If active-memory is intended to work with bundled memory-lancedb, it should use the current memory runtime/tool contract exposed by that backend, rather than stale legacy tool names.

At minimum, bundled plugins should not ship with incompatible built-in defaults.

Why this seems like a core bug

Both sides are bundled OpenClaw components:

  • bundled active-memory
  • bundled memory-lancedb

So if one ships expecting memory_search / memory_get and the other ships exposing memory_recall, that is an upstream integration regression/drift inside OpenClaw.

Related symptoms

This may also explain or contribute to:

  • active-memory recall failures
  • timeouts/skips in the recall path
  • confusing diagnosis when memory-lancedb itself is otherwise functional

Reproduction steps

  1. Install OpenClaw 2026.4.25
  2. Configure memory-lancedb as the active memory backend
  3. Enable bundled active-memory
  4. Start the gateway and trigger a conversation where active-memory should perform recall
  5. Observe that the active-memory path appears to rely on stale legacy memory tool names rather than the current LanceDB tool surface

Suggested fix

Audit the bundled active-memory integration against the current memory runtime contract used by bundled memory-lancedb, and update the allowlist/tool selection accordingly.

It would also be worth checking for any other stale references to:

  • memory_search
  • memory_get

inside the bundled active-memory pipeline.

extent analysis

TL;DR

Update the active-memory plugin to use the current memory runtime contract exposed by memory-lancedb, replacing legacy tool names memory_search and memory_get with memory_recall.

Guidance

  • Verify the compatibility of active-memory with memory-lancedb by checking the tool names used in the active-memory plugin.
  • Update the active-memory plugin to use the current tool names exposed by memory-lancedb, which are memory_recall, memory_store, and memory_forget.
  • Check for any other stale references to memory_search and memory_get in the active-memory pipeline.
  • Test the updated active-memory plugin with memory-lancedb to ensure compatibility and fix recall failures.

Example

// Replace this:
const allowedTools = ["memory_search", "memory_get"];

// With this:
const allowedTools = ["memory_recall"];

Notes

This fix assumes that the issue is caused by the outdated tool names used in the active-memory plugin. If the issue persists after updating the plugin, further investigation may be needed.

Recommendation

Apply the suggested fix by updating the active-memory plugin to use the current memory runtime contract exposed by memory-lancedb. This should resolve the compatibility issue and fix recall failures.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

If active-memory is intended to work with bundled memory-lancedb, it should use the current memory runtime/tool contract exposed by that backend, rather than stale legacy tool names.

At minimum, bundled plugins should not ship with incompatible built-in defaults.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Bug: active-memory still allowlists memory_search/memory_get, incompatible with bundled memory-lancedb tool surface [2 pull requests, 1 comments, 2 participants]