We have gotten surprisingly good at building AI agents that can reason, call tools, browse the web, write code, and interact with users.
But there is still a basic problem:
Most AI agents forget.
A conversation ends, the context window resets, and the agent starts over.
You can build your own memory system, but then you quickly end up maintaining embeddings, vector search, metadata filters, storage, cleanup policies, APIs, authentication, rate limiting, and an SDK.
I wanted the memory part to feel more like a normal infrastructure primitive.
So I built MouseBase.
GitHub: https://github.com/Lumine8/MouseBase-AI/
Website: https://mousebase.dev
What is MouseBase?
MouseBase is persistent memory infrastructure for AI applications and agents.
The basic idea is simple:
Your AI application
|
v
MouseBase
|
+--> Store memories
|
+--> Search memories
|
+--> Manage memory lifecycle
|
+--> Retrieve relevant context
|
v
PostgreSQL + pgvector
Instead of trying to cram an entire conversation history into every prompt, your application can store useful information and retrieve the relevant pieces when needed.
For example:
from mousebase import MouseBase
client = MouseBase(api_key="mb_live_...")
client.remember(
content="The user prefers dark mode in their IDE.",
metadata={
"source": "preferences",
"user_id": "123"
}
)
results = client.search(
"What theme does the user prefer?"
)
for result in results.results:
print(result.content)
The agent does not need to remember everything.
It only needs access to the right memory at the right time.
Why not just use a vector database?
This was one of the questions I kept coming back to while building MouseBase.
You can absolutely store embeddings in a vector database yourself.
But AI memory is not only a vector-search problem.
A real memory system also needs things like:
- memory lifecycle management
- metadata
- project isolation
- authentication
- rate limits
- APIs
- SDKs
- expiration
- archival
- recovery
- usage tracking
That means a lot of application code ends up surrounding the vector database.
MouseBase tries to package those pieces together.
The goal is not:
"Here is a database with vectors."
The goal is:
"Here is an API your AI application can use as its memory."
Hybrid search instead of semantic search alone
One of the design decisions I made was not to rely exclusively on embeddings.
MouseBase uses a hybrid ranking approach that combines:
| Signal | Weight |
|---|---|
| Semantic similarity | 60% |
| Keyword matching | 25% |
| Metadata matching | 10% |
| Recency | 5% |
Semantic similarity is useful because the query:
"What UI preferences does this user have?"
should be able to find:
"The user prefers dark mode."
even though the words don't exactly match.
But semantic similarity is not always enough.
Sometimes the exact keyword matters.
Sometimes metadata matters.
And sometimes a recent memory should be preferred over something that happened months ago.
That is why MouseBase combines multiple signals rather than treating vector similarity as the entire retrieval system.
Memories need a lifecycle
Another thing that becomes obvious once you build an actual memory system is that not every memory should live forever.
Some information should remain active.
Some information should be archived.
Some information should eventually disappear.
MouseBase currently provides three lifecycle states:
Active
|
+--> searchable
|
v
Archived
|
+--> preserved but excluded from normal search
|
v
Deleted
|
+--> soft deleted / hidden from normal queries
You can also attach an expiration time to a memory.
For example:
from datetime import datetime, timedelta, timezone
client.remember(
content="Temporary onboarding note",
expires_at=(
datetime.now(timezone.utc) +
timedelta(days=30)
).isoformat()
)
This is useful for information that should not become permanent user memory.
Projects keep memory isolated
Applications usually have more than one memory space.
You might have:
Project: Customer Support Agent
Project: Personal Assistant
Project: Internal Research Agent
MouseBase scopes memories to projects so different applications can maintain separate memory stores and API keys.
That makes the model much closer to how developers actually build software.
It is not tied to one LLM
Another design goal was to avoid making memory synonymous with a particular model provider.
Your application can use OpenAI, Gemini, Anthropic, open-source models, or something else.
MouseBase sits underneath the application:
+----------------+
| Your Agent |
+-------+--------+
|
v
+---------------+
| MouseBase |
+-------+-------+
|
+---------+---------+
| |
v v
Vector Search Metadata/Search
|
v
PostgreSQL
+ pgvector
The memory layer does not need to know which LLM generated the response.
It simply stores and retrieves useful information.
Developer experience matters
Infrastructure is only useful if developers can actually integrate it.
MouseBase currently provides SDKs for Python and JavaScript/TypeScript.
Python:
pip install mousebase
JavaScript:
npm install mousebase
Python:
from mousebase import MouseBase
client = MouseBase()
memory = client.remember(
"Alice prefers concise answers."
)
results = client.search(
"How should I respond to Alice?"
)
TypeScript:
import { MouseBase } from "mousebase";
const client = new MouseBase({
apiKey: process.env.MOUSEBASE_API_KEY!
});
await client.remember({
content: "Alice prefers concise answers"
});
const results = await client.search({
query: "How should I respond to Alice?"
});
There is also an async Python client for applications built around asyncio and frameworks such as FastAPI.
Framework integrations
The next level is making memory feel native to the ecosystem developers already use.
MouseBase includes integrations/adapters for tools such as:
- LangChain
- LlamaIndex
- OpenAI Agents
- MCP
- Next.js
- Express
- NestJS
- Cloudflare
The long-term idea is that adding persistent memory should be closer to adding a dependency than building an entire memory subsystem.
A simple agent architecture
A basic AI agent with MouseBase can look like this:
from mousebase import MouseBase
memory = MouseBase()
def agent(user_id, message):
# Save the interaction
memory.remember(
content=message,
external_id=user_id,
metadata={
"role": "user",
"user_id": user_id
}
)
# Retrieve relevant memories
results = memory.search(
message,
top_k=5
)
context = [
result.content
for result in results.results
]
# Pass `context` to your LLM
return context
The important part is not the final LLM call.
It is the loop:
Observe
↓
Remember
↓
Retrieve
↓
Reason
↓
Act
↓
Remember
That loop starts to make an agent feel less like a stateless chatbot and more like a persistent software system.
Production concerns
Building a demo is easy.
Building infrastructure means caring about the less exciting parts too.
MouseBase includes production-oriented components such as:
- JWT authentication
- refresh-token rotation
- API key authentication
- API key hashing and encryption
- key rotation
- rate limiting
- project-level isolation
- memory limits
- request IDs
- structured logging
- Sentry integration
- webhook processing
For example, API keys follow a format similar to:
mb_live_<key_id>_<secret>
and sensitive credentials are not stored as plaintext.
There are also plan-level limits so memory and request usage can be controlled.
Self-hosting
MouseBase is also designed to be self-hostable.
The backend uses PostgreSQL with the pgvector extension and supports embedding providers such as Gemini and OpenAI.
A basic setup looks like:
git clone https://github.com/Lumine8/MouseBase-AI.git
cd MouseBase-AI/backend
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
alembic upgrade head
uvicorn app.main:app --reload
You can then run the frontend separately.
This is important to me because memory is often one of the most sensitive parts of an AI application.
Some teams will prefer a hosted service.
Others will want the entire memory stack inside their own infrastructure.
Both should be possible.
What I am trying to build
I don't think AI memory should remain an implementation detail that every developer rebuilds independently.
Right now, a lot of AI applications have architectures that look roughly like:
LLM
+
Prompt
+
Tools
+
RAG
+
Custom database
+
Custom embeddings
+
Custom memory code
+
Custom cleanup logic
+
Custom retrieval logic
I think memory deserves to become its own infrastructure layer.
Something developers can call as easily as:
memory.remember(...)
memory.search(...)
without having to rebuild the entire system underneath it.
The bigger idea
AI agents are becoming increasingly capable.
But capability without continuity has an interesting limitation.
An agent can reason extremely well in the current moment and still know almost nothing about what happened yesterday.
Persistent memory changes that.
It allows an application to accumulate useful context over time:
Day 1
User preference learned
↓
Day 7
Preference retrieved
↓
Day 30
New behavior remembered
↓
Day 100
Agent has accumulated useful context
That is the direction I think agent infrastructure is moving toward.
Not just smarter models.
Systems that can remember.
Try MouseBase
The project is open on GitHub:
https://github.com/Lumine8/MouseBase-AI/
You can also check out the hosted service:
And install the SDK directly:
pip install mousebase
or:
npm install mousebase
I am still building MouseBase, so feedback from developers working on agents, assistants, RAG systems, and long-running AI applications is especially useful.
If persistent memory is something you've had to build yourself, I'd genuinely like to hear what your architecture looks like.
Top comments (0)