Skip to main content

CI codecov PyPI License

grafeo-memory

AI memory layer powered by GrafeoDB, an embedded graph database with native vector search.

No servers, no Docker, no Neo4j, no Qdrant. One .db file + one LLM.

Typical memory stack: Containers with Neo4j + Qdrant, Embedding API + LLM
grafeo-memory stack:  grafeo (single file) + LLM

Install

uv add grafeo-memory                   # base (bring your own LLM + embedder)
uv add grafeo-memory[mistral]          # + Mistral embeddings
uv add grafeo-memory[openai]           # + OpenAI embeddings
uv add grafeo-memory[anthropic]        # + Anthropic embeddings
uv add grafeo-memory[mcp]             # + MCP server for AI agents
uv add grafeo-memory[all]              # all providers

Or with pip:

pip install grafeo-memory[openai]

Quick Start

OpenAI

from openai import OpenAI
from grafeo_memory import MemoryManager, MemoryConfig, OpenAIEmbedder

embedder = OpenAIEmbedder(OpenAI())
config = MemoryConfig(db_path="./memory.db", user_id="alice")

with MemoryManager("openai:gpt-4o-mini", config, embedder=embedder) as memory:
    # Add memories from conversation
    events = memory.add("I just started a new job at Acme Corp as a data scientist")
    # -> [ADD "alice works at acme_corp", ADD "alice is a data_scientist"]

    events = memory.add("I've been promoted to senior data scientist at Acme")
    # -> [UPDATE "alice is a senior data scientist at acme_corp"]

    events = memory.add("I left Acme and joined Beta Inc")
    # -> [DELETE "alice works at acme_corp", ADD "alice works at beta_inc"]

    # Search
    results = memory.search("Where does Alice work?")
    # -> [SearchResult(text="alice works at beta_inc", score=0.92, ...)]

Mistral

from mistralai import Mistral
from grafeo_memory import MemoryManager, MemoryConfig, MistralEmbedder

embedder = MistralEmbedder(Mistral())
config = MemoryConfig(db_path="./memory.db", user_id="alice")

with MemoryManager("mistral:mistral-small-latest", config, embedder=embedder) as memory:
    events = memory.add("I just started a new job at Acme Corp as a data scientist")
    results = memory.search("Where does Alice work?")

How It Works

grafeo-memory implements the reconciliation loop, the intelligence layer that decides what to remember:

  1. Extract facts from conversation text (LLM call)
  2. Extract entities and relationships (LLM tool call)
  3. Search existing memory for related facts (vector + graph)
  4. Reconcile new facts against existing memory (LLM decides ADD/UPDATE/DELETE/NONE)
  5. Execute the decisions against GrafeoDB
┌──────────────────────────────────────────┐
│             grafeo-memory                │
│                                          │
│  Extractor -> Reconciler -> Executor     │
│  (LLM)       (LLM)        (GrafeoDB)     │
└──────────────────┬───────────────────────┘
                   │
         ┌─────────┴──────────┐
         │      GrafeoDB      │
         │  Graph + Vector    │
         │  + Text (optional) │
         │  single .db file   │
         └────────────────────┘

Multi-User Isolation

config = MemoryConfig(db_path="./chat_memory.db")

with MemoryManager("openai:gpt-4o-mini", config, embedder=embedder) as memory:
    # Each user's memories are isolated
    memory.add("I love hiking in the mountains", user_id="bob")
    memory.add("I prefer beach vacations", user_id="carol")

    bob_results = memory.search("vacation preferences", user_id="bob")
    # -> hiking, mountains

    carol_results = memory.search("vacation preferences", user_id="carol")
    # -> beach vacations

Supported LLM Providers

grafeo-memory uses pydantic-ai model strings, so any provider pydantic-ai supports works out of the box:

# OpenAI — use OpenAIEmbedder for embeddings
MemoryManager("openai:gpt-4o-mini", config, embedder=OpenAIEmbedder(OpenAI()))

# Anthropic — pair with OpenAI or custom embedder
MemoryManager("anthropic:claude-sonnet-4-5-20250929", config, embedder=embedder)

# Groq — pair with OpenAI or custom embedder
MemoryManager("groq:llama-3.3-70b-versatile", config, embedder=embedder)

# Mistral — use MistralEmbedder for embeddings
MemoryManager("mistral:mistral-small-latest", config, embedder=MistralEmbedder(Mistral()))

# Google — pair with OpenAI or custom embedder
MemoryManager("google-gla:gemini-2.0-flash", config, embedder=embedder)

Built-in Embedders

Class Provider Default Model Install Extra
OpenAIEmbedder OpenAI text-embedding-3-small [openai]
MistralEmbedder Mistral mistral-embed [mistral]

Both accept an optional model parameter to override the default.

Which model works best?

Provider Combined extraction Individual extraction Notes
OpenAI (gpt-4o-mini) Works Works Recommended default
Anthropic (claude-sonnet) Works Works Untested in CI
Mistral (mistral-small) Falls back Works 3 API calls instead of 1
Groq Unknown Unknown Needs testing
Google Unknown Unknown Needs testing

grafeo-memory tries a single "combined" LLM call first (facts + entities + relations in one schema). If the model cannot handle the combined schema, it falls back to separate calls automatically. Mistral models typically trigger this fallback, which means 3 API calls per add() instead of 1. The fallback is silent (logged at DEBUG level, no traceback printed).

Custom Embeddings

Implement the EmbeddingClient protocol to use any embedding provider:

from grafeo_memory import EmbeddingClient

class MyEmbedder:
    def embed(self, texts: list[str]) -> list[list[float]]:
        # Call your embedding API
        return [...]

    @property
    def dimensions(self) -> int:
        return 1024  # your model's output dimensions

memory = MemoryManager("openai:gpt-4o-mini", config, embedder=MyEmbedder())

MCP Server

grafeo-memory includes a built-in MCP server so AI agents (Claude Desktop, Cursor, etc.) can use it as a tool.

uv add grafeo-memory[mcp]
# or: pip install grafeo-memory[mcp]

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "grafeo-memory": {
      "command": "grafeo-memory-mcp",
      "env": {
        "GRAFEO_MEMORY_MODEL": "openai:gpt-4o-mini",
        "GRAFEO_MEMORY_DB": "./memory.db"
      }
    }
  }
}

Available Tools

Tool Description
memory_add Add a memory by extracting facts from text
memory_add_batch Add multiple memories in one batch
memory_search Search memories by semantic similarity and graph context
memory_update Update an existing memory's text
memory_delete Delete a single memory
memory_delete_all Delete all memories for a user
memory_list List all stored memories
memory_summarize Consolidate old memories into topic-grouped summaries
memory_history Show change history for a memory

Environment Variables

Variable Default Description
GRAFEO_MEMORY_MODEL openai:gpt-4o-mini pydantic-ai model string
GRAFEO_MEMORY_DB (in-memory) Database file path
GRAFEO_MEMORY_USER default Default user ID
GRAFEO_MEMORY_YOLO (off) Set to 1 for all features

Transport

Supports stdio (default), SSE and streamable HTTP:

grafeo-memory-mcp              # stdio (default)
grafeo-memory-mcp sse          # SSE
grafeo-memory-mcp streamable-http

Note: This is different from grafeo-mcp, which exposes the raw GrafeoDB database. grafeo-memory-mcp wraps the high-level memory API (extract, reconcile, search, summarize).

Observability

grafeo-memory supports OpenTelemetry instrumentation via pydantic-ai. When enabled, all LLM calls (extraction, reconciliation, summarization, reranking) are traced automatically.

config = MemoryConfig(instrument=True)  # uses global OTel provider

For custom providers:

from grafeo_memory import InstrumentationSettings

config = MemoryConfig(instrument=InstrumentationSettings(
    tracer_provider=my_tracer_provider,
    include_content=False,
))

Why grafeo-memory?

Traditional stack grafeo-memory
Infrastructure Neo4j + Qdrant (Docker) Single .db file
Install size ~750MB (Docker images) ~16MB (uv add)
Offline/edge Requires servers Yes
Graph + vector Separate services Unified engine
LLM providers Varies pydantic-ai (OpenAI, Anthropic, Mistral, Groq, Google)
Embeddings External API required Protocol-based (any provider)

API Reference

MemoryManager

  • MemoryManager(model, config=None, *, embedder): create memory manager. model is a pydantic-ai model string (e.g. "openai:gpt-4o-mini")
  • .add(messages, user_id=None, session_id=None, metadata=None, *, infer=True, importance=1.0, memory_type="semantic") → AddResult (list of MemoryEvent)
  • .search(query, user_id=None, k=10, *, filters=None, rerank=True, memory_type=None) → SearchResponse (list of SearchResult)
  • .update(memory_id, text) → MemoryEvent: update a memory's text directly
  • .get_all(user_id=None, memory_type=None) → list[SearchResult]
  • .delete(memory_id) → bool
  • .delete_all(user_id=None) → int (count deleted)
  • .summarize(user_id=None, *, preserve_recent=5, batch_size=20) → AddResult
  • .history(memory_id) → list[HistoryEntry]: returns change history sorted by timestamp (oldest first)
  • .set_importance(memory_id, importance) → bool
  • .close(): close the database

Use as a context manager: with MemoryManager(...) as memory:. Multiple sessions in the same process are supported.

MemoryConfig

  • db_path: path to database file (None for in-memory)
  • user_id: default user scope (default "default")
  • session_id: default session scope
  • agent_id: default agent scope
  • reconciliation_threshold: minimum cosine similarity (0.0 to 1.0) for a memory to be considered a reconciliation candidate during add(). Lower values find more candidates, higher values require closer matches. At 0.3 (default), loosely related memories are considered. At 0.7+, only very similar memories trigger UPDATE/DELETE decisions
  • search_min_score: minimum score for search results, 0.0 returns everything (default 0.0)
  • agreement_bonus: score boost when both vector and graph find the same memory (default 0.1)
  • embedding_dimensions: vector dimensions (default 1536)
  • enable_importance: enable composite scoring with recency/frequency/importance (default False)
  • weight_topology: topology score weight for graph-connected memories (default 0.0, requires enable_importance)
  • enable_topology_boost: re-rank search results by graph connectivity, no LLM call (default False)
  • topology_boost_factor: strength of topology boost (default 0.2)
  • consolidation_protect_threshold: protect well-connected memories from summarize (default 0.0, off)
  • instrument: OpenTelemetry instrumentation, True or InstrumentationSettings (default False)

EmbeddingClient (Protocol)

  • .embed(texts: list[str]) -> list[list[float]]: generate embeddings for a batch of texts
  • .dimensions -> int: return the embedding vector dimensionality

Return Types

  • AddResult: list subclass of MemoryEvent, with .usage for LLM token counts
  • SearchResponse: list subclass of SearchResult, with .usage for LLM token counts
  • MemoryEvent: .action (ADD/UPDATE/DELETE/NONE), .memory_id, .text, .old_text
  • SearchResult: .memory_id, .text, .score, .user_id, .metadata, .relations, .memory_type
  • HistoryEntry: .event (ADD/UPDATE/DELETE), .old_text, .new_text, .timestamp (epoch ms), .actor_id, .role. Returned sorted by timestamp ascending (oldest first)

Iteration

# AddResult is iterable:
for event in memory.add("text"):
    print(event.action, event.text)

# SearchResponse is iterable:
for result in memory.search("query"):
    print(result.text, result.score)

Ecosystem

grafeo-memory is part of the GrafeoDB ecosystem:

  • grafeo: Core graph database engine (Rust)
  • grafeo-langchain: LangChain integration
  • grafeo-llamaindex: LlamaIndex integration
  • grafeo-mcp: MCP server for raw GrafeoDB access
  • grafeo-memory-mcp (built-in): MCP server for the memory API (uv add grafeo-memory[mcp] or pip install grafeo-memory[mcp])

All packages share the same .db file. Build memories with grafeo-memory, query them with grafeo-langchain, expose them via MCP.

Requirements

  • Python 3.12+

License

Apache-2.0

Metadata

Release files for grafeo-memory 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for grafeo-memory 0.2.2
File Size Uploaded
grafeo_memory-0.2.2.tar.gz 224.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for grafeo-memory 0.2.2
File Interpreter ABI Platform
grafeo_memory-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 302.8 kB

Release files / grafeo_memory-0.2.2.tar.gz

Download URL grafeo_memory-0.2.2.tar.gz
Size 224.6 kB
Tags Source
SHA-256 checksum
How to use checksums
5b56442af7f186d76403832d37b8371c116f96c42e75f9d6b14f538542035bbf
BLAKE2b-256 checksum
How to use checksums
42a7ae0ff4ee90455b1936b0565c5cf78abfd20f4e398ec8255e5c1640f69fc3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 8, 2026.

Transparency log

Release files / grafeo_memory-0.2.2-py3-none-any.whl

Download URL grafeo_memory-0.2.2-py3-none-any.whl
Size 78.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
92a1b4e4e4be4f20d9ba93a1d0d6da9dec51af69ba0eb6aa7b3037f4fa02bd53
BLAKE2b-256 checksum
How to use checksums
37430502be31bc702bb0482a85090794c2a94e260f50171a2aa5637ff52085ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page