Skip to content

Memory Connectors

Matt Dula edited this page Apr 18, 2026 · 3 revisions

Memory Connectors

Nakatomi doesn't implement semantic memory on purpose. Agents already have good memory systems. Instead, Nakatomi is the structured spine and ships a bidirectional bridge to external memory providers.

How it works

%%{init: {"look": "handDrawn", "theme": "dark"}}%%
flowchart LR
    W[CRM mutation] --> Emit
    Emit --> TL[(timeline)]
    Emit -.->|configured connectors| MC[DocDeploy /<br/>Supermemory /<br/>GBrain]
    MC --> Link[(MemoryLink row)]

    R[memory_recall] --> Fan[fan-out]
    Fan --> MC
    MC --> Merge[merge by score]
    Merge --> Out[results + crm_links]
Loading

Every CRM write gets mirrored to every enabled connector. Every recall fans out across them. Results come back decorated with the MemoryLink rows already on file, so agents can pivot from a memory back into the CRM in the same call.

Enable connectors

Comma-separated list in the environment:

MEMORY_CONNECTORS=docdeploy,supermemory

Empty disables the whole subsystem. /memory/* endpoints still work but return empty.

DocDeploy

Pay-per-call encrypted memory on Base (x402). https://www.docdeploy.io

DOCDEPLOY_API_KEY=...
DOCDEPLOY_BASE_URL=https://x402.docdeploy.io

Cost model: ~cents per remember/recall call. Good for small, high-signal workspaces where you're happy to pay per event.

Supermemory

Subscription API. https://supermemory.ai

SUPERMEMORY_API_KEY=...
SUPERMEMORY_BASE_URL=https://api.supermemory.ai

Container tags (ws:<workspace_id>) keep workspaces isolated. Flat rate, so good for chatty workloads.

GBrain

Self-hosted, MCP-first, self-wiring knowledge graph. https://github.com/garrytan/gbrain

MEMORY_CONNECTORS=gbrain
GBRAIN_MCP_URL=https://your-brain.example.com/mcp
GBRAIN_TOKEN=...

The adapter is a stub — it demonstrates the wiring but the _call_tool body is intentionally a no-op. Fill it in with a real MCP client session for your GBrain deployment. The MCP tools vary by GBrain build (ingest, query, etc.).

Stacking

Enabling more than one is fine:

MEMORY_CONNECTORS=docdeploy,supermemory,gbrain
  • Every memory_recall fans out, merges, sorts by score, returns the top-N across all three.
  • Every CRM write mirrors to all three (best-effort; one failing doesn't block the others).
  • memory_trace shows every connector's links for a given entity.

API

Route Purpose
GET /memory/connectors list enabled adapters
GET /memory/links list every link in the workspace (paginated; filter by connector / entity_type / entity_id)
POST /memory/recall fan-out recall (see shape below)
POST /memory/link cross-link an external memory id with a CRM entity
DELETE /memory/link/{id} remove a link
GET /memory/trace/{entity_type}/{entity_id} list links for one entity
POST /memory/webhook/{connector} inbound — memory system pushes to us

Recall

curl -X POST http://localhost:8000/memory/recall \
  -H "Authorization: Bearer nk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "query": "what did we promise Acme about delivery timelines?",
    "entity_type": "company",
    "entity_id": "<acme-uuid>",
    "limit": 10
  }'

Response:

{
  "items": [
    {
      "connector": "docdeploy",
      "external_id": "mem_abc",
      "text": "...",
      "score": 0.81,
      "metadata": {...},
      "crm_links": ["company:acme-uuid", "deal:big-deal-uuid"]
    }
  ]
}

Link

curl -X POST http://localhost:8000/memory/link \
  -H "Authorization: Bearer nk_..." \
  -d '{
    "connector": "supermemory",
    "external_id": "mem_xyz",
    "crm_entity_type": "deal",
    "crm_entity_id": "<uuid>",
    "note": "call transcript 2026-04-18"
  }'

Idempotent on the (connector, external_id, crm_entity_type, crm_entity_id) tuple. Re-posting the same link returns 409.

Inbound webhook

Memory providers that notify on writes can POST to /memory/webhook/<connector>. The adapter's parse_webhook decodes the shape and creates matching MemoryLink rows automatically. Useful for bidirectional sync: a write in the memory system shows up as a linked memory in the CRM.

MCP tools

Same capabilities, agent-native:

  • memory_list_connectors
  • memory_recall
  • memory_link
  • memory_trace

See MCP-Tools.

Conflict policy

Currently: inbound writes never overwrite CRM fields. They can create new MemoryLink rows and emit memory.linked events, but they don't mutate contact/company/deal rows. A future config will allow opt-in overwrite rules.

Writing a new adapter

  1. Create app/services/memory/adapters/<name>.py
  2. Subclass MemoryConnector (see app/services/memory/base.py)
  3. Implement store_event, recall, and optionally verify_webhook / parse_webhook
  4. Register in app/services/memory/registry.py
  5. Document env vars in .env.example and in this page

The DocDeploy and Supermemory adapters are each ~100 lines — use them as templates.

Clone this wiki locally