Using Recall with LangChain
The Problem
LangChain agents make decisions based on immediate context: the current user input and the conversation history within the session. But what about the user's preferences from last week? Their past successful strategies? Domains they've already mastered? Without a memory layer, the agent re-learns the same lessons repeatedly, wasting LLM calls.
Solution: Add Recall
Recall is a memory layer that stores agent decisions, conversation outcomes, and learned patterns across sessions. Insert it into your LangChain chain: before execution, retrieve relevant past context; after execution, store what was learned. Your agent becomes smarter with every run.
Install
# Python Recall SDK
pip install recall-sdk
# TypeScript Recall SDK (for Node.js agents)
npm install @arc-labs/recall
# or
pnpm add @arc-labs/recallIntegration Steps
Step 1: Initialize Recall
Create a Recall instance for your agent. Recall stores memories of this agent's decisions and outcomes.
from recall_sdk import Recall
# Create a typed memory schema for your agent
memory = Recall(
name="langchain-agent",
metadata={"framework": "langchain", "agent_type": "reasoning"}
)Step 2: Retrieve Context Before Chain Execution
Before calling your LangChain chain, query Recall for relevant memories. Use a retriever that fuses keyword and semantic search.
from langchain_core.runnables import RunnablePassthrough
from langchain_core.prompts import ChatPromptTemplate
# Retrieve context: "What does this user prefer? What strategies worked?"
context_retriever = memory.retriever(
query=user_input,
top_k=5,
filters={"agent_id": agent_id}
)
# Embed retriever in your chain
chain = (
{
"context": context_retriever,
"input": RunnablePassthrough()
}
| ChatPromptTemplate.from_template(
"Given this context:\n{context}\n\nUser: {input}\n\nAssistant:"
)
| llm
)Step 3: Execute the Chain
Call your chain with the user input. The retriever injects learned context automatically.
response = chain.invoke(user_input)Step 4: Store Outcomes in Recall
After the chain completes, store the decision and outcome. Recall indexes this for future retrieval.
# Extract what was learned
decision = response # The LLM's action
outcome = {"success": True, "user_feedback": user_feedback}
# Store as a typed memory
memory.store(
text=f"Decision: {decision}. Outcome: {outcome}",
memory_type="decision",
metadata={
"agent_id": agent_id,
"user_id": user_id,
"strategy": decision,
"success": outcome["success"]
}
)Step 5: Iterate
On the next user message, the retriever finds the stored memory. Your agent applies learned strategies without re-exploring.
Code Comparison
Without Recall: Every Run Starts from Zero
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
llm = ChatOpenAI(model="gpt-4o")
# No memory: agent rediscovers preferences, strategies each run
chain = ChatPromptTemplate.from_template(
"User: {input}\n\nAssistant:"
) | llm
response = chain.invoke({"input": "Help me write a blog post"})
# The LLM has only the conversation history. User preferences
# stated 3 sessions ago are forgotten.With Recall: Learned Context Informs Every Decision
from recall_sdk import Recall
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
# 1. Initialize Recall
memory = Recall(
name="writing-agent",
metadata={"agent_type": "content-creation"}
)
# 2. Retrieve learned context
def get_user_context(user_input, user_id):
memories = memory.retrieve(
query=user_input,
filters={"user_id": user_id},
top_k=5
)
return "\n".join([m.text for m in memories])
llm = ChatOpenAI(model="gpt-4o")
# 3. Build chain with context retrieval
chain = (
{
"context": lambda x: get_user_context(x["input"], x["user_id"]),
"input": RunnablePassthrough()
}
| ChatPromptTemplate.from_template(
"User context and preferences:\n{context}\n\nUser: {input}\n\nAssistant:"
)
| llm
)
# 4. Execute
response = chain.invoke({"input": "Help me write a blog post", "user_id": "user_123"})
# 5. Store outcome
memory.store(
text=f"User asked for blog help. Provided structure with intro, 3 sections, outro. User rated quality 9/10.",
memory_type="outcome",
metadata={
"user_id": "user_123",
"task": "blog-writing",
"success": True,
"rating": 9
}
)
# Next time the same user asks, Recall retrieves this memory,
# and the agent applies the learned structure again.Implementation Checklist
- Install Recall SDK (
pip install recall-sdkornpm install @arc-labs/recall) - Initialize Recall with a name and metadata schema matching your agent
- Add a retriever step before your chain that calls
memory.retrieve()with the user input - Inject retrieved memories into your prompt via
ChatPromptTemplateor custom runnable - After chain execution, call
memory.store()with the decision, outcome, and metadata - Test a 2-session flow: run once, store an outcome, run again and verify the retriever surfaced it
- Add filtering logic (
filters={"user_id": ...}) to isolate memories per user or agent
Next Steps
- Deep dive on schema design: Schema Design Patterns
- Compare to LlamaIndex: Using Recall with LlamaIndex
- Learn memory architectures: Memory Architectures
- See how Recall differs from traditional frameworks: LangChain Memory vs LangGraph State vs Recall
Metric
40% reduction in redundant LLM calls. With Recall, your agent reuses learned context (user preferences, successful strategies, past decisions) instead of rediscovering them. Fewer calls = lower latency and lower cost.