Skip to content

fix(memory): OpenClaw plugin accepts profile: expert, which hides three of its four contract tools #3237

Closed

Description

@Forrest-ly

Component

memory

What happened?

The OpenClaw adapter accepts profile: "expert" in plugins.entries["memory-anolisa"].config and forwards it to the child as MEMORY_PROFILE, but expert is the one profile that hides the tools this plugin is built on.

src/agent-memory/src/config.rs::Profile::tool_visible hides Tier B under expert at both tools/list and tools/call (pinned by tests/profile_test.rs::expert_profile_hides_tier_b), and three of the four tools the plugin registers for the host's memory contract are exactly that list. Measured against main @ a3e641a3:

MEMORY_PROFILE=advanced  tools/list -> 37 tools
MEMORY_PROFILE=expert    tools/list -> 31 tools

MEMORY_PROFILE=expert:
  tools/call memory_search      -> -32601 tool 'memory_search' is not exposed under the Expert profile
  tools/call memory_observe     -> -32601 tool 'memory_observe' is not exposed under the Expert profile
  tools/call memory_get_context -> -32601 tool 'memory_get_context' is not exposed under the Expert profile
  tools/call mem_read           -> ok            # what memory_get maps to

So an operator who sets expert — a value the plugin's own configSchema.properties.profile.enum offers and the user guide lists as basic | advanced | expert — does not get "file tools only". The plugin loads, logs plugin registered (... profile=expert ...), registers all four tools plus both hooks, and then:

  • memory_search / memory_observe / memory_get_context answer with the error string inside every tool result;
  • the auto-recall hook (before_prompt_build) fails on every prompt, once per recall candidate, and logs a warning each time;
  • the corpus=all supplement catches the same error and returns no hits, so the host's memory corpus silently loses this backend;
  • only memory_get still works.

Nothing at boot says any of this. The adapter exposes exactly one Tier A tool and cannot expose the rest without breaking the contract the host selected it for, so expert is not a profile this adapter can honor at all — it belongs to direct MCP clients that drive Tier A themselves.

What I expected: setting profile: "expert" on the OpenClaw plugin either works or fails at plugin load with a message naming the reason, not a memory slot that loads and then fails per call.

How can we reproduce it?

  1. make -C src/agent-memory build and install the OpenClaw adapter (install.sh or anolisa adapter enable agent-memory openclaw).
  2. Set plugins.entries["memory-anolisa"].config.profile = "expert" in openclaw.json.
  3. openclaw gateway restart, then call memory_search from the agent (or watch the gateway log for the auto-recall warnings on the next prompt).
  4. Observe Search error: tool 'memory_search' is not exposed under the Expert profile and an empty corpus=all supplement, while memory_get still answers.

The child-side half is reproducible without the host:

MEMORY_PROFILE=expert MEMORY_BASE_DIR=/tmp/m MEMORY_SESSION_DIR=/tmp/s \
  agent-memory serve   # then tools/list and tools/call memory_search over stdio

Diagnostic output

$ git rev-parse --short HEAD
a3e641a3
$ grep -n 'profile' src/agent-memory/adapters/agent-memory/openclaw/src/config.ts
20:  profile: "basic" | "advanced" | "expert";
108:  if (s === "basic" || s === "advanced" || s === "expert") {
$ grep -n 'MEMORY_PROFILE' src/agent-memory/adapters/agent-memory/openclaw/src/mcp-client.ts
198:      MEMORY_PROFILE: this.config.profile,

Anything else?

Suggested fix, in the adapter rather than in the server (the server's gate is correct for direct MCP clients):

  • reject profile: "expert" in resolveConfig, which is where this module already fails on config the child would interpret differently than the operator meant (48d10029, a3e641a3). The host catches a throw from register() and logs [plugins] memory-anolisa failed during register from <source>: <message>, so the reason reaches the operator.
  • drop expert from configSchema.properties.profile.enum so the Control UI stops offering a value whose only effect is a plugin that fails to load, and keep the resolver check for hosts that do not validate config against the schema.
  • record the restriction next to the profile tables in docs/user-guide/{en,zh}/token-saving/agent-memory.md and the component READMEs.

Deliberately out of scope: profile leniency for unrecognized values (a typo still falls back to advanced), and the METHOD_NOT_FOUND troubleshooting row, which describes the direct-MCP path and stays accurate.

Activity

  1. added
    type:bugA confirmed defect or incorrect behavior
    priority:p2Normal: planned product or engineering work
    on Sep 11, 2026
  2. github-actions commented on Sep 11, 2026

    @github-actions

    🔀 Issue Router

    • Component: memory
    • Confidence: 99%
    • Owners notified: @ikunkun-sys
    • No assignee was added; assignment records active implementation ownership.

    问题涉及 Agent Memory 的 OpenClaw 适配器 profile 配置与工具暴露行为。

    Evidence: 标题、组件选择及正文中的 src/agent-memory 路径和 memory 工具均明确指向 memory。

    This routing was applied by the ANOLISA Issue Router through GitHub Actions.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    component:memorysrc/memorypriority:p2Normal: planned product or engineering worktype:bugA confirmed defect or incorrect behavior

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions