Active Memory Sub-Agent Returns NONE Despite Valid memory_search Results
The Active Memory sub-agent generates valid search queries and mcporter CLI returns high-scoring results, yet the sub-agent consistently returns NONE, indicating the sub-agent's internal tool call path differs from the main agent's memory bridge.
🔍 Symptom
A user on Ubuntu 24.04 with OpenClaw v2026.4.11 observes the following behavior in verbose mode:
- The Active Memory sub-agent generates appropriate search queries (e.g., "bob grandsons grandchildren names gianni jayden family")
- The
memory_searchoperation returns valid JSON results with high relevance scores (0.69–0.99) - Matching document identified:
people/bob-family.mdcontaining grandchildren names "Jayden Violette" and "Gianni Violette" - The sub-agent executes 2 search passes (indicating multi-step reasoning is functioning)
- Final result:
Active Memory: empty(NONE)
Direct CLI verification via mcporter call qmd.search returns valid, well-formatted JSON confirming the data exists in the backend.
🧠 Principle
Root Cause: Divergent Tool Registration Paths Between Main Agent and Sub-Agent
The Active Memory sub-agent operates within an embedded transport context that may use a separate tool registration namespace from the main gateway agent. This architectural separation means:
- The main agent's
memory_searchtool correctly routes through the QMD mcporter bridge to the custom backend - The sub-agent's internal
memory_searchmay invoke a different tool handler or transport layer not subject to the samememory.qmd.mcporter.*configuration - Result aggregation occurs in the sub-agent's isolated context, which may have different result acceptance thresholds
Secondary Factor: Embedded Transport Silent Failure
Known issue #41282 identifies incomplete fixes for the openai-codex/gpt-5.4 embedded transport. When the sub-agent's tool execution encounters certain conditions (timeout, malformed response, or model-specific quirks), the failure manifests silently as NONE rather than propagating an error.
Observation Gap
The /verbose output only exposes the search queries and final result timestamp, not the actual tool call input/output payload from within the sub-agent runtime. This prevents direct diagnosis of whether results are fetched and discarded, or whether the tool call itself fails.
🛠️ Fix
Diagnostic Steps
- Enable Sub-Agent Logging: Set
logLevel: "debug"in the active-memory plugin configuration to capture internal tool call traces - Instrument the Tool Bridge: Add debug logging at the QMD manager's tool invocation layer (
qmd-manager-*.js) to trace both main-agent and sub-agent calls - Verify Tool Registration Source: Confirm whether the sub-agent loads tools from the same registry as the main agent by checking
gateway/tools/registration order
Workaround Options
- Switch to Direct Memory Backend: Replace
memory.backend: "qmd"with a natively supported backend (chromadb, sqlite-vec) that registers tools identically for all agent contexts - Disable Embedded Transport: Set a different model in
plugins.entries.active-memory.configto avoid theopenai-codex/gpt-5.4embedded transport issues - Use Direct Memory Tool: If the main agent's
memory_searchworks, consider bypassing the Active Memory sub-agent and using direct memory queries in the main conversation flow
Verification Command
mcporter call qmd.search '{"query": "bob grandchildren names", "limit": 5}'Confirm this returns the expected JSON before investigating sub-agent routing.