Give your agent memory and knowledge. One file, three lines, no server, no API key.
git clone https://github.com/SRock44/rmbr && cp rmbr/*.md ~/.claude/agents/Subagents overview
# rmbr
<!-- mcp-name: io.github.SRock44/rmbr -->
> **Give your agent memory and knowledge. One file, three lines, no server, no API key.**
`rmbr` ("remember", vowels deleted) is an embedded, local-first **memory + retrieval engine for AI agents and LLM apps** — what SQLite is to Postgres, rmbr aims to be to hosted memory services.
> **v0.1.1.** `pip install rmbr` gets you a working library: `Memory`, `Index`, `Policy`, and MCP support (below), all implemented and tested — see [docs/PLAN.md](docs/PLAN.md) and [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the design.
## Why
Agents can already "remember" things across restarts — a `CLAUDE.md`, a system prompt, a JSON file on disk. That's not new, and rmbr isn't claiming otherwise.
What breaks is what happens as that file grows. Every fact in a static context file costs tokens on *every single call*, whether it's relevant to the current task or not — so it either stays small (a few dozen hand-curated notes) or turns into noise nobody's cheaply reading anymore. There's no ranking: the agent gets the whole file, or nothing, never just the 5 facts that actually matter for this turn. A static file gets more expensive and less useful the more the agent learns; a searchable memory gets more useful and stays the same cost per call. `mem.recall(query)` returns the *k* most relevant memories out of however many thousand you've accumulated — that's the actual gap between "an agent that can write to a file" and "an agent with memory."
The other place people get burned: rolling this yourself. Chunk text, embed it, throw it in a vector store — that's a legitimately easy weekend project (this one started that way too). What's easy to get wrong in that weekend project: real hybrid search (most ship vector-only or keyword-only and never notice), an embedding cache (so you're not re-embedding — and re-paying for — the same text on every call), and, if there's more than one agent involved, *safe* isolation between them. Most hand-rolled or framework-provided multi-agent memory either shares one blob every agent can read and write, or scopes access via a `namespace`/`user_id` parameter the *calling model itself* supplies — which a prompt injection can simply ask to change. rmbr's MCP tools don't expose that parameter at all; there's no field for an injected instruction to fill in.
So: rmbr exists for the gap between "stuff it in a system prompt" (doesn't scale past a few KB) and "stand up real infrastructure" (Docker, a graph database, a hosted API key) — search-quality, safely-isolated memory, as a dependency, not a service.
Concretely, rmbr gives you:
- **One file.** Your agent's entire memory and knowledge base is a single `.db` file — `git commit` it, diff it, roll it back, hand it to a teammate, attach it to a bug report, or check a known-good state into a test fixture for deterministic CI. No hosted memory service lets you do any of that.
- **Three lines.** `pip install rmbr`, import, remember. No account, no config, no service.
- **No added infrastructure.** Your agent already needs a network connection and an API key for its LLM calls — rmbr doesn't add a *second* one just for memory. mem0 defaults to a hosted LLM+embedding API, Zep needs Docker+Neo4j+an LLM key, Letta needs a server+Postgres — all on top of whatever you're already paying for the model itself. rmbr's own memory/retrieval path makes zero network calls by default: one less vendor, one less key to leak, one less service whose outage takes your agent's memory down with it. (It also means rmbr keeps working with a fully local LLM — Ollama, llama.cpp — for genuinely offline or air-gapped use; most people won't need that, but it's there.)
- **No proprietary format.** rmbr never calls an LLM itself — `recall()`/`search()` return plain strings, floats, and dicts (`hit.text`, `hit.score`, `hit.metadata`). Nothing to parse, no vendor SDK required to consume it — see [Using results with an LLM](#using-results-with-an-llm) below for how that plugs into Claude, GPT, or Gemini identically.
- **Namespace-pinned multi-agent access.** `Policy` is deny-by-default; MCP tools expose no namespace parameter to override — safe by construction, not by convention.
## Quickstart
```python
from rmbr import Memory
mem = Memory("agents.db", namespace="assistant")
mem.remember("user prefers dark mode and short answers")
mem.recall("user preferences")
```
Three lines — that's the whole API for the common case. Everything below is opt-in and lives in its own section, so you only read what you actually need. Library-only by design — no CLI to learn. (`python -m rmbr` exists solely so MCP clients can launch the server; see [MCP support](#mcp-support) below.)
### Indexing documents (RAG)
```python
from rmbr import Index
idx = Index("agents.db")
idx.add_files("docs/") # .py, .md, and plain text each get an appropriate splitter automatically
hits = idx.search("how do I deploy?", k=5)
hits[0].text, hits[0].score, hits.timings # per-stage latency, always visible
```
`Index` and `Memory` share the same `.db` file — open both against the same path if your agent needs a knowledge base *and* a memory. `add_files()`/`add_texts()` return an `IngestResult`: a plain list of document ids with a `.timings` breakdown attached (`chunk_ms`/`embed_ms`/`store_ms`/`ann_ms`/`docs_per_second`) — the same transparency `hits.timings` gives you for search, applied to ingestion, so you can see for yourself that embedding dominates the cost rather than take our word for it.
### Using results with an LLM
rmbr never calls a model — `search()`/`recall()` hand you back plain text and a score, and you decide what to do with it. The standard pattern (classic RAG: retrieve, then inject the retrieved text into the prompt) with Claude:
```python
from anthropic import Anthropic
from rmbr import Index
idx = Index("agents.db")
idx.add_files("docs/")
client = Anthropic() # reads ANTHROPIC_API_KEY from the environment
def answer(question: str) -> str:
hits = idx.search(question, k=5)
context = "\n\n".join(f"<document>{hit.text}</document>" for hit in hits)
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
# Context before the question, not after — Anthropic's own prompting
# docs measure this ordering as meaningfully better for long-context
# RAG, though it isn't required for correctness.
messages=[{"role": "user", "content": f"{context}\n\nUsing the documents above, answer: {question}"}],
)
return response.content[0].text
answer("how do I deploy?")
```
This isn't Claude-specific. `hit.text` is a plain Python string with no wrapper, no provider object, nothing rmbr-proprietary — the exact same `context` string above drops verbatim into OpenAI's `messages` array (`client.chat.completions.create(model=..., messages=[...])`) or Gemini's `contents`. Every mainstream chat-completion API takes the same fundamental shape (a list of role-tagged text messages), which is why "retrieve text, put it in the prompt" — the only integration contract rmbr makes — works identically across providers. Swap the SDK call, nothing else changes.
Want the embedding itself to come from OpenAI instead of the local default? `Memory("agents.db", namespace="assistant", embedder=OpenAIEmbedder())` (`pip install rmbr[openai]`) — same `Embedder` protocol, same rest of the API.
### Restricting access between agents
```python
from rmbr import Memory, Policy
policy = Policy()
policy.allow("supervisor", read="*") # supervisor can read every namespace
mem = Memory("agents.db", namespace="coder", policy=policy)
```
Deny-by-default: `coder` can only read/write its own namespace unless explicitly granted. See [Multi-agent isolation](#multi-agent-isolation-honestly-stated) below for the full model, the security reasoning, and a diagram of a real team topology.
### Async, for web backends and concurrent agents
Every read and write has an `a`-prefixed async twin — `aremember`/`arecall`/`aforget` on `Memory`, `aadd_text`/`aadd_texts`/`aadd_files`/`asearch` on `Index` — for `async def` route handlers (FastAPI, Starlette, aiohttp) where a blocking call stalls every other request on the same event loop:
```python
from fastapi import FastAPI
from rmbr import Memory
app = FastAPI()
mem = Memory("agents.db", namespace="assistant")
@app.post("/chat")
async def chat(message: str):
context = await mem.arecall(message, k=5)
await mem.aremember(f"user said: {message}")
return {"context": [hit.text for hit in context]}
```
Or fan a supervisor out across several granted namespaces concurrently instead of one at a time:
```python
import asyncio
coder_notes, researcher_notes = await asyncio.gather(
supervisor.arecall("release blockers", namespaces="coder"),
supervisor.arecall("release blockers", namespaces="researcher"),
)
```
One honestly-stated limitation: async calls on the *same* `Memory`/`Index` instance are serialized behind an internal lock, reads included. That's deliberate — the vector index (`usearch`) isn't documented as safe for concurrent mutation from multiple threads, and a corrupted index is a far worse failure than giving up some read concurrency. Open separate instances against the same file for true parallelism; SQLite's WAL mode supports that fine.
### Serving memory over MCP
```python
from rmbr import serve_mcp
serve_mcp("agents.db", namespace="coder", read_only=True)
```
See [MCP support](#mcp-support) below for what this exposes and how to actually connect a client to it.
### Contributing / running from source
```bash
git clone https://github.com/SRock44/rmbr.git
cd rmbr
python -m venv .venv && source .venv/bin/activate # .venv\Scripts\activate on Windows
pip install --only-binary :all: -e .
pytest tests/ # 129 tests, no network or API key required
```
The default embedder (`fastembed`, a local ONNX model) downloads its model wWhat people ask about rmbr
What is SRock44/rmbr?
+
SRock44/rmbr is subagents for the Claude AI ecosystem. Give your agent memory and knowledge. One file, three lines, no server, no API key. It has 1 GitHub stars and was last updated today.
How do I install rmbr?
+
You can install rmbr by cloning the repository (https://github.com/SRock44/rmbr) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.
Is SRock44/rmbr safe to use?
+
SRock44/rmbr has not been audited yet by our security agent. Review the original repository on GitHub before using it in production.
Who maintains SRock44/rmbr?
+
SRock44/rmbr is maintained by SRock44. The last recorded GitHub activity is from today, with 1 open issues.
Are there alternatives to rmbr?
+
Yes. On ClaudeWave you can browse similar subagents at /categories/agents, sorted by popularity or recent activity.
Deploy rmbr to your cloud
Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.
Maintain this repo? Add a badge to your README
Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.
More Subagents
The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.
The agent that grows with you
Java 面试 & 后端通用面试指南,覆盖计算机基础、数据库、分布式、高并发、系统设计与 AI 应用开发
Build Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.
The agent engineering platform.
Turn any codebase, with its docs, SQL schemas, configs, and PDFs, into a queryable knowledge graph. A /graphify skill for Claude Code, Cursor, Codex, and Gemini CLI: local deterministic AST parsing, every edge explained, no vector store.