Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content
Framework integrations

LangChain Integration

Drop-in BaseMemory for any LangChain chain. Cross-session memory works automatically through MuBit's semantic retrieval.

mubit-langchain provides MubitChatMemory, a BaseMemory subclass that any LangChain chain accepts. It auto-loads context before each call and saves the interaction after; cross-session retrieval works through MuBit's semantic recall, not LangChain's local buffer.

pip install mubit-langchain[langchain]

Minimal usage

langchain_minimal.py
from mubit_langchain import MubitChatMemory
from langchain_openai import ChatOpenAI
 
memory = MubitChatMemory(api_key="mbt_...", session_id="chat-1")
llm = ChatOpenAI(model="gpt-4o-mini")
 
# Manual loop — useful for understanding the contract
context = memory.load_memory_variables({"input": "What happened yesterday?"})
# build messages with context["history"], call LLM
memory.save_context({"input": question}, {"output": response})

Full example: Research assistant with cross-session memory

A multi-turn research conversation across two sessions. Session 2 retrieves relevant facts from Session 1.

research_assistant/main.py
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage
from mubit_langchain import MubitChatMemory
 
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.3)
 
# Session 1: learn about a topic
memory_s1 = MubitChatMemory(
    api_key="mbt_...",
    session_id="research-s1",
    agent_id="research-assistant",
)
 
for question in [
    "What caused the 2008 financial crisis?",
    "How did subprime mortgages contribute?",
]:
    context = memory_s1.load_memory_variables({"input": question})
    messages = [SystemMessage(content="You are a research assistant.")]
    if context.get("history"):
        messages.extend(context["history"])
    messages.append(HumanMessage(content=question))
    response = llm.invoke(messages)
    memory_s1.save_context({"input": question}, {"output": response.content})
 
# Session 2: new session, cross-session memory works automatically
memory_s2 = MubitChatMemory(
    api_key="mbt_...",
    session_id="research-s2",
    agent_id="research-assistant",
)
 
context = memory_s2.load_memory_variables({"input": "What about crisis prevention?"})
# Session 2's context now includes relevant facts from Session 1.

Extended LangChain components

MubitChatMemory implements only the BaseMemory contract (load_memory_variables / save_context). The MuBit control surface (reflect, record_outcome, surface_strategies, handoffs, and so on) lives on the SDK Client, not on the memory object — call those through Client directly when you need them.

For LangChain-native wiring, mubit-langchain ships two additional components:

ℹ️Note

Both components hold their own MuBit connection — pass api_key and session_id directly. They do not read state from a MubitChatMemory instance.

MubitLessonRetriever — a LangChain BaseRetriever that surfaces validated strategies as retrievable documents. It wraps the SDK's surface_strategies call and returns each strategy as a Document from get_relevant_documents, so you can drop it into any retrieval chain:

from mubit_langchain import MubitLessonRetriever
 
retriever = MubitLessonRetriever(api_key="mbt_...", session_id="chat-1")
docs = retriever.get_relevant_documents("How should I structure the migration?")
# docs -> [Document(page_content=<strategy>, metadata={...}), ...]

MubitCallbackHandler — a LangChain callback handler that records the outcome of each chain run back into MuBit. Add it to a chain's callbacks list; on completion it calls record_outcome with success_signal (default 0.8) and on error with failure_signal (default -0.8), so reflection learns from real runs:

from mubit_langchain import MubitCallbackHandler
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
 
handler = MubitCallbackHandler(
    api_key="mbt_...",
    session_id="chat-1",
    success_signal=0.8,
    failure_signal=-0.8,
)
 
# Attach the handler to a chain — it records the outcome on on_chain_end /
# on_chain_error. A bare llm.invoke() only emits on_llm_* events, which this
# handler does not observe, so the outcome would never be recorded.
chain = ChatPromptTemplate.from_template("Summarize: {input}") | ChatOpenAI(model="gpt-4o-mini")
response = chain.invoke({"input": "the migration plan"}, config={"callbacks": [handler]})

Gotchas

  • memory_key defaults to "history". If your chain expects a different key, pass MubitChatMemory(memory_key="chat_history", ...).
  • return_messages=True is the default — context["history"] is a list of BaseMessage objects, not a single string.
  • Session vs. user memory: for cross-session recall keyed by user, pass user_id="…" to MubitChatMemory and store with intent="lesson", lesson_scope="global". See SDK helpers → cross-session recall.
  • load_memory_variables() makes a network call. Don't call it inside tight loops.

Version compatibility

mubit-langchainmubit-sdklangchain
0.5.x>= 0.6.0>= 0.3.0