Home/Documentation

LangChain

Python SDK Integration

Add persistent MemoAir memory to LangChain agents and chains. Retrieve user or organization context before calling the model, then save the conversation turn after the response.

Install

install.sh
BASH
pip install "memoair[langchain]" langchain-openai

The LangChain dependency is optional, so core MemoAir SDK users do not install it unless they need this integration.

Use MemoAir as a Retriever

`MemoAirRetriever` implements LangChain's standard retriever interface and returns `Document` objects with MemoAir fact metadata.

retriever.py
PYTHON
from langchain_openai import ChatOpenAI
from memoair import MemoAir
from memoair.integrations.langchain import MemoAirRetriever
 
client = MemoAir(api_key="memoair_sk_...")
retriever = MemoAirRetriever(
client=client,
group_ids=["user:alice"],
max_facts=5,
)
 
docs = retriever.invoke("What does Alice prefer for backend work?")
context = "\n".join(doc.page_content for doc in docs)
 
llm = ChatOpenAI(model="gpt-4o")
response = llm.invoke(
[
("system", f"Use this MemoAir context when helpful:\n{context}"),
("user", "Which framework should I use?"),
]
)
print(response.content)

Conversation Memory

`MemoAirMemory` is a lightweight helper for the common retrieve, answer, save loop.

chat_memory.py
PYTHON
from langchain_openai import ChatOpenAI
from memoair import MemoAir
from memoair.integrations.langchain import MemoAirMemory
 
client = MemoAir(api_key="memoair_sk_...")
memory = MemoAirMemory(client=client, group_id="user:alice", max_facts=10)
llm = ChatOpenAI(model="gpt-4o")
 
def chat(message: str) -> str:
context = memory.get_context(message)
response = llm.invoke(
[
("system", f"You are a helpful assistant with memory:\n{context}"),
("user", message),
]
)
memory.save_interaction(
user_message=message,
assistant_message=response.content,
)
return response.content

LangChain-native Chat History

`MemoAirChatMessageHistory` implements LangChain's `BaseChatMessageHistory`, so it drops directly into `RunnableWithMessageHistory` and any LCEL component that consumes a chat history. Active turns are buffered in-memory while every turn is persisted to MemoAir for long-term memory.

chat_message_history.py
PYTHON
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI
from memoair import MemoAir
from memoair.integrations.langchain import MemoAirChatMessageHistory
 
client = MemoAir(api_key="memoair_sk_...")
prompt = ChatPromptTemplate.from_messages(
[
("system", "You are a helpful assistant with persistent MemoAir memory."),
MessagesPlaceholder("history"),
("human", "{input}"),
]
)
chain = prompt | ChatOpenAI(model="gpt-4o")
 
with_history = RunnableWithMessageHistory(
chain,
lambda session_id: MemoAirChatMessageHistory(client=client, group_id=session_id),
input_messages_key="input",
history_messages_key="history",
)
 
with_history.invoke(
{"input": "Use dark mode in all my apps."},
config={"configurable": {"session_id": "user:alice"}},
)

Use `auto_save=False` to buffer turns without persisting (useful for ephemeral previews), and call `history.get_context_messages(query)` to inject a `SystemMessage` of relevant facts into your prompt.

Function-calling Agent Tools

`MemoAirSearchTool` and `MemoAirSaveTool` are LangChain `BaseTool` subclasses that drop straight into `create_agent(tools=[...])`. Use `MemoAirMemory.as_tools()` to get both wrapped against the same client and group.

agent_tools.py
PYTHON
from langchain.agents import create_agent
from memoair import MemoAir
from memoair.integrations.langchain import MemoAirMemory
 
client = MemoAir(api_key="memoair_sk_...")
memory = MemoAirMemory(client=client, group_id="user:alice")
 
agent = create_agent(
model="openai:gpt-4o",
tools=memory.as_tools(), # MemoAirSearchTool + MemoAirSaveTool
system_prompt="Use MemoAir to recall facts and save anything worth remembering.",
)
 
result = agent.invoke({
"messages": [{"role": "user", "content": "Remember I prefer dark mode in all my apps."}]
})
print(result["messages"][-1].content)

Tripartite Graph Retrieval

Use `MemoAirRetriever` for personal memory only. Use `MemoAirTripartiteRetriever` when the prompt should combine personal memory, organization knowledge, and ontology context in a single retrieval call.

tripartite.py
PYTHON
from memoair import MemoAir
from memoair.integrations.langchain import MemoAirTripartiteRetriever
 
client = MemoAir(api_key="memoair_sk_...")
retriever = MemoAirTripartiteRetriever(
client=client,
user_id="user:alice",
org_id="org:acme",
max_results=8,
enable_hipporag=True,
)
 
docs = retriever.invoke("Who owns the Python runtime?")
for doc in docs:
print(doc.metadata["source_graph"], doc.page_content)

Agent Template

The MemoAir SDK ships an opinionated LangChain agent template at sdk/examples/langchain_agent.py. It composes the retriever, chat history, and tripartite search into a single `LangChainMemoryAgent` class with three entry points: a manual `chat()` loop, a `runnable_with_history()` chain, and `retriever()` / `tripartite_retriever()` factories.

agent_template.py
PYTHON
from langchain_agent import LangChainMemoryAgent
 
agent = LangChainMemoryAgent(user_id="user:alice", org_id="org:acme")
 
# Manual loop: retrieves MemoAir context, calls the LLM, persists the turn.
print(agent.chat("What framework should I use for backend services?"))
 
# LCEL chain: standard LangChain RunnableWithMessageHistory wiring.
chain = agent.runnable_with_history()
chain.invoke(
{"input": "And for ML services?"},
config={"configurable": {"session_id": agent.user_id}},
)
 
# Tripartite retriever: personal + org + ontology graph in one call.
docs = agent.tripartite_retriever().invoke("Who owns the Python runtime?")

LangGraph note: MemoAir is intentionally not exposed as a `BaseCheckpointSaver`. Its API is fact-extraction oriented and does not provide the raw key-value state surface that LangGraph checkpointers require. Use `MemoAirChatMessageHistory` for conversation persistence and a separate checkpointer (for example the in-memory or SQLite saver) for graph state.

What You Get

Standard Retriever
Works with LangChain's `invoke`, `ainvoke`, chains, and any component that accepts a retriever.
Native Chat History
`MemoAirChatMessageHistory` is a `BaseChatMessageHistory` implementation that buffers active turns and persists them to MemoAir.
Graph Metadata
Returned documents include fact IDs, group IDs, timestamps, graph source, and related fact IDs.
Async Ready
Pass `async_client=AsyncMemoAir(...)` to use `ainvoke`, `aget_context`, and `asave_interaction`.