memrust Book a demo GitHub ↗

Memory infrastructure for AI agents

Your agent doesn't need a vector database.
It needs memory.

A memory engine in Rust that answers “what do I know about this?” — not “which vectors are nearest?”

RustApache-2.0single binaryMCP over HTTPmulti-tenantPython & TypeScript SDKs
memory.recall("what is connected to Project Phoenix") relational
0.0386semantic1m ago

Dana Whitfield leads Project Phoenix

vector.0164
lexical.0164
graph.0164
recency1.00
0.0309semantic1m ago

the Billing Service rate limits at 100 requests per second

vector.0152
lexical.0000
graph.0159
recency1.00

That second memory never mentions Phoenix. It surfaced on graph — one hop through a shared entity — with lexical at zero.

The missing layer

Every other layer of the agent stack already exists.

Models, orchestration, tools, evals — each has infrastructure built for it. Memory got a vector index and a shrug. So every team building agents writes the same layer by hand: a vector store, a keyword index, fusion logic, a graph for relationships, a scheduler for expiry and summarization, access control between agents, and a protocol shim to expose it all.

memrust is that layer as one binary. Not a database an agent queries — memory an agent has.

Agent runtime Claude Code · LangGraph · OpenAI SDK · CrewAI
Tools & orchestration MCP · function calling
Memory remember · recall · forget memrust
Storage & compute disk · embeddings · your infrastructure

The ceiling nobody talks about

Ask for INC-90312 and vector search shrugs.

Agents ask for exact things constantly: error codes, ticket IDs, commit SHAs, customer names, function names. Embeddings can't separate INC-90312 from INC-90319 — near-identical strings make near-identical vectors.

The telling part: exact brute-force vector search scores the same 27%. This isn't an index-quality problem a faster ANN fixes. It's the ceiling of the embedding itself, and every pure vector store inherits it.

memrust runs BM25 and an entity graph over the same memories and fuses the rankings. Same embeddings, same corpus — different architecture.

Exact vector search · the ceiling27%
FAISS27%
Chroma27%
Qdrant27%
memrust · hybrid75%

hit@5 on 60 identifier lookups · 500 memories · identical all-MiniLM-L6-v2 embeddings for every engine · benches/agent_recall.py

Four signals, one call

Retrieval that shows its work.

Every hit comes back with its score broken out by signal. An agent can tell a strong semantic match from a lucky keyword hit — and so can you, when something surfaces that shouldn't have.

vector

Meaning

An in-crate HNSW index over your embeddings. Bring your own vectors, or let the engine call OpenAI, Gemini, or a local sentence-transformers server.

lexical

Exact terms

A BM25 inverted index for the identifiers, error codes and names that embeddings blur together.

graph

Relationships

Entities extracted at ingest, linked by co-occurrence. Finds what's connected to a thing, not just what resembles it. No external graph database.

recency

Time

Exponential decay as a first-class ranking term, because "what did we decide recently" is not a similarity question.

One memory, every agent

Your tools each remember separately. They shouldn't.

Claude Code learns something about your codebase. Cursor learns it again. Your LangGraph agent never finds out at all. Memory that lives inside one tool is not memory — it is a cache with a short life. memrust is one endpoint they all read and write, so what any of them learns, all of them know.

Claude CodeMCP over HTTP
Claude DesktopMCP over HTTP
claude.aicustom connector
CursorMCP over HTTP
WindsurfMCP over HTTP
Codex & othersMCP over HTTP
LangGraphPython SDK
CrewAIPython SDK
Your own stackHTTP, no SDK needed
Anything elseif it speaks MCP, it connects

One command, then they share a brain

# point Claude Code at hosted memory
claude mcp add --transport http memrust \
  https://your-project.memrust.dev/mcp \
  --header "Authorization: Bearer mr_live_..."

# the same URL and key in Cursor, Codex, claude.ai —
# now ask any of them: "what did we decide about pricing?"

Four tools — remember, recall, forget, entities — and recall hands the agent the per-signal breakdown, so it can weigh a strong semantic match against a lucky keyword hit instead of trusting an opaque number.

The memrust console: a recall for INC-90312 with per-signal score bars for vector, lexical, graph and recency, alongside the write panel and extracted entities

The console. Same memory the agents see.

Measured, not claimed

Every number here comes from a script in the repo.

0.64ms
recall p50 at 20k vectors — second-fastest server measured, behind pgvector
1.000
recall@10 against exact brute-force ground truth
4×
less vector memory with SQ8, applied automatically at 1024+ dims where it also runs faster
1,000
acknowledged writes, 1,000 recovered after kill -9 mid-checkpoint

What you'd otherwise assemble

One engine instead of five systems.

The usual answer to agent memory is a vector DB, a keyword index, fusion code, a graph store, a scheduler for expiry and summarization, access control, and an MCP shim. That's the stack memrust replaces.

CapabilitymemrustQdrantChromaFAISSpgvectorLanceDB
Vector search
Keyword fused into one querysetupDIY
Entity graph as a signalDIY
Per-signal score explanation
Agent API + memory kinds
TTLs & automatic consolidationcron
Multi-agent private/shared memoryfiltersfilterspoliciesfilters
MCP server for agent runtimes
One endpoint every agent shares
Tenants as fully separate indexescollectionscollectionsschemastables
API keys scoped per tenantone key/JWT
Prometheus metricsexporter
Built-in dashboard

✓ built in · anything else in that column = possible, you build it · — not available

Vector search, head to head

20,000 vectors, 384 dims, identical HNSW settings, recall against exact ground truth. Query latency is second-best among the servers and recall ties the field. Ingest is slower on purpose: memrust fsyncs every write, where the others buffer. For a memory layer that's the right trade — an agent quietly losing what it was told is worse than writing a little slower.

EngineIngest/sQuery p50recall@10
FAISS in-process35,6250.06 ms1.000
LanceDB embedded99,2388.60 ms1.000
Chroma in-process5,9070.49 ms1.000
pgvector server5,0170.46 ms1.000
Qdrant server2,4752.08 ms1.000
memrust server9880.64 ms1.000

Two minutes to first recall

Install it, remember something, ask.

# the engine — dashboard and HTTP API on :7700
cargo install memrust
memrust serve

# or the official image — multi-arch, 36 MB, non-root
docker run -p 7700:7700 -v memrust-data:/data aianytime/memrust
crates.ioPyPInpmDocker Hubprebuilt Linux & macOS binaries

From here, the developer documentation covers the full HTTP API, MCP setup for Claude Code and Cursor, LangGraph and CrewAI recipes, embeddings, the memory lifecycle and operations.

Run it for real

Multi-tenant, authenticated, observable.

The demo path needs no keys and no config. The production path is the same binary with flags — tenants that can't see each other, keys scoped to them, and metrics your existing Prometheus already knows how to scrape.

namespaces

Isolation, not a filter

A namespace is a separate engine — its own indexes, WAL, checkpoint, embedding dimension and directory. One tenant's ingest can't slow another's recall, and dropping one deletes a directory instead of scanning a shared index.

api keys

Scoped per tenant

Keys can be pinned to specific namespaces, arrive as a bearer token or header, and compare in constant time. Admin routes need an unscoped key. Leave keys off and it stays open — but says so, loudly, on a non-loopback address.

metrics

Prometheus & JSON logs

Request counts and latency histograms by matched route, plus per-namespace gauges for memories, index size, entities and WAL depth — read live at scrape time, so they can't drift. One JSON line per request for your log shipper.

deploy

One image, both arches

Official multi-arch image for amd64 and arm64, 36 MB, non-root, /data as a volume. Liveness is an unauthenticated /healthz, so probes never need to hold a credential.

# one admin key, one tenant key pinned to its own namespaces
docker run -p 7700:7700 -v memrust-data:/data aianytime/memrust:0.6.1 \
  serve --addr 0.0.0.0:7700 --data-dir /data --log-format json \
  --api-key "$ADMIN_KEY" \
  --api-key "$ACME_KEY:acme,acme-staging"

# every request picks its tenant; the key decides if that's allowed
curl localhost:7700/v1/recall \
  -H "Authorization: Bearer $ACME_KEY" \
  -H "X-Memrust-Namespace: acme" \
  -d '{"query":"what did we decide about pricing?"}'

Upgrading from a single-tenant deployment is safe: a data directory written before namespaces existed is adopted as default in place, and new namespaces are created alongside it.

Hosted · private beta

Don't want to run it? Don't.

Taking design partners now

Self-hosting stays free and uncapped forever — that is the whole point of an Apache-2.0 engine. memrust Cloud is for teams who would rather not operate a stateful service: sign up, create a project, get a key, and point every agent at one URL.

projects

Isolated by construction

Every project is its own engine — own indexes, own WAL, own directory. The namespace is pinned by your key, so a request cannot reach another tenant's memory even if it asks to.

keys

Scoped and revocable

Keys are shown once and stored as hashes. Revoking one stops it on the next request. Every account, project and key change lands in an audit log.

mcp

Hosted, not stdio

One HTTPS endpoint instead of a binary on every machine — which is what lets claude.ai and hosted agents share the same memory as your laptop.

usage

Metered, with a console

Requests, recalls and stored memories per project per month, with live index stats and a recall playground that shows the per-signal breakdown.

Free tier: 3 projects · 25,000 requests/month · 10,000 memories. Cloud from $49/month. Self-hosted: unlimited, because you run it.

Where this is going

The engine is open. The hard part is shared memory.

memrust is Apache-2.0 and will stay that way — an engine you can read, fork and run on your own hardware. Isolation and authentication are in the open engine, because you need them to self-host. What you pay for is the part a single node can't solve: fleets of agents sharing memory across machines, with quotas, replication and operations someone else runs. Open core, hosted control plane.

Shipping now

Hybrid retrieval, memory lifecycle, multi-agent visibility, namespaces, scoped API keys, metrics, MCP, dashboard, SDKs, Docker image.

In private beta

Hosted memory: projects, scoped keys, metering, audit, and MCP over HTTP so every agent shares one endpoint.

Next

Backup and restore to object storage, read replicas over WAL streaming, LLM entity extraction, hierarchical summarization.

Straight answers

The questions we actually get.

Is this just Qdrant + Mem0 in one box?

That stack is two systems: the memory semantics live in Python, the storage lives somewhere else, they talk over a network, and an LLM sits in the loop deciding what to keep. memrust implements the memory semantics inside the storage engine.

That's why filters apply during index traversal instead of after it, why it runs with no API keys at all, and why durability is something you can reason about rather than inherit from whatever store you configured underneath.

So is memrust a vector database?

There's one inside it — HNSW, scalar quantization, a write-ahead log, checkpoint recovery. But that index is one of four retrieval signals, and it isn't the API.

A vector database stores an embedding with a metadata blob attached. memrust stores a memory: typed as episodic, semantic, working or procedural; owned by an agent; able to expire; linked to extracted entities; and carrying provenance when it was distilled from older memories.

Do I need an LLM or API keys?

No. The default embedder and summarizer run offline with zero keys — enough to try every feature on this page, including the notebooks.

For production quality, point it at OpenAI, Gemini, or a local sentence-transformers server through Ollama, TEI, LM Studio or vLLM. Or skip the embedder entirely and pass your own vectors.

Why not just bolt a keyword index onto my vector DB?

You can — and if you do, you'll rebuild what memrust already is: two indexes, rank fusion, a graph for relationships, jobs for expiry and consolidation, per-agent access rules, and a protocol shim so agents can reach it.

The parts that resist bolting on are pre-filtering inside index traversal and per-signal score explanation. Both have to live in the engine; neither can be added by a layer sitting above it.

Can I keep the embedding model I already use?

Yes, and it's the common path. Pass embedding on write and query_embedding on recall, and memrust never calls a model — BGE, E5, OpenAI, Voyage, whatever you already run.

The first vector fixes a collection's dimension. Mixing models afterwards is rejected with a clear error rather than silently returning nonsense similarities.

Is it production-ready?

It's young and single-node, so be deliberate. What's there: API keys scoped to namespaces, isolated stores with their own indexes and directories, Prometheus metrics and JSON request logs, an official multi-arch image, and durability tested under kill -9 with concurrent writers and checkpoints racing — 1,000 acknowledged writes, 1,000 recovered — plus recall@10 of 1.000 against exact ground truth and a suite that runs on every commit.

The hosted control plane is in private beta: projects, scoped keys, metering, audit and MCP over HTTP all work and are covered by an end-to-end suite that specifically tries to break cross-tenant isolation. Billing and email are not wired yet, which is exactly why it is beta and not GA.

What it isn't: distributed, multi-writer, or scarred by years in production. Run it where a single node fits, which covers most agent workloads today.

How does it fit into my agent framework?

Three ways. As an MCP server, which is how Claude Code and Claude Desktop pick it up — the agent gets remember, recall and forget as native tools. Over HTTP with the Python or TypeScript SDK, for LangGraph, CrewAI, the OpenAI SDK or anything else. Or as a Rust library, embedded with no server at all.

What's the license, and how does this make money?

Apache-2.0, permanently. The engine is meant to be read, forked and self-hosted, and nothing on this page is behind a paywall.

The commercial layer is hosted memory — projects, scoped keys, metering, audit and one MCP endpoint every agent shares — for teams who would rather not operate a stateful service. Free tier is 3 projects and 25,000 requests a month; Cloud starts at $49. Self-hosting stays unlimited, because you are the one running it.

Do all my agents really share one memory?

Yes, and that is the point. Claude Code, Claude Desktop, claude.ai, Cursor, Windsurf and Codex all speak MCP, so they take the same URL and key. LangGraph, CrewAI and anything else take the HTTP API or an SDK. They read and write one project, so a fact Cursor learns is one your LangGraph agent can recall a week later.

Where agents should not see each other, they don't: a memory owned by an agent is private unless it is published, and that rule is applied inside the index traversal rather than as a filter over results — so it cannot leak through ranking either.

Why Rust?

Because this is a storage engine. Cache-friendly layouts, SIMD-friendly distance kernels, and predictable latency with no garbage collector pausing in the middle of a recall.

It's also why the whole thing ships as one static binary with no runtime to install — the same reason Qdrant is written in Rust.