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
- Configure a claude-cli-backed agent with default
--allowedTools mcp__*,... (matches gh-ship default at cli-backend-BDU6UI9e.js:5-69).
- Enable the memory-core plugin (default-enabled in shipped configs).
- Start a session with the agent and run a turn.
- 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
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.
Summary
buildCliAgentSystemPromptis invoked withtools: []inprepare.runtime, which causesbuildAgentSystemPromptto computeavailableTools = new Set([]). Plugins that gate their auto-injected system-prompt sections on tool availability (notablymemory-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_searchandmcp__openclaw__memory_getavailable (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 current2026.5.12bundle, filedist/prepare.runtime-DzWXf1k1.jsline 715) builds the claude-cli system prompt:That flows into
helpers(dist/helpers-B1ZH_nQ4.js:117):Which lands in
buildAgentSystemPrompt(dist/system-prompt-config-DpjdHIUy.js:443):buildMemorySection(dist/system-prompt-config-DpjdHIUy.js:160-166) callsbuildPromptSectionfromextensions/memory-core/index.js:99-110: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 toresolveGatewayScopedTools(...)(tool-resolution-D_3lVp4s.js:13-103) and serves the real tool list. So tools/list and the system-prompt'savailableToolsare inconsistent: tools/list has memory_search; the system prompt acts as if it doesn't.Reproducer
--allowedTools mcp__*,...(matches gh-ship default atcli-backend-BDU6UI9e.js:5-69).~/.openclaw/tmp/openclaw-cli-mcp-*/mcp.jsonis the MCP-config side; the system prompt itself is constructed inbuildCliAgentSystemPrompt).Expected: system prompt includes a "Memory Recall" section explaining
memory_search/memory_getand how to use them.Actual: section is absent because
availableToolsis empty.Indirect evidence: with default config,
gateway.logshows zeromemory_searchinvocations from claude-cli backed agents over multi-week windows, while non-CLI (agent/embedded) backed agents call it normally. (Verified locally: 4memory_searchcalls in 6 weeks of logs, all from[agent/embedded], zero from claude-cli.)Suggested fix
Populate
toolsin thebuildCliAgentSystemPrompt(...)call atprepare.runtime-DzWXf1k1.js:715from the gateway-scoped tool list — the same list the MCP loopback already serves viaresolveGatewayScopedTools(...)atmcp-http-CqosJaju.js:343-356.Roughly:
Then the
availableToolsset inbuildAgentSystemPromptwill accurately reflect what the agent actually has, and the plugin-sidebuildPromptSectioncalls will inject the right guidance.Related
memory_search(recall counts stay at 0, promotion gates can never be crossed).extensions/memory-core/index.js:102is the canonical reference for what should be injected.Stack
2026.5.12, brew-installed at/opt/homebrew/lib/node_modules/openclaw/claude-cli/claude-opus-4-7)Happy to provide the agent configs, redacted log excerpts, or work on a PR if useful.