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:
app.pycreates aMemMachineClient(class defined inpackages/client/src/memmachine_client/client.py).- The client reads configuration from
packages/client/src/memmachine_client/config.pyand builds aProjectobject (packages/client/src/memmachine_client/project.py). - Calling
project.memory(...)returns aMemoryinstance (packages/client/src/memmachine_client/memory.py). Memory.add()packages the payload and issues an HTTP POST to the server (memmachine_server/episodic_memory/service_locator.pyroutes the request).- 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 indeployments/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.exampleinintegrations/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.pyand related modules.
Code‑Health audit (CI‑visible)
| Severity | Issue | Location |
|---|---|---|
| High | Pin GitHub Actions to commit SHAs | .github/workflows/*.yml |
| Medium | Use lockfile in CI (npm ci/pip install -r lock) | .github/workflows/*.yml |
| Medium | Pin Docker base image by digest | Dockerfile |
| Medium | Add dependency‑vulnerability scan step | .github/workflows/*.yml |
| Medium | Move large dataset (wikimultihop.json) to LFS | evaluation/data/ |
| Medium | Disable credential persistence on checkout | .github/workflows/installation-test.yml |
| Medium | Add non‑root USER to container | Dockerfile |
| Low | Set timeout-minutes on workflow jobs | .github/workflows/docker-image.yml |
| Low | Add .editorconfig / formatter config | repository 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.