Guides / Frameworks
LangChain.js
For chains and agents built with LangChain.js (@langchain/core, version 1). @recall-memory/langchain plugs Recall into the places LangChain already has for memory: a chat message history stored in Recall sessions, a retriever over what Recall remembers about the user, and tools an agent can call. For Python, see LangChain and LangGraph.
What you get
| Export | What it does |
|---|---|
RecallChatMessageHistory | A BaseListChatMessageHistory backed by a Recall session. Human messages are stored as the user's, AI messages as the assistant's, and Recall learns about the user from them. Use it with RunnableWithMessageHistory or on its own. |
RecallRetriever | A BaseRetriever that returns the current facts Recall holds about the user and the messages they wrote that match the query, as documents (facts first). |
recallTools(options) | Three tools: search_memory, ask_memory (a question about the user, answered from memory) and remember_fact (save one fact). Bind them to a model or give them to an agent. |
All three take userId (the person, as a Recall peer) and optionally recall (a client; by default one is made from RECALL_API_KEY). The history also takes the sessionId of the conversation.
Build it
Install the package and the SDK (npm install @recall-memory/langchain @recall-memory/sdk; @langchain/core you already have) and set RECALL_API_KEY. The user is a peer keyed by your own stable user id, and each conversation is a session. Facts from your app's settings can go in directly.
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";
import { RunnableWithMessageHistory } from "@langchain/core/runnables";
import { RecallChatMessageHistory, RecallRetriever, recallTools } from "@recall-memory/langchain";
import { Recall } from "@recall-memory/sdk";
const recall = new Recall({ workspaceId: "my-app" });
// Who the memory is about (your own stable user id) and the conversation it belongs to.
const userId = "user-8412";
const sessionId = "chat-20261013-a91f";
// A fact from your app's settings, stored as given and searchable at once.
await recall.peer(userId).conclusions.create("Is vegetarian.");
The conversation: a message history. RunnableWithMessageHistory loads the history before each call and saves the new messages after it. With RecallChatMessageHistory they live in Recall, so the conversation survives restarts and Recall learns about the user as they talk. System and tool messages are not stored.
// `model` is any LangChain chat model. Each conversation's messages live in a Recall session,
// and Recall learns about the user from them.
const prompt = ChatPromptTemplate.fromMessages([
["system", "You are a helpful assistant.\n{memory}"],
new MessagesPlaceholder("history"),
["human", "{input}"],
]);
const chat = new RunnableWithMessageHistory({
runnable: prompt.pipe(model),
getMessageHistory: (id: string) =>
new RecallChatMessageHistory({ recall, sessionId: id, userId }),
inputMessagesKey: "input",
historyMessagesKey: "history",
});
Long conversations do not have to go into the prompt whole. Give the history a tokens budget and it returns Recall's context instead: a summary of the older turns as a system message, then the most recent messages.
What Recall knows: the retriever. The retriever brings in what Recall learned about the user in every earlier conversation, not just this one. It searches facts and messages rather than asking a question, so it is fast enough for every turn.
// The retriever finds what Recall knows about the user that bears on the message: facts first,
// then things they said. Put it in the prompt.
const retriever = new RecallRetriever({ recall, userId, k: 4 });
const input = "My parents visit on Saturday. Can you plan a dinner for four?";
const memory = (await retriever.invoke(input)).map((d) => `- ${d.pageContent}`).join("\n");
const reply = await chat.invoke({ input, memory }, { configurable: { sessionId } });
Let an agent use memory: the tools. With the tools an agent looks things up when it needs them and saves what the user shares. They are ordinary LangChain tools, so they work with bindTools, createAgent from the langchain package and LangGraph tool nodes.
// Tools let an agent search memory, ask it a question and save a fact on its own. Bind them to
// a model that supports tool calling, or give them to createAgent from the langchain package.
const tools = recallTools({ recall, userId });
const withTools = model.bindTools(tools);
// They are plain tools, so you can also call one yourself.
const [searchMemory] = tools;
const found = await searchMemory.invoke({ query: "diet" });
Settings that matter
| Option | Use |
|---|---|
userId | Your own stable user id, not an email address. Create the history, retriever and tools per request so each reads the right person's memory. |
assistantId (history) | The assistant's peer (default assistant). It is created with observeMe: false: Recall reads its replies as context but learns nothing about it. |
tokens (history) | Return a summary plus the recent messages within this budget instead of the whole conversation. |
k, include (retriever) | Documents of each kind (default 6), and whether to return "facts", "messages" or both. |
reasoningLevel (tools) | The reasoning level for ask_memory. See Reasoning levels and models. |
Cost and speed
Reading the history and the retriever's search are included in the price, and each takes under a second. Saving messages is one request per call. Recall learns from the user's messages in the background, and that is what you pay for. ask_memory is a question, a model call of a few seconds. Prices are on the pricing page and worked examples in Cost and speed.
Privacy and forgetting
Everything the user writes in a conversation with a Recall history is stored and learned from. Tell users in your privacy notice and keep secrets such as passwords and card numbers out of messages. history.clear() deletes the session: its messages and the facts learned from that conversation. To forget a user entirely, delete their peer (recall.peer(userId).delete()) and their sessions; see Privacy, consent and forgetting.
Pitfalls
- One session for everything. The summary then mixes every topic. Start a session per conversation; what Recall learns about the user carries over anyway, and the retriever brings it back.
- Expecting
clear()to keep what was learned. It deletes the conversation and what Recall learned from it. To start afresh but keep the memory, use a new session id. - Expecting a fact to show up at once. Recall learns from messages in the background, usually within about 20 seconds. Facts saved with
remember_factare searchable at once.
Next: Vercel AI SDK · LangChain and LangGraph