langgraph-memory
A long-term memory engine for LangGraph over any BaseStore: LLM fact extraction, consolidation against what is already known, and recall ranked by semantic similarity, recency and importance. A maintained alternative to LangMem (dormant since late 2025), modelled on CrewAI's unified Memory engine and built to pair with the agentstate-reducer on_prune hook and the langgraph-store-* backends.
pip install langgraph-memory
from langgraph_memory import MemoryEngine
from langgraph_store_postgres import PostgresStore
from langgraph_store_core import bedrock_titan_embeddings
store = PostgresStore(url, index={"dims": 1024, "embed": bedrock_titan_embeddings(dimensions=1024), "fields": ["content"]})
engine = MemoryEngine(store, "anthropic:claude-sonnet-5")
engine.remember(messages, namespace=("memories", "kamal")) # extract → dedupe → consolidate → put
for m in engine.recall("what does the user prefer for travel?", namespace=("memories", "kamal"), limit=5):
print(m.score, m.record.content, m.match_reasons)
What it does
| Stage | Behaviour |
|---|---|
| Extract | a chat model with structured output turns text or messages into discrete facts, each with categories and an importance in 0–1. Any model init_chat_model accepts, or a model instance; or pass your own extractor callable. |
| Dedupe | near-identical facts within one batch are collapsed |
| Consolidate | for each fact, store.search(query=fact) finds similar existing memories; above consolidation_threshold (0.85) the model decides insert / update / skip, so memory converges instead of piling up |
| Store | one BaseStore item per memory: {content, categories, importance, created_at, last_accessed, source, private, metadata}; the store embeds content on put |
| Recall | native vector search, oversampled ×3, then re-ranked with CrewAI's formula 0.5·similarity + 0.3·recency_decay + 0.2·importance (half-life 30 days); filters by categories, min_score, source / private; bumps last_accessed |
All weights, the half-life, thresholds and oversampling live in MemoryConfig.
Choosing the model
There is no default model — pass one explicitly. A memory engine that silently spends tokens on every prune would be a bad surprise, and the rest of the toolkit avoids picking a vendor for you. The embedding model is separate: it lives on the store's IndexConfig.
| Form | Example | Notes |
|---|---|---|
| Name string | MemoryEngine(store, "anthropic:claude-sonnet-5") |
resolved by LangChain's init_chat_model; the provider package (langchain-anthropic, langchain-aws, langchain-openai, …) must be installed and configured |
| Model instance | MemoryEngine(store, ChatBedrockConverse(model=..., region_name=...)) |
any LangChain BaseChatModel; control temperature, region, timeouts, share a client |
| Callables, no model | MemoryEngine(store, extractor=fn, consolidator=fn) |
extractor(text) -> list[ExtractedFact], consolidator(fact, similar) -> ConsolidationDecision; how the tests run with zero LLM calls; mix with model for the other step |
The same model serves both LLM steps, extraction and the consolidation decision, and both use with_structured_output, so the model must support tool calling or JSON-schema output (current Anthropic, OpenAI, Bedrock Converse and Gemini chat models all do). The system prompts are overridable: LLMExtractor(model, prompt=...) and LLMConsolidator(model, prompt=...), passed as extractor= / consolidator=, let you steer what counts as worth remembering for your domain without touching the pipeline.
Integrations
from agentstate_reducer import MessageReducer, ReducerConfig, Background
reducer = MessageReducer(config=ReducerConfig(max_messages=20, on_prune=[Background(engine.on_prune)]))
saver = DynamoDBSaver("checkpoints", reducer=reducer) # pruned turns become memories, under memory_namespace
agent = create_react_agent(model, tools=engine.tools()) # search_memory / manage_memory, namespace from config["configurable"]["memory_namespace"]
graph.add_node("recall", engine.recall_node(into="memory", limit=5)) # writes formatted memories into state["memory"] before the model call
engine.forget(namespace, key=... | categories=... | older_than=...) and engine.list(namespace) for housekeeping; aremember / arecall for async graphs.
Embedding
The engine never embeds anything. The store does, on put and on search(query=...), using the IndexConfig it was built with — so one embedder serves writes, consolidation lookups and recall, and each backend uses its native vector engine (DynamoDB SearchVectors, pgvector, Cosmos VectorDistance, Firestore find_nearest). The constructor refuses a store without an IndexConfig, because recall could not rank on it. Dimensions are fixed at index creation on every backend; changing the embedding model means a new table and re-embedding.
Testing
Deterministic and offline: LangGraph's InMemoryStore with langgraph_store_core.testing.FakeEmbeddings, and rule-based extractor/consolidator callables instead of a model. Backend e2e tests run the same suite against langgraph-store-postgres (pgvector) and langgraph-store-dynamodb, plus a real DynamoDBSaver + reducer on_prune flow.
Docs: https://skamalj.github.io/agentstate-reducer/
License
MIT
Metadata
Release files for langgraph-memory 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| langgraph_memory-0.1.0.tar.gz | 14.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| langgraph_memory-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.4 kB
Release files / langgraph_memory-0.1.0.tar.gz
| Download URL | langgraph_memory-0.1.0.tar.gz |
|---|---|
| Size | 14.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8c22190e2b59c6206e6dd11db351b8c4382e0932f13ad98b5c10aa391d7f498c
|
|
BLAKE2b-256 checksum How to use checksums |
11bf0d3bdea2bfdeaa982dd6e98b64baaafd4dfeea0ef28edbe6932e4bfe3eb5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / langgraph_memory-0.1.0-py3-none-any.whl
| Download URL | langgraph_memory-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d69a6ba23f1f0cf3c821b80ca7a605d390419cf9d20f3c02abc83b1dcbeec12f
|
|
BLAKE2b-256 checksum How to use checksums |
d9df0d779060da5a961e2e234ef48e2a2b975060d8262dcf57f40879afb80acc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|