LangChain is the most widely-used open-source framework for building LLM-powered applications. In 2026, it’s downloaded over 100 million times per month and has become the standard way to connect AI models to the real world — databases, APIs, files, the web.
Think of LangChain as the plumbing between your code and AI models. Instead of writing custom code for every model provider, memory system, or tool, LangChain gives you a unified interface so you can focus on building your product.
💡
Builder’s Mindset
LangChain isn’t magic — it’s structured engineering. Every piece of it is just Python classes wiring together LLM calls, tool execution, and memory. Once you understand the pattern, you can build anything.
What problems does it solve?
🔌
Provider Fragmentation
OpenAI, Claude, Gemini, Mistral — all have different APIs. LangChain unifies them so you swap models with one line.
🔄
Agent Loops
Building the think→act→observe loop from scratch is tedious. LangChain gives you a production-grade loop out of the box.
🧠
Memory & State
LLMs are stateless. LangChain handles conversation history, long-term memory, and context management for you.
02 — ECOSYSTEMThe 2026 Ecosystem
LangChain is not one library — it’s a family of tools. Understanding which tool to reach for is the first key decision as a builder.
Tracing, debugging, evaluation, and production monitoring
Always — use from day 1
Always On
🗺️
Learning Path
Start with LangChain to learn the core concepts. Graduate to LangGraph when you need complex orchestration. Use Deep Agents when you need an all-in-one production agent. Always add LangSmith for visibility.
How the Agent Loop Works
Every LangChain agent follows this core reasoning cycle. Understanding this is the foundation of everything else.
User Input
human message
→
LLM Reasons
decide: respond or act?
→
Call Tool
execute function
→
Observe Result
tool output → context
→
Final Answer
or loop again
03 — SETUPInstallation & Setup
LangChain is modular — you install only the provider packages you need. Here’s the recommended setup for 2026:
# Get key at: https://aistudio.google.comGOOGLE_API_KEY=your-key-here
LANGSMITH_TRACING=true
$pip install -U langchain langchain-ollama⎘
💚
Free & Private
Ollama runs models locally on your machine — no API key, no usage costs, no data sent to the cloud. Install Ollama from ollama.com, then run ollama pull llama3.3.
04 — CODEYour First Agent
Let’s build a real agent step by step. We’ll start simple, then layer on complexity. Every line below is explained — no black boxes.
Example 1 — Minimal Agent (3 minutes to run)
01_first_agent.py
from langchain.agents import create_agent
from dotenv import load_dotenv
load_dotenv() # loads ANTHROPIC_API_KEY from .env# ── Step 1: Define a tool ──────────────────────────────────────────────
# Any Python function becomes a tool. The docstring is what the LLM reads
# to understand what the tool does — so write clear docstrings!defget_crypto_price(symbol: str) -> str:
“””
Get the current price of a cryptocurrency by its ticker symbol.
Returns a string with the price in USD.
Example symbols: BTC, ETH, SOL, ADA
“””# In production, you’d call a real API here (CoinGecko, Binance, etc.)
prices = {“BTC”: 65420, “ETH”: 3210, “SOL”: 182, “ADA”: 0.58}
price = prices.get(symbol.upper(), None)
if price:
returnf”{symbol.upper()} is currently trading at ${price:,} USD”returnf”Price not found for {symbol}. Try BTC, ETH, SOL, or ADA.”# ── Step 2: Create the agent ────────────────────────────────────────────
# The model string tells LangChain which provider + model to use.
# Swap “claude-sonnet-4-6” for “openai:gpt-4o” or “ollama:llama3.3”
agent = create_agent(
model=“claude-sonnet-4-6”,
tools=[get_crypto_price],
system_prompt=“””You are a helpful crypto assistant.
When asked about prices, always use the get_crypto_price tool.
Format prices clearly and add a brief market context.”””,
)
# ── Step 3: Run it ──────────────────────────────────────────────────────
result = agent.invoke({
“messages”: [{
“role”: “user”,
“content”: “What’s the price of BTC and ETH right now?”
}]
})
# The last message in the list is the agent’s final responseprint(result[“messages”][-1].content)
⚠️
Common Mistake
Don’t forget the load_dotenv() call at the top. Without it, your API key won’t load and you’ll get an authentication error.
When you run this, the agent will: (1) see you asked about two coins, (2) call get_crypto_price("BTC"), (3) call get_crypto_price("ETH"), and (4) write a natural response combining both results.
05 — CODEMulti-Tool Agents
Real agents need multiple tools. The LLM decides which tool to call based on the user’s question — you just provide the toolbox.
Example 2 — Data Analysis Agent with 4 Tools
02_multi_tool_agent.py
import pandas as pd
import json
from langchain.agents import create_agent
from dotenv import load_dotenv
load_dotenv()
# ── Tool 1: Load CSV data ────────────────────────────────────────────────defload_sales_data() -> str:
“””Load the sales dataset and return a summary of its structure.”””
df = pd.DataFrame({
“month”: [“Jan”, “Feb”, “Mar”, “Apr”, “May”, “Jun”],
“revenue”: [42000, 38500, 55200, 61800, 49300, 72100],
“units”: [210, 193, 276, 309, 247, 361],
“region”: [“UAE”, “UAE”, “KSA”, “KSA”, “UAE”, “KSA”]
})
returnf”Dataset loaded. Shape: {df.shape}.\nData:\n{df.to_string()}“# ── Tool 2: Calculate statistics ─────────────────────────────────────────defcalculate_statistics(metric: str) -> str:
“””
Calculate statistics for a given metric.
Args:
metric: Either ‘revenue’ or ‘units’
Returns mean, max, min, and total.
“””
data = {
“revenue”: [42000, 38500, 55200, 61800, 49300, 72100],
“units”: [210, 193, 276, 309, 247, 361]
}
if metric not in data:
returnf”Unknown metric. Choose ‘revenue’ or ‘units'”
values = data[metric]
return json.dumps({
“metric”: metric,
“mean”: round(sum(values) / len(values), 2),
“max”: max(values),
“min”: min(values),
“total”: sum(values),
“growth”: f”{((values[-1]-values[0])/values[0]*100):.1f}%”
}, indent=2)
# ── Tool 3: Filter by region ─────────────────────────────────────────────deffilter_by_region(region: str) -> str:
“””
Filter sales data by region.
Args:
region: Region name — ‘UAE’ or ‘KSA’
Returns revenue and units for that region only.
“””
regional_data = {
“UAE”: {“months”: [“Jan”,“Feb”,“May”], “revenue”: [42000,38500,49300]},
“KSA”: {“months”: [“Mar”,“Apr”,“Jun”], “revenue”: [55200,61800,72100]},
}
d = regional_data.get(region.upper())
if not d:
return“Region not found. Try ‘UAE’ or ‘KSA'”
total = sum(d[“revenue”])
returnf”{region.upper()} data: {d}. Total revenue: ${total:,}“# ── Tool 4: Generate insight ─────────────────────────────────────────────deffind_best_month() -> str:
“””Find the best performing month by revenue.”””
months = [“Jan”, “Feb”, “Mar”, “Apr”, “May”, “Jun”]
revenue = [42000, 38500, 55200, 61800, 49300, 72100]
best_idx = revenue.index(max(revenue))
returnf”Best month: {months[best_idx]} with ${revenue[best_idx]:,} revenue”# ── Create the analyst agent ─────────────────────────────────────────────
agent = create_agent(
model=“claude-sonnet-4-6”,
tools=[load_sales_data, calculate_statistics, filter_by_region, find_best_month],
system_prompt=“””You are a senior data analyst.
When asked about data, always load it first before analyzing.
Provide insights backed by numbers, and suggest next steps.”””,
)
# One question → multiple tool calls automatically
result = agent.invoke({
“messages”: [{
“role”: “user”,
“content”: “””Analyze our H1 sales data.
Which region performed better?
What’s the best month and revenue growth trend?”””
}]
})
print(result[“messages”][-1].content)
06 — CODEAdding Memory
By default, agents forget everything after each call. Memory lets your agent remember the conversation — essential for chatbots, assistants, and multi-turn workflows.
Example 3 — Conversational Agent with Memory
03_memory_agent.py
from langchain.agents import create_agent
from dotenv import load_dotenv
load_dotenv()
defget_course_info(course_name: str) -> str:
“””Get information about a specific AI/Data Science course.”””
courses = {
“ai residency”: “12-week intensive. Topics: ML, LLMs, RAG, Agents. $499.”,
“ai guild”: “Community membership with live sessions. $49/month.”,
“ai executive”: “6-week program for business leaders. $299. No coding required.”,
}
key = course_name.lower()
return courses.get(key, f”Course ‘{course_name}’ not found.”)
agent = create_agent(
model=“claude-sonnet-4-6”,
tools=[get_course_info],
system_prompt=“You are a helpful learning advisor at Decoding Data Science.”,
)
# ── Multi-turn conversation ──────────────────────────────────────────────
# The trick: keep passing the FULL conversation history each time.
# Each agent response returns updated messages — we append and reuse.
conversation = []
defchat(user_message: str) -> str:
# Add user message to history
conversation.append({“role”: “user”, “content”: user_message})
# Run agent with full history
result = agent.invoke({“messages”: conversation})
# Extract the new messages (agent may produce multiple)
new_messages = result[“messages”][len(conversation):]
conversation.extend(new_messages)
# Return the last (final) messagereturn result[“messages”][-1].content
# ── Simulate a real conversation ─────────────────────────────────────────print(“User: Hi, I want to learn AI. Where do I start?”)
print(“Agent:”, chat(“Hi, I want to learn AI. Where do I start?”))
print(“\nUser: Tell me more about the AI Residency”)
print(“Agent:”, chat(“Tell me more about the AI Residency”))
print(“\nUser: How does that compare to the AI Guild?”)
print(“Agent:”, chat(“How does that compare to the AI Guild?”))
# Notice the agent remembers you mentioned AI Residency ↑
💡
Memory Pattern
The key insight: LangChain doesn’t “store” memory magically — you pass the full conversation list every time. Each call returns an updated message list. Store it, append to it, and pass it back.
07 — CODEBuilding a RAG Agent
RAG (Retrieval-Augmented Generation) lets your agent answer questions from your own documents, knowledge bases, or data — not just from the LLM’s training data. This is one of the most in-demand skills for AI builders in 2026.
How RAG works
1
Embed your documents
Convert text chunks into vector embeddings (numerical representations). Store them in a vector database like FAISS, Chroma, or Pinecone.
2
User asks a question
The question is also converted to an embedding. The vector DB finds the most semantically similar document chunks.
3
Inject context into the LLM
The retrieved chunks are added to the prompt. The LLM answers based on your documents — grounded, accurate, no hallucination.
4
Return a cited answer
The agent generates an answer that references your actual data — not a guess from training data.
from langchain_community.vectorstores import FAISS
from langchain_anthropic import ChatAnthropic, AnthropicEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.agents import create_agent
from dotenv import load_dotenv
load_dotenv()
# ── Step 1: Your knowledge base ──────────────────────────────────────────
# In production this would be PDFs, docs, database records, etc.
documents = [
“””LangChain 2026 introduced Deep Agents as the recommended way to build
production agents. Deep Agents include automatic context compression,
a virtual filesystem, sub-agent spawning, and long-term memory.”””,
“””LangGraph is LangChain’s low-level orchestration framework. It models
agent workflows as graphs where nodes are processing steps and edges
define the flow between them. It supports durable execution and
human-in-the-loop checkpoints.”””,
“””LangSmith provides observability for LangChain agents. Set the
LANGSMITH_TRACING=true environment variable to automatically trace
all agent calls, tool invocations, and LLM completions.”””,
“””RAG stands for Retrieval-Augmented Generation. It combines a retrieval
system (vector database) with an LLM. Documents are chunked, embedded,
and stored. At query time, relevant chunks are retrieved and injected
into the LLM prompt as context.”””,
]
# ── Step 2: Chunk the documents ──────────────────────────────────────────
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50# overlap ensures context isn’t cut off at boundaries
)
chunks = splitter.create_documents(documents)
# ── Step 3: Create embeddings and vector store ───────────────────────────
embeddings = AnthropicEmbeddings()
vectorstore = FAISS.from_documents(chunks, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={“k”: 2}) # top-2 chunks# ── Step 4: Wrap retriever as an agent tool ──────────────────────────────defsearch_knowledge_base(query: str) -> str:
“””
Search the LangChain documentation knowledge base.
Use this to answer questions about LangChain, LangGraph,
LangSmith, Deep Agents, and RAG.
“””
results = retriever.get_relevant_documents(query)
if not results:
return“No relevant information found.”
context = “\n\n—\n\n”.join([doc.page_content for doc in results])
returnf”Found {len(results)} relevant sections:\n\n{context}“# ── Step 5: Build the RAG agent ──────────────────────────────────────────
agent = create_agent(
model=“claude-sonnet-4-6”,
tools=[search_knowledge_base],
system_prompt=“””You are a LangChain documentation assistant.
Always search the knowledge base before answering.
Only answer based on retrieved context — say “I don’t know” if not found.
Cite which section your answer comes from.”””,
)
result = agent.invoke({
“messages”: [{
“role”: “user”,
“content”: “How do Deep Agents handle long conversations?”
}]
})
print(result[“messages”][-1].content)
08 — CODEStructured Output
Getting unstructured text from an LLM is fine for conversations. But for data pipelines, APIs, and applications, you need typed, validated JSON output every time. LangChain makes this trivial with Pydantic.
Example 5 — Extract Structured Data from Text
05_structured_output.py
from langchain_anthropic import ChatAnthropic
from pydantic import BaseModel, Field
from typing import List, Optional
from dotenv import load_dotenv
load_dotenv()
# ── Step 1: Define your output schema with Pydantic ──────────────────────
# This is the contract — the LLM MUST return data in this exact shapeclassJobPosting(BaseModel):
title: str = Field(description=“Job title”)
company: str = Field(description=“Company name”)
location: str = Field(description=“Location or ‘Remote'”)
salary_min: Optional[int] = Field(description=“Minimum salary in USD”)
salary_max: Optional[int] = Field(description=“Maximum salary in USD”)
required_skills: List[str] = Field(description=“Required technical skills”)
experience_years: int = Field(description=“Minimum years of experience”)
is_ai_role: bool = Field(description=“True if this is an AI/ML role”)
# ── Step 2: Create a model with structured output ─────────────────────────
llm = ChatAnthropic(model=“claude-sonnet-4-6”)
structured_llm = llm.with_structured_output(JobPosting)
# ── Step 3: Extract from raw job posting text ─────────────────────────────
raw_job_post = “””
🚀 Senior AI Engineer @ TechCorp Dubai
We’re hiring a skilled ML Engineer with 5+ years experience to join
our growing AI team in Dubai (hybrid). You’ll build production LLM
pipelines using LangChain, LangGraph, and PyTorch.
Salary: AED 35,000–50,000/month (~$9,500–$13,600 USD).
Must have: Python, LangChain, RAG systems, vector databases.
Nice to have: LangGraph, AWS, Docker.
“””
result: JobPosting = structured_llm.invoke(f”Extract job info:\n{raw_job_post}“)
# ── Result is a typed Python object — not a string! ───────────────────────print(f”Title: {result.title}“)
print(f”Company: {result.company}“)
print(f”Salary: ${result.salary_min:,} – ${result.salary_max:,}“)
print(f”Skills: {‘, ‘.join(result.required_skills)}“)
print(f”AI Role: {result.is_ai_role}“)
print(f”Experience: {result.experience_years}+ years”)
# ── You can also convert to dict or JSON for APIs ─────────────────────────print(result.model_dump()) # → Python dictprint(result.model_dump_json()) # → JSON string
09 — NEW 2026Deep Agents
Introduced in late 2025 and matured in 2026, Deep Agents is the “batteries-included” agent framework built on top of LangChain and LangGraph. It’s the recommended starting point for any complex, real-world agent task.
🆕
Why Deep Agents?
Standard agents hit a wall on long tasks — the context window fills up, the agent loses track, or it can’t coordinate subtasks. Deep Agents solves this with built-in planning, a virtual filesystem, and sub-agent delegation.
Planning
📋
Explicit Task Planning
A built-in write_todos tool forces the agent to break down any task into discrete steps before acting. Reasoning is transparent and traceable.
Context
📁
Virtual Filesystem
Tools like read_file, write_file, and edit_file let the agent offload large context to storage — no more context window overflow.
Scale
🤝
Sub-Agent Delegation
Spawn specialized sub-agents for parallel tasks. Each sub-agent is stateful via Agent Protocol — thread history preserved across interactions.
Memory
🧠
Auto-Compression
When the conversation grows long, older messages are automatically summarized — keeping the agent effective across hour-long sessions.
Example 6 — Deep Agents Quick Start
$pip install deepagents⎘
06_deep_agent.py
from deepagents import create_deep_agent
from dotenv import load_dotenv
load_dotenv()
# ── Custom tool on top of built-in filesystem + planning tools ───────────defsearch_papers(topic: str) -> str:
“””Search for research papers on a given topic.”””# In production: call Semantic Scholar, ArXiv API, etc.returnf”Found 3 papers on ‘{topic}’: [2024] Attention Mechanisms, [2025] RAG Survey, [2026] Agent Patterns”# ── Deep Agent: comes with planning, filesystem, compression built-in ─────
agent = create_deep_agent(
model=“claude-sonnet-4-6”,
tools=[search_papers], # your tools + all built-in deep tools
system_prompt=“””You are a research assistant.
For complex tasks, always plan first using write_todos.
Save findings to files so you don’t lose context.”””,
# Deep Agent specific options:
auto_compress=True, # auto-summarize old messages
filesystem=True, # enable virtual file system tools
max_subagents=3, # allow up to 3 parallel sub-agents
)
# Give it a complex, multi-step task
result = agent.invoke({
“messages”: [{
“role”: “user”,
“content”: “””Research the latest developments in RAG systems for 2026.
Find papers, summarize key findings, compare approaches,
and write a structured report saved as ‘rag_report.md’.”””
}]
})
# The agent will: plan → search → save → summarize → write reportprint(result[“messages”][-1].content)
10 — DEBUGGINGDebugging with LangSmith
Flying blind when your agent fails is painful. LangSmith gives you an X-ray view of every agent decision — what the LLM was thinking, which tools were called, how long each step took, and exactly where it went wrong.
Setup is literally 2 lines
.env
LANGSMITH_TRACING=true
LANGSMITH_API_KEY=ls__your_key_from_smith.langchain.com
# That’s it. Every agent.invoke() call is now traced automatically.
Example 7 — Using LangSmith Evaluations
07_langsmith_eval.py
from langsmith import Client, evaluate
from langchain.agents import create_agent
from dotenv import load_dotenv
load_dotenv()
client = Client()
# ── Step 1: Create a test dataset in LangSmith ───────────────────────────
dataset_name = “crypto-agent-evals-2026”
dataset = client.create_dataset(dataset_name)
client.create_examples(
inputs=[
{“question”: “What is the price of BTC?”},
{“question”: “Compare ETH and SOL prices”},
],
outputs=[
{“expected_tools”: [“get_crypto_price”]},
{“expected_tools”: [“get_crypto_price”, “get_crypto_price”]},
],
dataset_id=dataset.id
)
# ── Step 2: Define your agent as a function ──────────────────────────────defget_crypto_price(symbol: str) -> str:
“””Get price of a cryptocurrency by symbol (BTC, ETH, SOL, ADA)”””
prices = {“BTC”:65420, “ETH”:3210, “SOL”:182, “ADA”:0.58}
returnf”{symbol}: ${prices.get(symbol.upper(), ‘N/A’)}“
agent = create_agent(model=“claude-sonnet-4-6”, tools=[get_crypto_price])
defrun_agent(inputs: dict) -> dict:
result = agent.invoke({
“messages”: [{“role”:“user”, “content”: inputs[“question”]}]
})
return {“response”: result[“messages”][-1].content}
# ── Step 3: Run evaluations ──────────────────────────────────────────────defcorrectness_evaluator(run, example):
“””Check if the response mentions a price number”””
response = run.outputs.get(“response”, “”)
passed = “$”in response
return {“score”: 1if passed else0, “comment”: “Has price”if passed else“Missing price”}
results = evaluate(
run_agent,
data=dataset_name,
evaluators=[correctness_evaluator],
experiment_prefix=“crypto-agent-v1”
)
print(f”Results: {results.to_pandas()}“)
# View full traces at: https://smith.langchain.com
✅ Builder’s Checklist — What You’ve Learned
🔌 What LangChain is and why it exists in 2026
🗺️ The difference between LangChain, LangGraph, Deep Agents, and LangSmith
⚙️ How to install and configure any model provider
🤖 How to build a basic agent with create_agent()
🛠️ How to give agents multiple tools and let the LLM decide which to call
🧠 How to implement multi-turn conversation memory
📚 How to build a RAG pipeline with a vector store
📤 How to extract structured data with Pydantic schemas
🚀 What Deep Agents adds over standard agents
🔭 How to trace and evaluate agents with LangSmith
NEXT STEPSWhere to Go From Here
Official Docs
📘
LangChain Docs 2026
The official documentation at docs.langchain.com — models, agents, tools, middleware, and advanced patterns.
Build Something Real Today
The best way to learn LangChain is to pick one of the examples above and extend it with your own data. Start with Example 2 (multi-tool agent) and replace the mock data with a real CSV or API you work with. You’ll learn more in 30 minutes of building than in 3 hours of reading.