Skip to main content

Long-term structured memory for AI agents — facts, hybrid search, profiles, and MCP.

Project description

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-transformers or 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

anima_mem-0.1.1.tar.gz (59.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

anima_mem-0.1.1-py3-none-any.whl (73.8 kB view details)

Uploaded Python 3

File details

Details for the file anima_mem-0.1.1.tar.gz.

File metadata

  • Download URL: anima_mem-0.1.1.tar.gz
  • Upload date:
  • Size: 59.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.0

File hashes

Hashes for anima_mem-0.1.1.tar.gz
Algorithm Hash digest
SHA256 16e7095e499eb4f217fc0b9c6355db274c68ad37d0c84b68e595bae30ef9e7dd
MD5 4c7bc969b95edc8be2aaba6213779213
BLAKE2b-256 4ea37b3661bff9971475c4344496ef232989e952eb386f0823732482bf9c20c6

See more details on using hashes here.

File details

Details for the file anima_mem-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: anima_mem-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 73.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.0

File hashes

Hashes for anima_mem-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 73b32ed16f394282bd06c48067d71f16228c141bed9ec2f83c5b23d0f99145e3
MD5 72576da4bb0daea7d3bde56e6e9af195
BLAKE2b-256 1a7e1f4f846a037a1643ffe07a45f2a590a4916555359ebac8688ce7da4f599d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page