Memori is model-agnostic memory middleware for AI agents. It lets any agent loop retrieve durable memories, expose memory-management tools, and store end-of-session summaries without Memori owning the model call.
Install the library directly from this repository:
pip install git+https://github.com/maty-millien/Memori.gitInstall from a local checkout while developing:
git clone https://github.com/maty-millien/Memori.git
cd Memori
pip install -e .Then import Memori:
from memori import MemoriMemori currently uses OpenRouter for embeddings and session summarization. Create a .env file in your project with the values from .env.example:
OPENROUTER_API_KEY=sk-or-v1-...
MEMORI_LLM_MODEL=moonshotai/kimi-k2.6
MEMORI_REASONING_EFFORT=high
MEMORI_EMBEDDING_MODEL=google/gemini-embedding-2The remaining values in .env.example control retrieval limits, importance weights, and ranking weights.
Memori plugs into an existing agent loop. It does not call your model, manage retries, own streaming, or impose a message format.
from memori import Memori
memori = Memori.from_env(path=".memori")
user_message = "Please remember that I prefer concise Python examples."
context = memori.before_turn(user_message)
response = agent.run(
prompt=context.prompt,
tools=memori.tools(),
)
for call in response.tool_calls:
memori.handle_tool_call(call.name, call.arguments)
memori.after_turn(
user_message=user_message,
assistant_message=response.text,
tool_calls=response.tool_calls,
)
summary = memori.end_session()If your agent does not support tools, you can still use retrieval and session summaries:
context = memori.before_turn(user_message)
response = agent.run(prompt=context.prompt)
memori.after_turn(user_message, response.text)
memori.end_session()- Before a turn, call
before_turn(user_message). Memori retrieves ranked durable memories plus recent and similar past conversation summaries. - During the agent call, use
context.promptdirectly or rendercontext.memories,context.recent_conversations, andcontext.similar_conversationsyourself. - During tool execution, route
memory_upsertandmemory_deletecalls tohandle_tool_call(...). - After a turn, call
after_turn(...)so Memori can track the active session transcript. - When a session ends, call
end_session(). Memori summarizes the session, stores that summary as conversation memory, and clears the session buffer.
Ranking blends semantic similarity, importance category, recency, usage, and a small boost for globally scoped memories.
Memori.from_env(path: str | None = None) -> Memori
Creates a Memori instance using the current .env settings. Pass path=".memori" for a persistent local Chroma store, or omit path for an in-memory store.
before_turn(user_message: str) -> MemoryContext
Retrieves relevant durable memories, recent conversation summaries, and similar conversation summaries. The returned context includes:
context.user_message
context.prompt
context.history_message
context.retrieved
context.memories
context.recent_conversations
context.similar_conversationstools() -> list[MemoryTool]
Returns framework-neutral tool definitions for memory_upsert and memory_delete.
handle_tool_call(name: str, arguments: dict) -> str
Executes a memory tool call:
memori.handle_tool_call(
"memory_upsert",
{
"content": "The user prefers concise Python examples.",
"scope": "global",
"importance": "global_preference",
},
)after_turn(user_message: str, assistant_message: str, tool_calls: list | None = None) -> None
Records a completed turn in the active session transcript. This does not persist a conversation summary yet.
end_session() -> str
Summarizes the active session, stores the summary for future recent/similar conversation retrieval, clears the active transcript, and returns the summary. If no turns were recorded, it returns an empty string.
memories() -> list[Memory]
Returns durable memories. Conversation summaries are used for retrieval but are not included in this list.
reset(memories: list[Memory] | None = None) -> None
Clears stored memories and replaces them with the optional list. This also clears the active session transcript.
The CLI is a development/demo app built on the same public Memori API. It is not installed as a command by the base library package.
make env
make cliCommands:
| Command | What it does |
|---|---|
/new |
Save the current session as a summary and start fresh |
/clear |
Alias for /new |
/reset |
Wipe all stored memories |
/memories |
List every stored memory |
/help |
Show help |
/quit |
Save the current session as a summary and exit |
15 YAML scenarios in tools/bench/scenarios/ cover retrieval injection, memory tool calls, importance reranking, session-end summaries, and multi-session loops.
make benchA timestamped JSON artifact lands in .memori/runs/ (gitignored).
All tooling is driven through the Makefile so caches, paths, and flags stay consistent.
The installable library lives in memori/. Local demo and bench code lives outside the package in tools/, so the base package only exposes the public memory API.
Core library responsibilities are split by purpose:
| Path | Responsibility |
|---|---|
memori/client.py |
Public Memori facade |
memori/models.py |
Shared dataclasses and literal types |
memori/config.py |
Environment-backed settings |
memori/memory_service.py |
Retrieval, writes, reset, and summary recording |
memori/prompting.py |
Prompt and timestamp formatting |
memori/storage/ |
Chroma persistence |
memori/providers/ |
OpenRouter provider/client code |
memori/summarization.py |
Session summary generation |
| Target | Description |
|---|---|
make env |
Create .venv and install the package plus app/dev dependency groups |
make clean |
Remove .venv |
make run |
Alias for make cli |
make cli |
Start the interactive CLI |
make bench |
Run YAML scenarios in tools/bench/scenarios/, writing JSON to .memori/runs/ |
make tidy |
mypy, ruff check --fix, ruff format, and prettier --write |
