Summary
memory_save MCP tool defines project in its input schema and the handler (src/mcp/server.ts:175-185) correctly forwards it to mem::remember. The remember function (src/functions/remember.ts:121) spreads project onto the Memory object before kv.set(). However, the iii engine's serialization layer drops the field — it is never persisted to the binary store.
Evidence
-
Unit test passes — test/remember-project-scope.test.ts mocks the KV store and verifies the field is written. This confirms the agentmemory code does the right thing.
-
Real engine drops it — All memories saved via memory_save(project="juice") show project=<missing> when read back from:
- The
GET /agentmemory/memories REST endpoint
- The binary file (
mem%3Amemories.bin at ./data/state_store.db/)
- The MCP
memory_recall tool
-
Direct binary file edit confirms engine rejects unknown fields — Adding project to each memory in the .bin file caused the engine to start with 0 memories (silently recreating the file from scratch).
Impact
memory_diagnose check memory-project-coverage permanently shows failure
POST /agentmemory/migrate {"step":"infer-memory-projects"} returns ambiguous: 256, updated: 0
- Sessions CAN be created with project scope (confirmed via
POST /agentmemory/session/start), but the project never flows down to memories saved through any external API
- Cross-project isolation and
inferMemoryProjects() backfill are both broken in production
Root Cause
The Memory type (src/types.ts) defines project?: string and remember.ts sets it. The inferMemoryProjects() function in src/functions/migrate.ts also writes project via the same kv.set() path. This suggests the issue is in the iii engine's state::set implementation — it serializes memories using a fixed schema that rejects unknown keys.
To Reproduce
npx @agentmemory/agentmemory # start engine
# Save with project
npx @agentmemory/agentmemory mcp # then call memory_save with project="test"
# Read back — project field is missing
curl http://localhost:3111/agentmemory/memories?limit=1 | jq '.memories[0].project'
# Output: null
Or directly via MCP tool:
- Call
memory_save with project: "juice"
- Response object has no
project field
- Binary file at
./data/state_store.db/mem%3Amemories.bin confirms it's absent
Expected Behavior
memory_save(project="juice") should persist the project field on the memory, and the diagnose check should pass after running infer-memory-projects.
Summary
memory_saveMCP tool definesprojectin its input schema and the handler (src/mcp/server.ts:175-185) correctly forwards it tomem::remember. Therememberfunction (src/functions/remember.ts:121) spreadsprojectonto theMemoryobject beforekv.set(). However, the iii engine's serialization layer drops the field — it is never persisted to the binary store.Evidence
Unit test passes —
test/remember-project-scope.test.tsmocks the KV store and verifies the field is written. This confirms the agentmemory code does the right thing.Real engine drops it — All memories saved via
memory_save(project="juice")showproject=<missing>when read back from:GET /agentmemory/memoriesREST endpointmem%3Amemories.binat./data/state_store.db/)memory_recalltoolDirect binary file edit confirms engine rejects unknown fields — Adding
projectto each memory in the.binfile caused the engine to start with 0 memories (silently recreating the file from scratch).Impact
memory_diagnosecheckmemory-project-coveragepermanently shows failurePOST /agentmemory/migrate {"step":"infer-memory-projects"}returnsambiguous: 256, updated: 0POST /agentmemory/session/start), but the project never flows down to memories saved through any external APIinferMemoryProjects()backfill are both broken in productionRoot Cause
The
Memorytype (src/types.ts) definesproject?: stringandremember.tssets it. TheinferMemoryProjects()function insrc/functions/migrate.tsalso writesprojectvia the samekv.set()path. This suggests the issue is in the iii engine'sstate::setimplementation — it serializes memories using a fixed schema that rejects unknown keys.To Reproduce
Or directly via MCP tool:
memory_savewithproject: "juice"projectfield./data/state_store.db/mem%3Amemories.binconfirms it's absentExpected Behavior
memory_save(project="juice")should persist theprojectfield on the memory, and the diagnose check should pass after runninginfer-memory-projects.