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).

Full list: .env.example

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.0.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.0-py3-none-any.whl (73.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: anima_mem-0.1.0.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.0.tar.gz
Algorithm Hash digest
SHA256 aa8b1feeee76c7bc6d322155790458b8e1305f727eb35f7014a288067695a452
MD5 92d16348cf0c5fe0b4bf38695ff6d9dd
BLAKE2b-256 082a1bd2803b04aadc21d694c17fb9107dce67499c9fe53f5e1f680389cd8d74

See more details on using hashes here.

File details

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

File metadata

  • Download URL: anima_mem-0.1.0-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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b89a2c2e9aa7b841ce4e8cecdd8f959469aa49cb25ff26fb7945b5deb2ba61e4
MD5 d1a00c863c9e0c69d24420f7ea52cfae
BLAKE2b-256 ec364e9cb2b409c1ae23b8bffd29070f5a55790a9c90dd64c18e4a5a593c577f

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