Repository navigation
[BUG] Project-scoped writes (ingest with project_id, remember_decision) are stored without embeddings #216
Description
What happened?
Memories written through the project path never get a semantic vector, even when an embedding provider is configured and working. They are stored with vectors.semantic: null, so recall scores them vector: 0 and they can only ever match lexically.
This affects every longmemory_remember_decision call (it requires project_id) and every longmemory_ingest call that passes project_id. The same text ingested without project_id is embedded correctly.
Expected: project-scoped writes are embedded with the configured provider, like the non-project path.
Cause. The non-project path embeds before ingesting (src/core/create_memory.ts:389, inside ingest()). The project path does not:
src/mcp/tools/ingest.ts:33andsrc/mcp/tools/remember_decision.ts:31callproject_memory.ingestProjectEvent()- which calls
ingest_project_event()→memory.applyImportPlan(built.plan)(src/core/project/project_ingest.ts:133) applyImportPlan(src/core/create_memory.ts:544) callsengine.ingest({...})at line 610 with novector, inside a synchronousimport_transaction().run(...)- so
ingest_enginestoresvectors: { semantic: parsed.event.vector ?? null, ... }(src/core/engine/ingest_engine.ts:387) asnull
src/core/connectors/connector_ingest.ts:89 also goes through applyImportPlan, so connector imports are probably affected too (not tested).
A possible fix: compute the embeddings for plan.nodes_to_create before entering the transaction, using the same embed(cfg.embedding_provider, multilingual_embeddings, embedding_cache, …, 'document') call as ingest(), and pass each as vector to engine.ingest.
Related: #214 fixes the same pattern (a write path that bypasses the configured embedder) for legacy migration.
Steps to Reproduce
- Start the MCP HTTP server with a working embedding provider, e.g.:
Startup logs
LONGMEMORY_EMBEDDING_PROVIDER=openai LONGMEMORY_EMBEDDING_TIER=deep LONGMEMORY_EMBEDDING_DIMENSION=1024 LONGMEMORY_OPENAI_BASE_URL=<any OpenAI-compatible /embeddings endpoint> LONGMEMORY_OPENAI_EMBEDDING_MODEL=<model> OPENAI_API_KEY=<key>embedding provider: openai. - Call
longmemory_ingestwithproject_id: "demo"and the text:
the staging database credentials rotate every forty-five days, and Dana owns that schedule. - Call
longmemory_recallwithmode: "associative",project_id: "demo", queryhow often do test DB passwords change.
The record ranks first, butitems[0].node.vectors.semanticisnullanditems[0].breakdown.vectoris0. - Repeat steps 2–3 without
project_id.
Nowvectors.semanticis a 1024-dimension array andbreakdown.vectoris0.390, withlexical: 0: a real semantic match.
Component
Backend (API/Server)
Environment
- LongMemory
4da4986in Docker (node:22-bookworm-slim), MCP over streamable HTTP - Embedding provider
openaiagainst an OpenAI-compatible endpoint, 1024 dimensions, tierdeep - The same code path is unchanged on
mainat9ee2c8e(2026-09-20)
Relevant log output
No error is logged: the provider works, it is just never called for project writes. Recall breakdown for the same text:
with project_id: vectors.semantic = null breakdown.vector = 0 lexical = 0
without project_id: vectors.semantic = array(1024) breakdown.vector = 0.390 lexical = 0
Code of Conduct
- I agree to follow this project's Code of Conduct
Activity
Patch LongMemory: embed project-scoped writes