The Problem

Stateless LLM‑driven agents lose context after each request, forcing developers to re‑implement ad‑hoc persistence layers. The result is duplicated code, fragile serialisation, and limited ability to build truly personalised assistants.

What This Does

MemMachine delivers a reusable memory service that stores three tiers of data – working, episodic (graph‑based), and profile (SQL) – and exposes them via a RESTful MCP server and language‑specific client libraries. The core server lives under packages/server/ (e.g., memmachine_server/episodic_memory/ and memmachine_server/common/embedder/). Client SDKs are in packages/client/, with the Python entry point memmachine_client/client.py. Example applications (e.g., examples/simple_chatbot/app.py) show a five‑line integration pattern that creates a MemMachineClient, obtains a project, and calls memory.add() / memory.search().

Integrations for LangChain, CrewAI, LlamaIndex, etc., are under integrations/ and each provides a thin wrapper that imports the client and registers a memory backend.

How It Is Wired

Execution starts at the chosen entry point, for instance examples/simple_chatbot/app.py:

  1. app.py creates a MemMachineClient (class defined in packages/client/src/memmachine_client/client.py).
  2. The client reads configuration from packages/client/src/memmachine_client/config.py and builds a Project object (packages/client/src/memmachine_client/project.py).
  3. Calling project.memory(...) returns a Memory instance (packages/client/src/memmachine_client/memory.py).
  4. Memory.add() packages the payload and issues an HTTP POST to the server (memmachine_server/episodic_memory/service_locator.py routes the request).
  5. The server’s service locator forwards to the appropriate service (memmachine_server/episodic_memory/long_term_memory/long_term_memory.py) which persists data via the embedder (memmachine_server/common/embedder/embedder.py) and the Neo4j driver (configured in deployments/helm/templates/neo4j-deployment.yaml).

The most connected module is packages/server/src/memmachine_server/common/reranker/reranker (imported by eight other modules). The client side shows a small cycle among client.py, memory.py, and config.py (four modules in a circular import) that inflates the blast radius for any change to shared types. The longest nesting depth reaches eight levels in long_term_memory.py, making the control flow hard to follow.

All network I/O passes through the thin HTTP client in client.py; the server’s public API is defined in packages/server/src/memmachine_server/api/. No file currently maps a direct file‑system write outside the database layers, so the persistence side‑effects are confined to the Neo4j and PostgreSQL Helm charts (deployments/helm/templates/*.yaml).

How To Use It

# Clone the repo
git clone https://github.com/moses-y/MemMachine
cd MemMachine

# Build the server container (Dockerfile at repo root)
docker build -t memmachine/server:dev .

# Start dependencies (Neo4j, PostgreSQL) and the server
docker-compose up -d   # uses docker-compose.yml

# Install the Python client in a virtualenv
python -m venv .venv
source .venv/bin/activate
pip install -r examples/simple_chatbot/requirements.txt

Configuration files:

  • deployments/helm/values.yaml – overrides for Neo4j/Postgres credentials.
  • .env.example in integrations/dify/plugin/ – shows required env vars for that plugin.

Run the demo chatbot:

python examples/simple_chatbot/app.py

The script prints a prompt, stores user utterances via the client, and retrieves them on subsequent turns.

Real‑World Use

A SaaS product that offers travel planning can embed memmachine_client in its backend service. Each user session creates a Memory tied to a user_id. The episodic graph records prior itinerary discussions, while profile memory keeps static preferences (seat type, airline loyalty). When the user returns weeks later, a single memory.search("flight preferences") call restores context without rebuilding a custom DB layer.

Code Health & Issues

Measured findings (static analysis) – 27 high, 116 medium:

  • High – Cognitive load: deep nesting (24 files, e.g., long_term_memory.py).
  • High – Soundness: import cycles (4 files, e.g., client.py).
  • High – Clarity: duplicated 6‑line blocks across 147 files.
  • Medium – Resilience: broad except: handling (22 files).
  • High – Oversized files: >1500 lines in memory.py and related modules.

Code‑Health audit (CI‑visible)

SeverityIssueLocation
HighPin GitHub Actions to commit SHAs.github/workflows/*.yml
MediumUse lockfile in CI (npm ci/pip install -r lock).github/workflows/*.yml
MediumPin Docker base image by digestDockerfile
MediumAdd dependency‑vulnerability scan step.github/workflows/*.yml
MediumMove large dataset (wikimultihop.json) to LFSevaluation/data/
MediumDisable credential persistence on checkout.github/workflows/installation-test.yml
MediumAdd non‑root USER to containerDockerfile
LowSet timeout-minutes on workflow jobs.github/workflows/docker-image.yml
LowAdd .editorconfig / formatter configrepository root

The repo includes a full test suite (140 test files) and CI pipelines for linting, SBOM generation, and package publishing. A Helm chart (deployments/helm/) provides production‑grade deployment, but the chart contains a committed secrets.yaml template that may expose placeholder values.

The Bottom Line

MemMachine offers a coherent, multi‑tier memory service with ready‑made client SDKs and a breadth of integrations. The architecture is functional but hampered by deep nesting, import cycles, and duplicated logic that raise maintenance costs. Teams that need a plug‑and‑play memory layer and can allocate effort to refactor the client/server cores will find it valuable; projects with strict code‑quality mandates should address the highlighted health issues first.