memrails
v0.1.0
Published
A per-user "brain": file-backed memory for AI agents, organized into four human memory systems (episodic, semantic, procedural, perspective). Decompose raw text into typed memories, retain history on changes, and recall answers with cited sources.
Maintainers
Readme
memrails
A per-user "brain" for AI agents: file-backed memory organized into the four human memory systems — episodic (timed events), semantic (durable facts), procedural (how-to), and perspective (opinions/preferences). It decomposes raw text into typed memories, retains history when facts change (ask "who is my manager?" and "who was my previous manager?"), and answers questions with cited sources.
Under the hood it's a small Python service (FastAPI + SQLite + local embeddings, optionally Claude Haiku for high-quality decompose/recall). This npm package wraps it so you can try it in one command — no Python setup required.
Quick start
npx memrails upThe first run provisions a self-contained Python virtualenv (CPU-only torch +
the embedding model) — that takes a few minutes. After that it's instant, and the
server is live on http://localhost:8080.
Requires Node 18+ and Python 3.9+ on your PATH. For high-quality memory, set
ANTHROPIC_API_KEY(otherwise it falls back to a lower-quality offline heuristic). See Configuration.
In another terminal, talk to it from the CLI:
npx memrails add alice "Started at Helix today. My manager is Priya."
npx memrails recall alice "who is my manager?"
npx memrails add alice "Reorg — my manager is now Jane."
npx memrails recall alice "who was my previous manager?" # → Priya
npx memrails brain alice # the rendered brainUse it from JavaScript
import { Memrails } from "memrails";
const m = new Memrails(); // http://localhost:8080 by default
// const m = new Memrails({ url: "https://your-app.fly.dev", apiKey: process.env.MEMRAILS_API_KEY });
await m.add("alice", "Started at Helix today. My manager is Priya.");
const { answer, sources } = await m.recall("alice", "who is my manager?");
console.log(answer); // → "Priya"
console.log(sources); // → the memories that grounded the answerWire it into an agent loop — recall to ground the reply, then remember the turn:
async function onMessage(userId, text) {
const { answer: context } = await m.recall(userId, text);
const reply = await yourAgent(text, { memory: context });
m.add(userId, text); // fire-and-forget is fine
return reply;
}CLI
memrails up [--port 8080] Provision (first run) and start the server
memrails setup [--force] Provision the Python env without starting it
memrails add <user> <text…> Remember text for a user
memrails recall <user> <query…> Ask the user's memory a question
memrails brain <user> Print the user's rendered markdown brain
memrails stats [user] Memory counts (all users, or one)
memrails health Check a running server + active LLM provider
memrails doctor Diagnose local setupFlags: --port <n>, --url <url> (target a remote server), --key <key> (API key).
HTTP API
The CLI and JS client are thin wrappers over an HTTP API you can call from any
language. All /memory/* endpoints require a key when MEMRAILS_API_KEY is set —
send it as Authorization: Bearer <key> or X-API-Key: <key>.
| Method & path | Body / params | Returns |
|----------------------|--------------------------------------|---------|
| GET /health | — | status + active LLM provider (no auth) |
| POST /memory/add | {user, text, title?, date?} | counts added/skipped/superseded |
| POST /memory/recall| {user, query, top_k?, synthesize?} | {answer, sources[]} |
| GET /memory/brain | ?user=<id> | the user's rendered markdown brain |
| GET /memory/stats | ?user=<id> (optional) | memory counts per user/type |
user is your platform's stable id for the person (e.g. a Telegram user id).
memrails is multi-tenant by that value — each user gets an isolated brain.
Configuration
Set these as environment variables or in a .env file (in your working directory
or the package dir). A template is in env.example.
| Variable | Purpose |
|---------------------|---------|
| ANTHROPIC_API_KEY | Enables the Claude Haiku 4.5 provider for high-quality decompose + recall. Without it, memrails uses a deterministic offline heuristic (lower quality). |
| MEMRAILS_API_KEY | If set, required on every /memory/* endpoint. Leave unset only for local dev. |
| PORT | Server port (default 8080). |
| BRAIN_ROOT | Where brains (sqlite + markdown) are stored. Defaults to ./memrails-data in your working directory. |
Deploying
For production you'll usually run the service as a container rather than via npx.
The included Dockerfile installs CPU-only torch and bakes the
embedding model into the image, and fly.toml is a ready Fly.io config
(2GB RAM, a mounted volume for brains, scale-to-zero):
fly launch --copy-config --no-deploy # pick a unique app name
fly volumes create memrails_data --size 1
fly secrets set ANTHROPIC_API_KEY=sk-ant-... MEMRAILS_API_KEY=$(openssl rand -hex 32)
fly deployThen point the JS client at it: new Memrails({ url, apiKey }).
How it works & scaling
This deployment is single-writer by design: SQLite + one process, with all
brain access serialized onto a single thread (see service.py).
That's correct and fast enough for one bot / moderate load. To scale to many
instances or millions of memories, swap the storage inside Brain for
PostgreSQL + pgvector — that's a change to memrails_v2.py's storage layer,
not to the API surface above, so your client code doesn't move.
License
MIT
