anima
Long-term, structured memory for AI agents. Extract facts from conversations, deduplicate and supersede them over time, search with hybrid semantic + BM25 retrieval, maintain user profiles, and expose everything over a clean Python library or MCP server.
Features
- Fact extraction — LLM-backed extraction from conversation turns (OpenRouter by default)
- Deduplication — embedding similarity + slot rules + LLM review; supersede outdated facts
- Temporal validity — facts are superseded, not deleted, so you can answer “what did we know before?”
- Production embeddings — local
sentence-transformersor OpenAI by default (not random vectors) - Hybrid search — FAISS semantic recall + BM25 rerank, fused with confidence and recency
- Document ingestion — chunk and index Markdown (extensible ingester registry)
- User profiles — incremental O(1) profile updates on every
add()(requires LLM) - Entity graph — optional NetworkX graph of entities and relationships (requires LLM)
- Lifecycle — confidence decay, TTL expiry, signal-based
watch()auto-save - MCP server — six tools for Cursor, Claude Desktop, or any MCP client
- Export / import — JSON backup and restore of memories + profile
Requirements
- Python 3.12+
- uv (recommended for development) or pip
Quickstart
Install
pip install anima-mem
Optional extras:
pip install "anima-mem[dev]" # pytest, pytest-asyncio, python-dotenv
pip install "anima-mem[benchmark]" # LoCoMo benchmark runner deps (see Development)
Python API
import asyncio
from anima import Config, Memory
async def main():
mem = Memory(config=Config.from_env())
await mem.add("User: I moved to Berlin last week.", user_id="alice")
result = mem.search("Where does Alice live?", user_id="alice")
print(result.injected_prompt)
page = mem.list("alice", limit=20)
print(f"{len(page.items)} of {page.total} memories")
asyncio.run(main())
Without OPENROUTER_API_KEY, Memory() still works for storage and search: each message is stored as a single raw fact and embeddings default to local sentence-transformers. LLM extraction, dedup review, profiles, and entity graph population require OPENROUTER_API_KEY.
MCP server
After installing from PyPI:
{
"mcpServers": {
"anima": {
"command": "anima-mcp"
}
}
}
From a local clone (stdio transport):
{
"mcpServers": {
"anima": {
"command": "uv",
"args": ["run", "anima-mcp"],
"cwd": "/path/to/anima"
}
}
}
Tools: memory_add, memory_search, memory_profile, memory_ingest_file, memory_list, memory_delete
User-controlled memory API
| Method | Description |
|---|---|
mem.list(user_id, offset=0, limit=50) |
Paginated memory list |
mem.pin(memory_id) |
Mark permanent (no decay / TTL deletion) |
mem.export(user_id) |
MemoryExport JSON snapshot |
mem.import_memories(data) |
Restore from export |
export_data = mem.export("alice").model_dump(mode="json")
# ... later or on another machine ...
mem.import_memories(export_data)
Configuration
Set environment variables before creating Memory(config=Config.from_env()). The library reads os.environ only — export variables in your shell or use a tool that loads .env (e.g. uv run).
| Variable | Default | Purpose |
|---|---|---|
OPENROUTER_API_KEY |
— | LLM extraction, dedup, profiles, graph |
DATABASE_URL |
sqlite:///./anima.db |
SQLAlchemy URL |
VECTOR_STORE_PATH |
./data/faiss |
FAISS index directory |
GRAPH_STORE_PATH |
./data/graph |
Entity graph JSON |
EMBEDDER |
st (or openai if OPENAI_API_KEY set) |
st or openai |
EMBEDDING_DIM |
1536 (OpenAI) / auto for ST |
Set for OpenAI; ST uses model dim |
ST_MODEL |
all-MiniLM-L6-v2 |
Local embedding model |
DECAY_RATE_PER_WEEK |
0.05 |
Confidence decay rate |
WATCH_KEYWORDS |
remember,... |
watch() trigger phrases |
Memory(config=Config.from_env()) picks a production embedder automatically. Override explicitly if needed:
from anima import Memory, Config, build_embedder
embed_fn, dim = build_embedder()
cfg = Config.from_env()
cfg.embedding_dim = dim
mem = Memory(config=cfg, embed_fn=embed_fn)
Development
Clone the repository (required for tests, benchmarks, and lint):
git clone https://github.com/themillenniumfalcon/anima.git
cd anima
cp .env.example .env # OPENROUTER_API_KEY — extraction, dedup, profile, graph
uv sync --extra dev # or: pip install -e ".[dev]"
uv run pytest -v
uv run ruff check src tests
Benchmarks
LoCoMo evaluation requires a repo checkout (the runner is not shipped on PyPI):
uv sync --extra benchmark # or: pip install -e ".[benchmark]"
uv run python benchmarks/run_locomo.py
Methodology: benchmarks/README.md
License
MIT — see LICENSE.
Metadata
Release files for anima-mem 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| anima_mem-0.1.1.tar.gz | 59.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| anima_mem-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 133.1 kB
Release files / anima_mem-0.1.1.tar.gz
| Download URL | anima_mem-0.1.1.tar.gz |
|---|---|
| Size | 59.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
16e7095e499eb4f217fc0b9c6355db274c68ad37d0c84b68e595bae30ef9e7dd
|
|
BLAKE2b-256 checksum How to use checksums |
4ea37b3661bff9971475c4344496ef232989e952eb386f0823732482bf9c20c6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.6.0
|
Release files / anima_mem-0.1.1-py3-none-any.whl
| Download URL | anima_mem-0.1.1-py3-none-any.whl |
|---|---|
| Size | 73.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
73b32ed16f394282bd06c48067d71f16228c141bed9ec2f83c5b23d0f99145e3
|
|
BLAKE2b-256 checksum How to use checksums |
1a7e1f4f846a037a1643ffe07a45f2a590a4916555359ebac8688ce7da4f599d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.6.0
|
Security for anima-mem 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.