LangChain Cheatsheet: LCEL, Agents, RAG and LangGraph
By DevShelfHub
LangChain is a Python/JS framework for composing LLM-powered applications: it provides a unified interface across model providers, a composable LCEL pipe syntax, and pre-built chains for RAG, agents, and memory. This cheatsheet covers the core imports, Chat and Embedding model wrappers, LCEL runnables, prompt templates, retrievers, agents, tools, LangGraph state, and full minimal RAG and agent examples.
75 items
◷ 7 min
Chains
LCEL
LangGraph
RAG
LangChain is a Python and JavaScript framework that provides a unified interface for building LLM-powered applications. Its core insight is that most LLM applications follow the same structural patterns — retrieve context, format a prompt, call a model, parse the output — so LangChain abstracts each step behind composable primitives. The LangChain Expression Language (LCEL) lets you chain these primitives with the pipe operator (|), producing a lazy, streaming-capable runnable that can be invoked, batched, or streamed with the same API surface.
The framework is organised into several packages: langchain-core holds the base abstractions (Runnable, BaseMessage, BasePromptTemplate), langchain ships the high-level chains and agents, and langchain-community or provider packages (e.g. langchain-openai, langchain-anthropic) provide concrete model integrations. Pinning to provider packages rather than langchain-community gives you faster upgrades and smaller dependency footprints in production.
Agents in LangChain follow the ReAct (Reason + Act) loop: the model decides which tool to call, the framework executes it and feeds the result back, and the loop continues until the model emits a final answer. LangGraph extends this model to multi-node stateful graphs, enabling cycles, parallel branches, and human-in-the-loop checkpoints — essential for production agentic workflows. This cheatsheet covers the full daily surface: imports, model wrappers, LCEL chains, retrievers, agents, memory, callbacks, and end-to-end RAG and agent patterns.
LangChain moves fast — module paths and class names shift between minor versions
(e.g. langchain.chat_models →
langchain_openai,
LLMChain → LCEL, classic memory → LangGraph checkpointers).
If an import errors, check the official docs at
python.langchain.com
for the current path. This sheet pins to the names current as of May 2026.
Install · envSetup
bash
# pip — install only what you need; provider packages are split out
pip install langchain langchain-core langchain-community langgraph
pip install langchain-openai langchain-anthropic # providers
pip install langchain-chroma langchain-pinecone # vector stores
# env
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-...
export LANGSMITH_API_KEY=ls-... # optional, for tracing
Where things liveCommon imports
Provider integrations live in their own packages — langchain-openai,
langchain-anthropic, etc. Core abstractions stay in
langchain-core. Old from langchain import …
paths still work but are mostly re-exports.
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
OpenAI chat + embeddings.
from langchain_anthropic import ChatAnthropic
Anthropic chat.
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage
Message classes.
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate, MessagesPlaceholder
Prompt templates.
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
Output parsers.
from langchain_core.runnables import RunnablePassthrough, RunnableParallel, RunnableLambda
LCEL building blocks.
from langchain_core.tools import tool
The @tool decorator.
from langchain.agents import create_agent, before_model, after_model, wrap_model_call, wrap_tool_call
Agent factory + 4 middleware decorators.
from langgraph.graph import StateGraph, MessagesState, START, END
Graph primitives.
from langgraph.checkpoint.memory import MemorySaver
In-memory checkpointer (dev).
from langgraph.checkpoint.sqlite import SqliteSaver
SQLite checkpointer (prod).
from langchain_community.document_loaders import WebBaseLoader, PyPDFLoader
Document loaders.
from langchain_text_splitters import RecursiveCharacterTextSplitter
Text splitter (own package).
from langchain_chroma import Chroma
Local vector store.
from langchain_pinecone import PineconeVectorStore
Managed vector store.
Chat models · messagesModels
Chat models
ChatOpenAI(model="gpt-4o-mini", temperature=0)
OpenAI chat model.
ChatAnthropic(model="claude-sonnet-4-6")
Anthropic chat model.
llm.invoke("hi")
Single sync call → AIMessage.
await llm.ainvoke("hi")
Async variant. Use in FastAPI / asyncio.
llm.batch(["q1", "q2"])
Parallel calls. Faster than a Python loop.
for chunk in llm.stream("hi"): …
Stream tokens as they arrive.
Message types
SystemMessage("You are a tutor.")
Sets behavior / persona.
HumanMessage("What is RAG?")
User input.
AIMessage("RAG is…")
Model response. Has .content and .tool_calls.
ToolMessage(content, tool_call_id)
Tool execution result fed back to the model.
Pass a list[BaseMessage] to .invoke() for multi-turn — strings are auto-wrapped as HumanMessage.
Templates · placeholdersPrompts
PromptTemplate.from_template("Tell me a {topic} joke")
Decorate a Python function into a tool. Docstring + type hints become the schema.
llm_with_tools = llm.bind_tools([add, search])
Give the model tools it can call.
resp.tool_calls
List of {name, args, id} the model wants to invoke.
add.invoke(call["args"])
Execute the tool yourself with the model’s args.
TavilySearchResults(max_results=3)
Prebuilt web-search tool.
Reason + act loopAgents
from langchain.agents import create_agent
High-level agent factory.
agent = create_agent(model, tools=[…])
Build a tool-using agent.
agent.invoke({"messages":[("user","…")]})
Run; returns final state.
create_agent(…, middleware=[hook])
Inject pre/post hooks.
Middleware decorators
@before_model
Runs before each model call. Inject context, redact, rate-limit.
@after_model
Runs after each model call. Log, filter, transform.
@wrap_model_call
Wrap entire model call. Add retry / fallback logic.
@wrap_tool_call
Wrap tool invocations. Sandbox, audit, mock.
Persist across turnsMemory & state
Modern path: memory has moved from chain-attached
ConversationBufferMemory / RunnableWithMessageHistory
to graph-level checkpointers in LangGraph. State is keyed by thread_id
and persisted via a Saver. Use the legacy classes only if you’re maintaining old code.
Current — LangGraph checkpointers Preferred
MemorySaver()
In-process checkpointer. Drop-in for dev.
SqliteSaver.from_conn_string("checkpoints.db")
Durable checkpointer for single-node prod.
PostgresSaver.from_conn_string("postgresql://…")
Durable, multi-node prod.
graph.compile(checkpointer=saver)
Make a graph stateful.
config = {"configurable":{"thread_id":"u1"}}
Identify a conversation thread. Required when checkpointer is set.
graph.get_state(config)
Inspect current state of a thread.
graph.update_state(config, {"messages":[…]})
Patch state (e.g., human-in-the-loop edit).
Legacy — chain-attached memory Legacy
InMemoryChatMessageHistory()
Per-session message store. Use a checkpointer instead.
RunnableWithMessageHistory(chain, get_history)
Wraps a chain to add memory. Superseded by graph state.
ConversationBufferMemory()
Pre-LCEL memory class. Avoid in new code.
Load → split → embed → store → retrieveRAG pipeline
Prefer with_structured_output over PydanticOutputParser.
The latter regex-parses model output and fails on minor format drift; the former uses the model’s native JSON/tool mode.
RunnablePassthrough() in a dict is a fork, not a no-op.{"context": retriever, "question": RunnablePassthrough()} sends the same input to both branches.
Chunk size matters more than embedding model.
Most bad-RAG diagnoses are really bad chunking. Start at chunk_size=800–1200, overlap=120–200.
Common trapsWatch out for
Don’t call .invoke() inside an async event loop.
It blocks. Use .ainvoke() in FastAPI / asyncio. The error is silent latency, not a crash.
Always set a thread_id when using a checkpointer.
Missing thread_id silently makes every turn a fresh conversation — no memory.
.batch() isn’t magic.
It parallelizes I/O but provider rate limits still apply. Tune max_concurrency in RunnableConfig.
LangChain is a Python (and JavaScript) framework for building LLM-powered applications. It provides abstractions for model calls, prompt templates, output parsers, retrieval chains, tool-using agents, and memory. Since v0.3, the recommended way to compose these components is through LCEL (LangChain Expression Language), which uses the pipe operator.
What is LCEL in LangChain?
LCEL (LangChain Expression Language) is LangChain v0.2+ syntax for composing chains using the pipe operator. Each component (prompt, model, parser, retriever) implements a Runnable interface with invoke(), stream(), and batch() methods. Chains are built as prompt | model | parser, and the resulting chain is itself a Runnable.
How do LangChain agents work?
A LangChain agent binds tools to a model and runs a loop: the model receives the task and tool descriptions, chooses a tool and arguments, observes the result, and repeats until it produces a final answer. Modern agents use the model's native tool-calling API rather than ReAct text parsing. LangGraph is now the recommended framework for complex multi-step agents.
How do I build a RAG pipeline with LangChain?
Load documents with a document loader, split them with a text splitter, embed and store chunks in a vector store, then create a retriever. Build a chain as retriever | format_docs | prompt | model | parser. LangChain includes built-in integrations for Chroma, Pinecone, pgvector, and Weaviate so you can swap stores without rewriting the chain.
What is the difference between LangChain and LangGraph?
LangChain provides the building blocks: model wrappers, prompt templates, retrievers, and simple sequential chains. LangGraph adds a stateful graph execution engine on top for orchestrating cyclic, branching, and multi-agent workflows with explicit state management and checkpointing. Most new agent work starts with LangGraph rather than legacy LangChain AgentExecutor.