Skip to main content

Cross-channel memory infrastructure for conversational AI agents.

Project description

Memnex

Cross-channel permanent memory for AI agents.

Memnex is a memory service for conversational AI agents. When the same user moves from a phone call to WhatsApp to web chat, every agent on every channel already knows what happened on the previous channels: same name, same open issues, same preferences, same history. No more "how can I help you today?" on channel three.

It plugs in over the Model Context Protocol (MCP), so any MCP-compatible agent (Claude Desktop, Cursor, LangGraph, CrewAI, your own runtime) can use it without writing integration code.

License: Apache 2.0 Python 3.11+


Why this exists

Most agent platforms have short-term conversation memory (the chat scrollback). They don't have long-term, cross-channel memory. So a customer who calls support on Monday and messages on Wednesday talks to two strangers, even when both are powered by the same LLM. They re-explain everything. Trust evaporates.

Memnex fixes this by being a shared memory layer the agents talk to. Each agent writes durable facts as the conversation unfolds (intent, preferences, issues, resolutions, profile attributes), and reads them back at the start of every turn. When channels hand off, nothing is lost. When a session disconnects mid-flow, only the un-written facts are lost. Write per sub-intent and even that goes away.


Quick start

As an MCP server (recommended for agent runtimes)

Memnex is open-source and self-hosted. Run the server yourself (your machine, your cloud, Railway, Fly.io, AWS, GCP, anywhere a Python process can run); your agents connect to it over MCP.

pip install memnex
export GOOGLE_API_KEY=...                  # for embeddings
export MEMNEX_POSTGRES_URL=postgres://...  # or leave unset for in-memory (dev only)
export MEMNEX_DEV_KEY=1                    # auto-creates a dev API key on boot
memnex serve mcp --transport stdio
# stderr: [memnex] MEMNEX_SECRET_KEY=mx_live_k.....

Take the printed key and put it in your MCP client config:

{
  "mcpServers": {
    "memnex": {
      "command": "memnex",
      "args": ["serve", "mcp", "--transport", "stdio"],
      "env": {
        "MEMNEX_SECRET_KEY": "mx_live_kXXXXXXXX_<secret>",
        "MEMNEX_CHANNEL": "voice"
      }
    }
  }
}

For a real network endpoint instead of a stdio subprocess, run memnex serve mcp --transport streamable-http --port 8500 and point your client at http://your-host:8500/mcp with the same API key in headers.

Common deployment mistake: putting GOOGLE_API_KEY or MEMNEX_POSTGRES_URL in the client env block. Those are server-side infrastructure secrets. Set them where the server runs, never in the agent's MCP config. The client only ever needs MEMNEX_SECRET_KEY and MEMNEX_CHANNEL. See Configuration for the full split.

Tenants integrate via MCP, not by importing Memnex into Python. The Python codebase is what runs on the server. Self-hosters and contributors may run it directly. See the operator guide for that path.


What the MCP server exposes

Three primitives: Tools (functions the agent calls), Resources (read-only data the host app fetches), Prompts (reusable templates the host can pull).

Tools (5)

Tool Purpose
memory_write Store one or more structured facts about the user. Pydantic-validated. No LLM on the hot path.
memory_read Fetch formatted memory context for one user, sized to a token budget.
memory_search Semantic search over a single user's memories.
memory_forget GDPR purge. Wipes Redis, Postgres, Qdrant, and pending events for the user.
memory_trace Given a draft agent reply, return the source memories that could have produced it. Empty hits suggests a hallucination.

Example call:

{
  "tool": "memory_write",
  "arguments": {
    "user_id": "u_123",
    "facts": [
      {
        "fact": "Wants to cancel order XYZ",
        "type": "intent",
        "entities": ["order:XYZ"],
        "confidence": 0.95
      }
    ]
  }
}

Resources (3)

URI Returns When to read
memnex://schema/fact-types Markdown describing the 5 fact types with examples and the entities "type:value" convention Once at agent startup, so the host LLM learns the taxonomy
memnex://users/{user_id}/memories JSON of all active memories for one user (tenant-scoped) When you want to render a "what we remember" panel in your support UI
memnex://tenants/me/stats JSON with per-tenant counts and oldest/newest timestamps Admin dashboard, health check, billing/usage view

Prompts (3)

Name When to use
memory-writer Pull at agent startup as the system-prompt section that teaches the LLM when to write (per sub-intent, not at end of conversation) and how (5 types, entities convention, structured facts over raw text).
memory-reader Pull at agent startup to teach the LLM how to call memory_read once per turn and where to fold the returned context into its prompt without echoing it verbatim.
hallucination-check Pull when you want a verification step. Wraps memory_trace so the agent verifies its draft reply against stored facts before sending.

Architecture

                   ┌────────────────┐
   Voice agent ──▶ │                │
                   │                │      Identity ──▶ phone / wa / email / web normalization
WhatsApp agent ──▶ │  MCP / REST /  │ ──▶  Memory   ──▶ extract · score · conflict · compress
                   │   stdio        │      Privacy  ──▶ regex + Presidio · GDPR forget
   Web agent  ──▶  │                │      Audit    ──▶ HMAC-signed write ledger
                   └────────────────┘
                          │
                          ▼
              ┌─────────┬─────────┬─────────┐
              │  Redis  │ Postgres│ Qdrant  │
              │  (hot)  │ (warm,  │(semantic│
              │         │  RLS)   │  vector)│
              └─────────┴─────────┴─────────┘
                          ▲
                          │
                      embeddings

All four layers (Identity, Memory, Privacy, Audit) are tenant-scoped. Storage is pluggable behind HotStore / WarmStore / SemanticStore protocols, so the same code runs against in-memory backends in tests and real services in production.

See the architecture doc for the full design.


Configuration

Two distinct sets of environment variables. Mixing them up is the single most common deployment mistake.

Server-side (set by whoever runs the Memnex server)

These are infrastructure secrets. They live on the operator's side. Never copy these into an MCP client config.

Variable Purpose
MEMNEX_POSTGRES_URL Warm storage. Leave unset for in-memory.
MEMNEX_REDIS_URL Hot cache. Leave unset for in-memory.
MEMNEX_QDRANT_URL Semantic vector store. Leave unset for in-memory.
GOOGLE_API_KEY Embeddings (models/text-embedding-004).
MEMNEX_AUDIT_KEY HMAC key that signs audit receipts.
MEMNEX_JWT_SIGNING_KEY Required for the SaaS dashboard register/login flow.
MEMNEX_DEV_KEY Set to 1 to auto-create a throwaway dev tenant on memnex serve mcp boot. Never set in production.

Generative LLM (legacy, opt-in): MEMNEX_LLM_PROVIDER and MEMNEX_LLM_API_KEY only have an effect if you explicitly switch the provider away from the default none. They are used solely by the legacy raw_text extraction path; the structured-fact path that all current tools and prompts recommend never invokes a generative LLM. Most operators can leave both unset.

Client-side (set by the tenant in their MCP client config)

Variable Purpose
MEMNEX_SECRET_KEY The tenant's API key, in the form mx_live_kXXXX_<secret>.
MEMNEX_CHANNEL Which channel this agent represents: voice / whatsapp / web / sms / app. Drives output formatting.

A copy-paste-ready template is at .env.example.


Storage backends

Layer Default (no setup) Production
Hot (recent reads) In-memory dict Redis
Warm (durable facts) In-memory dict Postgres (with RLS for tenant isolation)
Semantic (embeddings) In-memory list Qdrant
Embeddings model Hash fallback (testing only) Google text-embedding-004 (768 dim)

All four are gated behind protocol interfaces in src/memnex/storage/base.py. A new backend is one new class implementing the protocol; no core changes required.


How we compare

Quick orientation. None of these are exact substitutes for each other; pick based on what matters most to you.

Memnex Mem0 Zep Letta OpenAI memory
Cross-channel by design partial partial partial
Multi-tenant w/ RLS n/a
MCP-native ❌ (SDK) ❌ (SDK) ❌ (SDK)
GDPR forget receipts ✅ signed partial n/a
Regulated PII masking at write partial n/a
Audit ledger (HMAC)
Self-hostable

If you want a hosted memory backend bolted to ChatGPT, use OpenAI memory. If you want the smallest possible API for a single-app agent, use Mem0. If you need cross-channel, multi-tenant, compliance-aware memory exposed over MCP, that's where Memnex sits.

See the comparison doc for the longer version.


Documentation

Full documentation lives in the docs/ directory on GitHub. Routed by audience:


Contributing

PRs welcome. Read CONTRIBUTING.md for the dev loop and the architectural invariants we hold to. For security issues, see SECURITY.md.

License

Apache License 2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

memnex-0.1.1.tar.gz (135.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

memnex-0.1.1-py3-none-any.whl (124.5 kB view details)

Uploaded Python 3

File details

Details for the file memnex-0.1.1.tar.gz.

File metadata

  • Download URL: memnex-0.1.1.tar.gz
  • Upload date:
  • Size: 135.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for memnex-0.1.1.tar.gz
Algorithm Hash digest
SHA256 ccd417880952ddb01f9a85c3693a7c7fe1650f4d6e2cac4fe23f122934361874
MD5 b5c155899218efd137a46129b4b04719
BLAKE2b-256 a204808d331511948189929a944113448d1cc514197fe81c1c541c9a1bcdb9e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for memnex-0.1.1.tar.gz:

Publisher: release.yml on vtensor/memnex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file memnex-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: memnex-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 124.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for memnex-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 63ca5078c1143202a74ee76cf7ae3b7e557c73939034f076eecfcd3d6ae37eb5
MD5 5e94a65ccebdd7c2365344f0440e4d1b
BLAKE2b-256 ba24ec95b08e6720f6395bd7d8faa9db1c60b992a568e3885797373d96945818

See more details on using hashes here.

Provenance

The following attestation bundles were made for memnex-0.1.1-py3-none-any.whl:

Publisher: release.yml on vtensor/memnex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page