In the rapidly evolving world of AI, building applications with Large Language Models (LLMs) has gone from a niche skill to a foundational one. Frameworks like LangChain have been instrumental in this shift, providing developers with the tools to chain together LLM calls, data sources, and actions. The LangChain Expression Language (LCEL) made it incredibly intuitive to create these "chains" as Directed Acyclic Graphs (DAGs) — clear, linear workflows that go from A to B to C.
But what happens when your AI needs to think in circles? What if it needs to revisit a step, ask for help, or decide between multiple paths based on its progress? Real-world problems are rarely linear. They require iteration, decision-making, and state management. This is precisely the challenge that LangGraph was built to solve.
If LCEL is like a straightforward assembly line, LangGraph is the dynamic, intelligent workshop where different workers can collaborate, review each other's work, and adapt their process on the fly. It's a game-changer for building sophisticated, agent-like systems.
This guide will walk you through everything you need to know about LangGraph, from the core concepts to building your first cyclical, stateful AI application.
Before diving into LangGraph, it's crucial to understand the limitations it addresses. Standard LangChain chains are fantastic for tasks like:
These are one-way streets. The data flows in a single direction without loops. But consider these more complex scenarios:
These applications require state (a memory of what has happened) and cycles (the ability to loop or go back). This is where LangGraph shines.
LangGraph extends the LCEL syntax with a few powerful, graph-theory-inspired concepts. At its heart, it allows you to define your workflow as a state machine.
Let's break down the key components:
The state is the central, most critical concept in LangGraph. It's a shared object that is passed between all the steps in your workflow. Every step (or "node") can read from this state and write back to it, effectively creating a persistent memory for the entire duration of the task.
Technically, this state is often defined as a Python TypedDict or a Pydantic BaseModel, ensuring that the data moving through your graph is structured and predictable.
A node is a single "step" or unit of work in your graph. It's a function or any other LangChain Runnable that performs an action. Each node receives the current state as input, performs its task, and returns an object containing the new or updated information to be merged back into the state.
Examples of nodes could be:
An edge is a connection that directs the flow from one node to another. In the simplest case, you have a standard edge that says, "After node A finishes, always proceed to node B."
The real power of LangGraph, however, comes from conditional edges.
This is where the magic happens. A conditional edge is a routing function that inspects the current state and decides which node to go to next. It acts as a traffic controller for your workflow.
This ability to route an application's flow based on its own intermediate results is the key to building autonomous and intelligent agents.
Talk is cheap. Let's build something! We'll create a simple agent that tries to answer a question by searching the web. Crucially, it will first grade the search results to see if they are relevant. If not, it will try searching again.
This is a classic example that's simple to understand but impossible to build with a standard linear chain. Mastering foundational concepts is key, and if you're new to the broader AI ecosystem, a structured learning path like the one in Uncodemy's AI development course can provide the comprehensive background to excel.
First, you'll need to install the necessary libraries. You'll also need to set up API keys for your chosen LLM and search tool (we'll use Tavily for this example).
Bash
Copy Code
pip install langgraph langchain langchain_openai tavily-python
Python
Copy Code
import os os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_API_KEY" os.environ["TAVILY_API_KEY"] = “YOUR_TAVILY_API_KEY”
Our agent needs to keep track of a few things: the original question, the documents it finds, the final answer, and how many times it has tried.
Python
Copy Code
from typing import TypedDict, List class GraphState(TypedDict): question: str generation: str documents: List[str]
We need three primary functions to act as our nodes: one to retrieve documents, one to generate an answer, and one to grade the retrieved documents.
Python
Copy Code
from langchain_community.tools.tavily_search import TavilySearchResults from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser # Initialize our tools and models retriever = TavilySearchResults(max_results=3) llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)
# 1. Retrieve Node
Copy Code
def retrieve_documents(state):
print("---RETRIEVING DOCUMENTS---")
question = state["question"]
documents = retriever.invoke({"query": question})
return {"documents": documents, "question": question}# 2. Generate Node
Copy Code
def generate_answer(state):
print("---GENERATING ANSWER---")
question = state["question"]
documents = state["documents"]
prompt = ChatPromptTemplate.from_template(
"""You are an assistant for question-answering tasks.
Use the following retrieved context to answer the question.
If you don't know the answer, just say that you don't know.
Question: {question}
Context: {context}
Answer:"""
)
rag_chain = prompt | llm | StrOutputParser()
generation = rag_chain.invoke({"context": documents, "question": question})
return {"generation": generation}# 3. Grader Node
Copy Code
def grade_documents(state):
print("---CHECKING DOCUMENT RELEVANCE---")
question = state["question"]
documents = state["documents"]
prompt = ChatPromptTemplate.from_template(
"""You are a grader assessing relevance of a retrieved document to a user question.
If the document contains keywords related to the user question, grade it as relevant.
It does not need to be a stringent test. The goal is to filter out erroneous retrievals.
Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question.
Retrieved Document:
\n\n {document} \n\n
User Question: {question} \n
grade:
"""
)
grader_chain = prompt | llm | StrOutputParser()
# We'll check each document. If any are irrelevant, we'll retry.
filtered_docs = []
for d in documents:
score = grader_chain.invoke({"question": question, "document": d['content']})
grade = score.strip().lower()
if grade == "yes":
filtered_docs.append(d)
if len(filtered_docs) == 0:
# All documents were irrelevant
print("---DECISION: DOCUMENTS ARE NOT RELEVANT, RETRYING---")
return {"documents": [], "decision": "retry"}
else:
print("---DECISION: DOCUMENTS ARE RELEVANT, PROCEEDING TO GENERATION---")
return {"documents": filtered_docs, "decision": "generate"}Now, let's define the graph structure, add our nodes, and set up the crucial conditional edge.
Python
Copy Code
from langgraph.graph import StateGraph, END
# Define the workflow
workflow = StateGraph(GraphState)
# Add the nodes
workflow.add_node("retrieve", retrieve_documents)
workflow.add_node("grade_documents", grade_documents)
workflow.add_node("generate", generate_answer)
# Define the conditional edge
def decide_to_generate(state):
if state["decision"] == "generate":
return "generate"
else:
return "retrieve"
# Build the graph
workflow.set_entry_point("retrieve")
workflow.add_edge("retrieve", "grade_documents")
workflow.add_conditional_edges(
"grade_documents",
decide_to_generate,
{
"generate": "generate",
"retry": "retrieve",
}
)
workflow.add_edge("generate", END)
# Compile the graph into a runnable object
app = workflow.compile()One of the best features of LangGraph is its built-in visualization. You can see the exact structure you just created.
Python
Copy Code
# To get a visual representation of the graph
# Requires `pip install pygraphviz`
# You can save this to a file and view it
image_data = app.get_graph().draw_mermaid_png()
with open("workflow.png", "wb") as f:
f.write(image_data)This image will show "retrieve" as the entry point, leading to "grade_documents," which then branches either to "generate" (and then END) or back to "retrieve," creating our self-correcting loop.
Now, let's run it with an input.
Python
Copy Code
inputs = {"question": "What are the main health benefits of regular exercise?"}
for output in app.stream(inputs):
for key, value in output.items():
print(f"Node '{key}':")
print("---")
print(value)
print("\n---\n")You will see the output trace the steps: retrieving, grading, and then, if the documents are good, generating the final answer. If you were to give it a very ambiguous query that returns poor results, you would see it loop back to retrieve again.
Choosing the right tool is key. While you could build everything in LangGraph, it's often overkill.
LangGraph isn’t just another library—it’s a complete shift in how we think about building AI applications. Instead of sticking to rigid, step-by-step processes, it opens the door to flexible, intelligent, and autonomous systems that can reason, plan, and even correct themselves.
With its powerful framework for managing state and control flow, LangGraph gives developers the tools to create the next generation of AI agents—ones capable of handling complex, multi-layered problems like never before.
Whether you’re an experienced AI engineer or just beginning your journey in the field, learning and mastering LangGraph is an essential move toward shaping the future of intelligent technology.
Personalized learning paths with interactive materials and progress tracking for optimal learning experience.
Explore LMSCreate professional, ATS-optimized resumes tailored for tech roles with intelligent suggestions.
Build ResumeDetailed analysis of how your resume performs in Applicant Tracking Systems with actionable insights.
Check ResumeAI analyzes your code for efficiency, best practices, and bugs with instant feedback.
Try Code ReviewPractice coding in 20+ languages with our cloud-based compiler that works on any device.
Start Coding
TRENDING
BESTSELLER
BESTSELLER
TRENDING
HOT
BESTSELLER
HOT
BESTSELLER
BESTSELLER
HOT
POPULAR