LangChain cheat sheet

A scannable LangChain reference: 25 short snippets across 12 topics, each linking back to the lesson it came from.

At a glance

TopicWhat it covers
Prompt templates and chainsA prompt template is a function from variables to messages. Keeping it separate from the call site means you canlesson
Tools and agentsA tool is a normal function plus a description the model can read. The signature becomes the argument schema and thelesson
Retrieval-augmented generationChunk and index documents, retrieve the right passages, and answer with citations while allowing an honest not-foundlesson
Models, messages and providersinit_chat_model, provider packages, message types, streaming, and swapping providers without rewriting the rest of thelesson
Structured output and output parserswith_structured_output, Pydantic and JSON schemas, plain text parsers, and handling parse failures with retries insteadlesson
Runnables and LangChain Expression Language in depthRunnableLambda, RunnablePassthrough, parallel and branching runnables, fallbacks, retries, runtime configuration andlesson
Document loaders and text splittersChunk size is a retrieval parameter, not a formatting preference. Small chunks match precise questions; large chunkslesson
Embeddings and vector storesEmbedding model choice, FAISS, Chroma and pgvector, indexing and updating, and filtering on metadata before similaritylesson
Retrievers in depthSimilarity search, MMR, multi-query and contextual compression, hybrid search, reranking, and writing your ownlesson
Conversation memory and historyThe test of a good memory design: restart the service, and the next request should behave identically. Anything heldlesson
Observability with callbacks and LangSmithStructured logging around each step gets you most of the value of a tracing platform in about twenty lines. Adopt alesson
Deploying LangChain apps and moving to LangGraphDependency pinning, streaming from an API, production error handling, and migrating a multi-step agent workflow tolesson

Quick snippets

Prompt templates and chains

Prompts as reusable templates

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a terse technical editor. Return the rewritten text only."),
    ("human", "Rewrite for clarity and keep every fact:\n\n{draft}"),
])

chain = prompt | ChatOpenAI(model="gpt-4o-mini", temperature=0) | StrOutputParser()

print(chain.invoke({"draft": "The system does the thing where it retries on failure."}))

Composing and branching

from langchain_core.runnables import RunnableParallel, RunnablePassthrough, RunnableLambda

clean = RunnableLambda(lambda d: d["text"].strip())

chain = RunnableParallel(
    summary=clean | summary_chain,
    keywords=clean | keyword_chain,
    original=RunnablePassthrough(),          # pass the input through unchanged
)

out = chain.invoke({"text": "  Long report body ...  "})
print(out.keys())                            # dict_keys(['summary', 'keywords', 'original'])

Full lesson: Prompt templates and chains →

Tools and agents

Turning functions into tools

from langchain_core.tools import tool

@tool
def stock_level(sku: str) -> int:
    """Return units on hand for a SKU. Call this before promising any delivery date."""
    return warehouse.on_hand(sku)

@tool
def place_order(sku: str, quantity: int) -> dict:
    """Create a draft order. Does not charge the customer; the draft needs approval."""
    return orders.create_draft(sku, quantity)

… 1 more lines in the full lesson.

The agent loop

from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a support agent. Use tools for every fact; never guess stock or prices."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

tools = [stock_level, place_order]
agent = create_tool_calling_agent(llm, tools, prompt)

… 11 more lines in the full lesson.

Full lesson: Tools and agents →

Retrieval-augmented generation

Build the index once

from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma

splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,          # characters, not tokens - measure with your embedding model
    chunk_overlap=120,       # keep enough context that a sentence is not cut in half
    separators=["\n\n", "\n", ". ", " "],
)
chunks = splitter.split_documents(load_documents("docs/"))

store = Chroma.from_documents(chunks, OpenAIEmbeddings(model="text-embedding-3-small"))

… 1 more lines in the full lesson.

Ask with the retrieved context

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_messages([
    ("system", "Answer using only the context below. If the answer is not present, "
               "reply exactly: Not found in the provided documents."),
    ("human", "Context:\n{context}\n\nQuestion: {question}"),
])

def format_docs(docs):
    return "\n\n".join(f"[{d.metadata['source']}] {d.page_content}" for d in docs)

… 7 more lines in the full lesson.

Full lesson: Retrieval-augmented generation →

Models, messages and providers

Initialising a model

import os
from langchain.chat_models import init_chat_model

# one factory, many providers: the model string is parsed into provider + name
model = init_chat_model("gpt-4o-mini", model_provider="openai", temperature=0)
claude = init_chat_model("claude-3-5-sonnet-latest", model_provider="anthropic")
local = init_chat_model("llama3.2", model_provider="ollama", base_url="http://localhost:11434")

print(model.model_name if hasattr(model, "model_name") else type(model).__name__)

# provider packages are separate installs; a missing one fails at import time
# pip install langchain-openai langchain-anthropic langchain-ollama

… 4 more lines in the full lesson.

Message types

from langchain_core.messages import (
    SystemMessage, HumanMessage, AIMessage, ToolMessage, trim_messages
)

messages = [
    SystemMessage("You answer in British English, in at most three sentences."),
    HumanMessage("Summarise the point of idempotency in APIs."),
    AIMessage("An idempotent request can be repeated without changing the outcome."),
    HumanMessage("Give one concrete example."),
]

# a tool result is a distinct message type tied to a tool call id

… 14 more lines in the full lesson.

Streaming and batching

# streaming: print tokens as they arrive instead of waiting for the whole reply
for chunk in model.stream("Write a haiku about deployment."):
    print(chunk.content, end="", flush=True)

# async streaming for a web endpoint
import asyncio

async def stream_reply(prompt):
    pieces = []
    async for chunk in model.astream(prompt):
        pieces.append(chunk.content)
        yield chunk.content

… 11 more lines in the full lesson.

Full lesson: Models, messages and providers →

Structured output and output parsers

Structured output with a schema

from typing import Literal, Optional
from pydantic import BaseModel, Field
from langchain.chat_models import init_chat_model

class Ticket(BaseModel):
    """A support ticket extracted from a customer message."""

    category: Literal["billing", "technical", "account", "other"] = Field(
        description="The single best matching category.")
    urgency: Literal["low", "normal", "high"] = Field(
        description="high only if the customer is blocked from working.")
    order_id: Optional[str] = Field(default=None, description="Order reference, if present.")

… 14 more lines in the full lesson.

Parsers and validation

from langchain_core.output_parsers import (
    StrOutputParser, JsonOutputParser, PydanticOutputParser
)
from langchain_core.prompts import ChatPromptTemplate

str_parser = StrOutputParser()
json_parser = JsonOutputParser(pydantic_object=Ticket)
pydantic_parser = PydanticOutputParser(pydantic_object=Ticket)

prompt = ChatPromptTemplate.from_messages([
    ("system", "Extract the ticket.\n{format_instructions}"),
    ("human", "{message}"),

… 14 more lines in the full lesson.

Structured output in production

from langchain_core.runnables import RunnableLambda
from pydantic import ValidationError

def safe_extract(message: str):
    """Return a validated object, or an explicit failure record. Never guess."""
    try:
        ticket = extractor.invoke(message)["parsed"]
        if ticket is None:
            raise ValueError("model returned nothing parseable")
        return {"ok": True, "ticket": ticket}
    except (ValidationError, ValueError) as exc:
        return {"ok": False, "reason": str(exc)[:200], "input": message[:200]}

… 12 more lines in the full lesson.

Full lesson: Structured output and output parsers →

Runnables and LangChain Expression Language in depth

The Runnable protocol

from langchain_core.runnables import (
    RunnableLambda, RunnablePassthrough, RunnableParallel, RunnableBranch
)

# any function becomes a runnable; keep it pure and small
normalise = RunnableLambda(lambda x: x.strip().lower())
word_count = RunnableLambda(lambda x: len(x.split()))

# RunnableParallel runs its branches on the SAME input and returns a dict
enrich = RunnableParallel(text=RunnablePassthrough(), words=word_count)
print(enrich.invoke("  Hello World  "))

… 12 more lines in the full lesson.

Streaming through a composed chain

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_template("Explain {topic} in three sentences.")
chain = prompt | model | StrOutputParser()

# stream the final text out of a multi-step chain
for token in chain.stream({"topic": "idempotency keys"}):
    print(token, end="", flush=True)

# when intermediate steps matter, stream events instead of text
async def trace_chain(topic):

… 13 more lines in the full lesson.

Full lesson: Runnables and LangChain Expression Language in depth →

Document loaders and text splitters

Loading documents

from langchain_community.document_loaders import (
    PyPDFLoader, CSVLoader, UnstructuredMarkdownLoader,
    WebBaseLoader, DirectoryLoader, TextLoader,
)

# a PDF per page: page number becomes metadata, which is what citations need
pdf_docs = PyPDFLoader("handbook.pdf").load()
print(pdf_docs[0].metadata)
# {'source': 'handbook.pdf', 'page': 0, ...}

# every file in a tree, dispatched by extension, with parallel workers
loader = DirectoryLoader(

… 15 more lines in the full lesson.

Splitting text

from langchain_text_splitters import (
    RecursiveCharacterTextSplitter, MarkdownHeaderTextSplitter, TokenTextSplitter
)

# structure-first: split on markdown headings, then on size
headers = MarkdownHeaderTextSplitter(
    headers_to_split_on=[("#", "h1"), ("##", "h2"), ("###", "h3")]
)
sections = headers.split_text(markdown_text)
print(sections[0].metadata)     # {'h1': 'Guide', 'h2': 'Installation'}

size_splitter = RecursiveCharacterTextSplitter(

… 15 more lines in the full lesson.

Full lesson: Document loaders and text splitters →

Embeddings and vector stores

Choosing an embedding model

from langchain_openai import OpenAIEmbeddings
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.embeddings import OllamaEmbeddings

# hosted: strong, cheap, and a network dependency
openai_emb = OpenAIEmbeddings(model="text-embedding-3-small", dimensions=512)

# local: no per-call cost, no data leaving the machine
local_emb = HuggingFaceEmbeddings(
    model_name="sentence-transformers/all-MiniLM-L6-v2",
    encode_kwargs={"normalize_embeddings": True, "batch_size": 64},
)

… 11 more lines in the full lesson.

Updating an index

from langchain_core.documents import Document
import datetime

def reindex(store, source_path, new_chunks):
    """Replace every chunk from one source without touching the rest."""
    existing = store.get(where={"source": source_path})
    if existing["ids"]:
        store.delete(ids=existing["ids"])

    stamped = [
        Document(
            page_content=c.page_content,

… 15 more lines in the full lesson.

Full lesson: Embeddings and vector stores →

Retrievers in depth

Retrieval modes

from langchain_community.vectorstores import FAISS
from langchain_core.runnables import RunnableLambda

store = FAISS.from_documents(chunks, local_emb)

# 1. plain similarity: top-k nearest
basic = store.as_retriever(search_kwargs={"k": 6})

# 2. MMR: relevant but mutually diverse, good for summaries over a broad question
mmr = store.as_retriever(
    search_type="mmr",
    search_kwargs={"k": 6, "fetch_k": 30, "lambda_mult": 0.5},

… 11 more lines in the full lesson.

Multi-query, compression and hybrid

from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain.retrievers import ContextualCompressionRetriever, EnsembleRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
from langchain_community.retrievers import BM25Retriever

# multi-query: the model rewrites the question several ways, results are unioned
multi = MultiQueryRetriever.from_llm(retriever=basic, llm=model)

# contextual compression: keep only the sentences that bear on the question
compressor = LLMChainExtractor.from_llm(model)
compressed = ContextualCompressionRetriever(base_compressor=compressor, base_retriever=basic)

… 11 more lines in the full lesson.

Full lesson: Retrievers in depth →

Conversation memory and history

What belongs outside the context

# per-user retrieval: never retrieve across tenants
def user_retriever(user_id: str, question: str, k: int = 6):
    return store.similarity_search(
        question,
        k=k,
        filter={"tenant_id": user_id},     # enforced in the query, not after
    )

def build_messages(user_id, question, history):
    profile = load_profile(user_id)         # a database call, not a memory
    system = (
        "You are a support assistant.\n"

… 10 more lines in the full lesson.

Full lesson: Conversation memory and history →

Observability with callbacks and LangSmith

Tracing with LangSmith

# enable tracing with two environment variables
export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_API_KEY=lsv2_...
export LANGCHAIN_PROJECT=support-assistant

# or set it in code before importing anything that reads the environment
python -c "import os; os.environ['LANGCHAIN_TRACING_V2']='true'; import langchain"

Tracing with LangSmith

import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_PROJECT"] = "support-assistant"

from langsmith import traceable, Client

@traceable(run_type="tool", name="lookup_order")
def lookup_order(order_id: str) -> dict:
    return {"order_id": order_id, "status": "in_transit", "eta": "2026-09-21"}

@traceable(name="support_reply")
def support_reply(question: str, user_id: str) -> str:

… 12 more lines in the full lesson.

Full lesson: Observability with callbacks and LangSmith →

Deploying LangChain apps and moving to LangGraph

Packaging and pinning

# LangChain moves quickly: pin exact versions and upgrade deliberately
python -m pip freeze | grep -E "langchain|langgraph|pydantic" > requirements.txt

# a minimal pinned set for a RAG service
cat > requirements.txt <<'EOF'
langchain-core==0.3.29
langchain==0.3.14
langchain-openai==0.2.14
langchain-community==0.3.14
langchain-text-splitters==0.3.5
langgraph==0.2.62
pydantic==2.10.4

… 5 more lines in the full lesson.

Packaging and pinning

# fail fast at startup if a required environment variable is missing
import os
from dataclasses import dataclass

@dataclass(frozen=True)
class Settings:
    openai_api_key: str
    langchain_project: str
    vector_store_path: str
    max_concurrency: int = 4

    @classmethod

… 13 more lines in the full lesson.

Full lesson: Deploying LangChain apps and moving to LangGraph →

FAQ

Is this LangChain cheat sheet free to use?
Yes. No sign-up and no tracking: the page is static, every example is on the page itself, and you can print it or save it as a one-page reference.
Where do the examples come from?
Every snippet is taken from the 12 lessons of the LangChain course on this site, and each section links back to the lesson it was pulled from.
How do I go deeper than a cheat sheet?
Open the full LangChain course — it carries the worked explanations, the edge cases and the exercises behind every line here.

AI Basics AI Agents Math for AI Machine Learning scikit-learn TensorFlow

Last refreshed 2026-09-27.