openclaw - 💡(How to fix) Fix buildCliAgentSystemPrompt invoked with tools: [], suppresses plugin-side prompt sections like Memory Recall

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…

buildCliAgentSystemPrompt is invoked with tools: [] in prepare.runtime, which causes buildAgentSystemPrompt to compute availableTools = new Set([]). Plugins that gate their auto-injected system-prompt sections on tool availability (notably memory-core's "Memory Recall" guidance) then return empty, so claude-cli-backed agents never receive the prompt-side documentation about tools they actually have access to via the openclaw MCP loopback.

The user-visible symptom: claude-cli agents have mcp__openclaw__memory_search and mcp__openclaw__memory_get available (allowed by the default --allowedTools mcp__*,... and surfaced via the MCP loopback), but never call them, because the system prompt contains zero hint that they exist or how to use them.

Root Cause

The user-visible symptom: claude-cli agents have mcp__openclaw__memory_search and mcp__openclaw__memory_get available (allowed by the default --allowedTools mcp__*,... and surfaced via the MCP loopback), but never call them, because the system prompt contains zero hint that they exist or how to use them.

Code Example

buildCliAgentSystemPrompt({
    ...,
    tools: [],   // empty
    ...
})

---

toolNames: params.tools.map((tool) => tool.name)

---

availableTools = new Set(normalizedTools)   // empty set

---

const hasMemorySearch = availableTools.has("memory_search");
const hasMemoryGet = availableTools.has("memory_get");
if (!hasMemorySearch && !hasMemoryGet) return [];

---

const { tools: gatewayTools } = await resolveGatewayScopedTools({
    cfg,
    sessionKey,
    // ...whatever else resolveGatewayScopedTools needs from the existing prepare ctx
});

buildCliAgentSystemPrompt({
    ...,
    tools: gatewayTools,
    ...
})
RAW_BUFFERClick to expand / collapse

Summary

buildCliAgentSystemPrompt is invoked with tools: [] in prepare.runtime, which causes buildAgentSystemPrompt to compute availableTools = new Set([]). Plugins that gate their auto-injected system-prompt sections on tool availability (notably memory-core's "Memory Recall" guidance) then return empty, so claude-cli-backed agents never receive the prompt-side documentation about tools they actually have access to via the openclaw MCP loopback.

The user-visible symptom: claude-cli agents have mcp__openclaw__memory_search and mcp__openclaw__memory_get available (allowed by the default --allowedTools mcp__*,... and surfaced via the MCP loopback), but never call them, because the system prompt contains zero hint that they exist or how to use them.

Trace

prepare.runtime (in current 2026.5.12 bundle, file dist/prepare.runtime-DzWXf1k1.js line 715) builds the claude-cli system prompt:

buildCliAgentSystemPrompt({
    ...,
    tools: [],   // empty
    ...
})

That flows into helpers (dist/helpers-B1ZH_nQ4.js:117):

toolNames: params.tools.map((tool) => tool.name)

Which lands in buildAgentSystemPrompt (dist/system-prompt-config-DpjdHIUy.js:443):

availableTools = new Set(normalizedTools)   // empty set

buildMemorySection (dist/system-prompt-config-DpjdHIUy.js:160-166) calls buildPromptSection from extensions/memory-core/index.js:99-110:

const hasMemorySearch = availableTools.has("memory_search");
const hasMemoryGet = availableTools.has("memory_get");
if (!hasMemorySearch && !hasMemoryGet) return [];

With an empty set, this returns []. The "Memory Recall" guidance — "Mandatory recall step: semantically search MEMORY.md + memory/.md… Before answering anything about prior work, decisions, dates…"* — is never injected. Same shape applies to any other plugin section that gates on tool availability.

Meanwhile, the loopback's tools/list (mcp-http-CqosJaju.js:69) IS wired to resolveGatewayScopedTools(...) (tool-resolution-D_3lVp4s.js:13-103) and serves the real tool list. So tools/list and the system-prompt's availableTools are inconsistent: tools/list has memory_search; the system prompt acts as if it doesn't.

Reproducer

  1. Configure a claude-cli-backed agent with default --allowedTools mcp__*,... (matches gh-ship default at cli-backend-BDU6UI9e.js:5-69).
  2. Enable the memory-core plugin (default-enabled in shipped configs).
  3. Start a session with the agent and run a turn.
  4. Inspect the system prompt OC sends to claude-cli (the temp file under ~/.openclaw/tmp/openclaw-cli-mcp-*/mcp.json is the MCP-config side; the system prompt itself is constructed in buildCliAgentSystemPrompt).

Expected: system prompt includes a "Memory Recall" section explaining memory_search / memory_get and how to use them. Actual: section is absent because availableTools is empty.

Indirect evidence: with default config, gateway.log shows zero memory_search invocations from claude-cli backed agents over multi-week windows, while non-CLI (agent/embedded) backed agents call it normally. (Verified locally: 4 memory_search calls in 6 weeks of logs, all from [agent/embedded], zero from claude-cli.)

Suggested fix

Populate tools in the buildCliAgentSystemPrompt(...) call at prepare.runtime-DzWXf1k1.js:715 from the gateway-scoped tool list — the same list the MCP loopback already serves via resolveGatewayScopedTools(...) at mcp-http-CqosJaju.js:343-356.

Roughly:

const { tools: gatewayTools } = await resolveGatewayScopedTools({
    cfg,
    sessionKey,
    // ...whatever else resolveGatewayScopedTools needs from the existing prepare ctx
});

buildCliAgentSystemPrompt({
    ...,
    tools: gatewayTools,
    ...
})

Then the availableTools set in buildAgentSystemPrompt will accurately reflect what the agent actually has, and the plugin-side buildPromptSection calls will inject the right guidance.

Related

  • Issue #79500 (dreaming narrative subagent text never reaches DREAMS.md) — separate bug, but adjacent in the same neighborhood; the dreaming pipeline can't function properly when agents never call memory_search (recall counts stay at 0, promotion gates can never be crossed).
  • The memory-core "Memory Recall" guidance text intentionally documented at extensions/memory-core/index.js:102 is the canonical reference for what should be injected.

Stack

  • OpenClaw 2026.5.12, brew-installed at /opt/homebrew/lib/node_modules/openclaw/
  • macOS Sequoia 15.x, M5 Max
  • Three claude-cli-backed agents (claude-cli/claude-opus-4-7)
  • Claude CLI 2.1.143

Happy to provide the agent configs, redacted log excerpts, or work on a PR if useful.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING