Skip to content

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

Merged
Takhoffman merged 1 commit intomainfrom
codex/fix-active-memory-recall
Apr 28, 2026
Merged

fix(active-memory): use bundled recall tool#73584
Takhoffman merged 1 commit intomainfrom
codex/fix-active-memory-recall

Conversation

@Takhoffman
Copy link
Copy Markdown
Contributor

@Takhoffman Takhoffman commented Apr 28, 2026

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.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 28, 2026

Greptile Summary

This PR fixes the tool name mismatch between Active Memory's recall sub-agent and the memory-lancedb backend by switching toolsAllow and the recall prompt from the legacy memory_search/memory_get pair to memory_recall. The debug transcript parser is carefully updated to stay compatible with old traces.

  • The toolsAllow is now hardcoded to [\"memory_recall\"], which will silently break recall for any user whose memory slot is backed by memory-core (the other bundled backend), since memory-core exposes memory_search and memory_get and neither is in the new allowlist.

Confidence Score: 3/5

Not safe to merge as-is: fixes LanceDB recall but introduces a regression for memory-core users whose recall will silently stop working.

One P1 regression — hardcoding toolsAllow to ["memory_recall"] blocks the memory-core backend tools — prevents this from scoring higher than 3.

extensions/active-memory/index.ts — specifically the toolsAllow change at line 1692 and the prompt at lines 792–793.

Comments Outside Diff (1)

  1. extensions/qa-lab/src/providers/mock-openai/server.ts, line 1475-1505 (link)

    P2 Dead code left in the memory_recall handler

    Now that the new memoryText branch (lines 1455–1474) returns early whenever toolJson.text is a string, the memorySnippet fallback on line 1495 repeats typeof toolJson?.text === "string" — a condition that can never be true here. The entire block from const results = ... through the memorySnippet assignment is unreachable for the memory_recall response shape. If backward compat with the old { results: [...] } shape isn't intentional for this scenario, this dead code can be removed to avoid confusion.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: extensions/qa-lab/src/providers/mock-openai/server.ts
    Line: 1475-1505
    
    Comment:
    **Dead code left in the `memory_recall` handler**
    
    Now that the new `memoryText` branch (lines 1455–1474) returns early whenever `toolJson.text` is a string, the `memorySnippet` fallback on line 1495 repeats `typeof toolJson?.text === "string"` — a condition that can never be true here. The entire block from `const results = ...` through the `memorySnippet` assignment is unreachable for the `memory_recall` response shape. If backward compat with the old `{ results: [...] }` shape isn't intentional for this scenario, this dead code can be removed to avoid confusion.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/active-memory/index.ts
Line: 1692

Comment:
**`memory-core` backend recall will silently fail after this change**

The `toolsAllow` list is hardcoded to `["memory_recall"]`, but `memory-core` (a supported bundled backend) exposes `memory_search` and `memory_get` — neither of which is now in the allowlist. Any user whose memory slot is backed by `memory-core` rather than `memory-lancedb` will have the sub-agent blocked from calling either legacy tool, causing recall to silently produce no results.

The prompt on line 792 also now only instructs the model to call `memory_recall`, compounding the problem for `memory-core` users.

Consider expanding the allowlist to cover both contracts:
```ts
toolsAllow: ["memory_recall", "memory_search", "memory_get"],
```
and updating the prompt to either dynamically reflect the active backend or mention both tool families.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/qa-lab/src/providers/mock-openai/server.ts
Line: 1475-1505

Comment:
**Dead code left in the `memory_recall` handler**

Now that the new `memoryText` branch (lines 1455–1474) returns early whenever `toolJson.text` is a string, the `memorySnippet` fallback on line 1495 repeats `typeof toolJson?.text === "string"` — a condition that can never be true here. The entire block from `const results = ...` through the `memorySnippet` assignment is unreachable for the `memory_recall` response shape. If backward compat with the old `{ results: [...] }` shape isn't intentional for this scenario, this dead code can be removed to avoid confusion.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(active-memory): use bundled recall t..." | Re-trigger Greptile

Comment thread extensions/active-memory/index.ts Outdated
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 28, 2026

Codex review: keeping this open for maintainer follow-up; there is still a little grit to resolve.

Keep open. This PR is protected by cleanup policy because the author is a MEMBER and the PR has the maintainer label. It is also still a live implementation candidate: current main still wires Active Memory to memory_search/memory_get only, while bundled memory-lancedb exposes memory_recall for recall.

Best possible solution:

Keep this PR open for explicit maintainer review. If the approach is accepted, land this PR or an equivalent patch that lets Active Memory use both bundled memory contracts, updates the docs/tests/QA mock, and records or resolves the intended privacy scope for memory-lancedb recall. Close the linked bug only after the implementation merges.

What I checked:

  • Protected maintainer PR: Provided GitHub context shows authorAssociation is MEMBER and labels include maintainer. Conservative cleanup policy requires explicit maintainer judgment for this PR.
  • Active Memory prompt still uses legacy tools on main: buildRecallPrompt still tells the hidden recall agent to use only memory_search and memory_get, so the PR's intended behavior is not already implemented on main. (extensions/active-memory/index.ts:851, dd643c82b55e)
  • Active Memory allowlist still excludes memory_recall on main: runRecallSubagent still passes toolsAllow: ["memory_search", "memory_get"], which blocks memory-lancedb's recall tool. (extensions/active-memory/index.ts:2075, dd643c82b55e)
  • memory-lancedb exposes memory_recall: The bundled memory-lancedb plugin registers memory_recall as its recall tool, and its docs list memory_recall, memory_store, and memory_forget as LanceDB memory tools. (extensions/memory-lancedb/index.ts:597, dd643c82b55e)
  • memory-core still exposes the legacy contract: The bundled memory-core plugin registers memory_search and memory_get, supporting the PR discussion's updated approach of allowing both bundled tool families rather than switching exclusively to memory_recall. (extensions/memory-core/index.ts:52, dd643c82b55e)
  • Docs and tests still encode the old Active Memory contract: Current docs and tests still describe or assert Active Memory's memory_search/memory_get-only behavior, which the PR updates alongside the implementation. Public docs: docs/concepts/active-memory.md. (docs/concepts/active-memory.md:83, dd643c82b55e)

Remaining risk / open question:

  • Closing would violate the protected maintainer-item rule because the PR author is a MEMBER and the PR has the maintainer label.
  • Current main still has the Active Memory versus memory-lancedb tool-name mismatch, so this PR is not obsolete cleanup work.
  • Before merge, maintainers should explicitly resolve or accept the privacy/product scope of preferring memory_recall while memory-lancedb recall appears broad/global in the inspected current implementation.

Codex review notes: model gpt-5.5, reasoning high; reviewed against dd643c82b55e.

@Takhoffman Takhoffman force-pushed the codex/fix-active-memory-recall branch 2 times, most recently from 0596088 to f2ed7b6 Compare April 28, 2026 13:47
@openclaw-barnacle openclaw-barnacle Bot added the docs Improvements or additions to documentation label Apr 28, 2026
@Takhoffman Takhoffman force-pushed the codex/fix-active-memory-recall branch from f2ed7b6 to c997346 Compare April 28, 2026 14:00
@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot Bot commented Apr 28, 2026

🔒 Aisle Security Analysis

We found 1 potential security issue(s) in this PR:

# Severity Title
1 🟡 Medium Active Memory sub-agent can request unbounded memory dump via newly-allowed memory_recall(limit)
1. 🟡 Active Memory sub-agent can request unbounded memory dump via newly-allowed memory_recall(limit)
Property Value
Severity Medium
CWE CWE-200
Location extensions/active-memory/index.ts:2078-2083

Description

extensions/active-memory now allowlists memory_recall for the hidden recall sub-agent. In the LanceDB memory plugin, memory_recall accepts a user-controlled limit with no upper bound and returns raw memory text for each result.

Because the recall sub-agent is driven by the current conversation context (including potentially untrusted group-chat participants), it can be prompted to call memory_recall with a very large limit, causing:

  • Excessive disclosure: large portions of long-term memory (raw entry.text across many memories) can be pulled into the recall transcript and then forwarded to the main agent as “recall context”, increasing the chance it is echoed back into the chat.
  • Resource/latency amplification: large limit values can cause heavy DB retrieval/formatting and oversized tool results.

Changed code enabling this broader retrieval path:

toolsAllow: ["memory_recall", "memory_search", "memory_get"],

Relevant tool behavior (existing, but newly reachable by the sub-agent):

  • memory_recall in extensions/memory-lancedb/index.ts:
    • takes limit?: number (default 5)
    • calls db.search(vector, limit, 0.1)
    • formats and returns r.entry.text for each result

Recommendation

Mitigate bulk exfiltration by enforcing a hard upper bound on recall results at the tool boundary and/or at the sub-agent boundary.

Option A (tool-side clamp; recommended because it protects all callers):

// in memory_recall execute
const requested = typeof limit === "number" ? limit : 5;
const safeLimit = Math.max(1, Math.min(requested, 10)); // choose a small cap
const results = await db.search(vector, safeLimit, 0.1);

Option B (sub-agent-side): prevent the recall agent from requesting large limits by stripping/overriding limit (or by wrapping tool calls) and truncating tool results before they are returned to the main agent.

Additionally, consider returning summaries/snippets instead of full entry.text, or applying redaction for sensitive categories before passing context to the main agent (especially for group-chat scenarios).


Analyzed PR: #73584 at commit c997346

Last updated on: 2026-04-28T14:03:30Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation extensions: qa-lab maintainer Maintainer-authored PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: active-memory still allowlists memory_search/memory_get, incompatible with bundled memory-lancedb tool surface

1 participant