## Root Cause Analysis: Schema Mismatch in memory_get / memory_search Tool Registration
### Summary
The TypeBox schema rejection reported in #75244 is symptomatic of a broader architectural mismatch in the `memory-core` plugin. The root cause is **duplicate schema definitions** that use incompatible approaches, causing tool validation to fail silently and tools to be dropped from the agent's tool registry.
### The Problem
**Two conflicting schema definitions exist:**
1. **In `extensions/memory-core/index.ts` (lines 61-83):**
- Uses plain JSON Schema objects (`type: "object"`, `properties: {}`, `required: []`)
- Directly instantiated as static module-level constants
- Example: `const MemorySearchSchema = { type: "object", properties: {...}, required: ["query"], ...}`
2. **In `extensions/memory-core/src/tools.shared.ts` (lines 34-44):**
- Uses TypeBox `Type.Object()` API (`@sinclair/typebox`)
- Produces TypeBox-wrapped schema objects with internal Symbol properties
- Example: `export const MemorySearchSchema = Type.Object({ query: Type.String(), ... })`
### What Happens
1. **Lazy loader** (`index.ts`) passes the plain JSON schema to the tool factory
2. **Actual tool implementation** (`tools.ts`) imports and uses the TypeBox schema from `tools.shared.ts`
3. **Tool validation** expects `parameters` to be a plain record object (`isRecord()` check)
4. **TypeBox schema object** fails `isRecord()` due to internal Symbol properties or Proxy wrapping
5. **Tool is rejected** with `"memory_search missing parameters object"` error
6. **Tools are silently dropped** from the agent's runtime tool registry (error logged but never surfaced)
### Evidence
**File: `extensions/memory-core/index.ts` (lazy wrapper layer)**
```typescript
const MemoryGetSchema = {
type: "object",
properties: {
path: { type: "string" },
from: { type: "number" },
lines: { type: "number" },
corpus: { type: "string", enum: ["memory", "wiki", "all"] },
},
required: ["path"],
additionalProperties: false,
} as const satisfies TSchema;File: extensions/memory-core/src/tools.shared.ts (actual tool implementation)
export const MemoryGetSchema = Type.Object({
path: Type.String(),
from: Type.Optional(Type.Number()),
lines: Type.Optional(Type.Number()),
corpus: Type.Optional(stringEnum(["memory", "wiki", "all"])),
});File: tools-Dt0Yx7_E.js (validation that rejects the tool)
function isRecord(value) {
return Boolean(value && typeof value === "object" && !Array.isArray(value));
}
// This fails for TypeBox schemas:
if (!isRecord(tool.parameters)) return `${name} missing parameters object`;- Silent tool loss: Agents lose
memory_searchandmemory_getwithout visible error - Cascading failures: Without memory tools, agents compensate with more tool calls → context overflow → stuck sessions
- Recurring per-turn: Error fires on every agent turn (tools are re-validated each turn)
- Workaround required: External plugins like
openclaw-remnicforced to inline schemas instead of referencing module-level variables
-
Unify schemas to plain JSON (Recommended):
- Remove TypeBox from
tools.shared.ts - Use plain JSON Schema objects everywhere
- Lowest risk, maintains current validation logic
- Effort: Low
- Remove TypeBox from
-
Update validation to accept TypeBox:
- Add TypeBox-aware check:
value?.[Symbol.for("@sinclair/typebox/Kind")] - Or use a try-catch around
isRecord()with schema serialization fallback - Effort: Low-Medium
- Add TypeBox-aware check:
-
Centralize schema definitions:
- Consolidate schemas to a single location
- Use a schema builder that produces plain JSON objects
- Effort: Medium
Implement Option 1 (unify to plain JSON) in tools.shared.ts:
- Remove TypeBox dependency from schema definitions
- Keep TypeBox only where needed for other schema transformations
- Add a regression test: "Tool with module-level schema reference should not be rejected as malformed"
This aligns with the fix pattern from #69423 (tool parameter validation) and will resolve the cascading failures experienced by users of both bundled and third-party memory plugins.
---
**Note for the issue:** This analysis should be cross-linked with:
- #64877 (config.patch schema validation issues)
- #72885 (memory tool corpus field mislabeling)
- #83013 (tencentdb config schema rejection)
All point to the same root cause: schema definition/validation mismatch in tool registration.