LangGraph Explained

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.

LangGraph Explained

Visualizing AI Workflows Step by Step

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.

Why We Need to Go Beyond Linear Chains

Before diving into LangGraph, it's crucial to understand the limitations it addresses. Standard LangChain chains are fantastic for tasks like:

  • Simple RAG (Retrieval-Augmented Generation): Fetch documents -> Pass to LLM -> Get answer.
  • Summarization: Get text -> Pass to LLM -> Get summary.
  • Extraction: Get text -> Pass to LLM with function-calling -> Get structured data.

These are one-way streets. The data flows in a single direction without loops. But consider these more complex scenarios:

  • Multi-Step Research Agent: An agent that searches the web, realizes its initial query was too broad, and refines the query to search again. This requires a loop.
  • Human-in-the-Loop Workflows: A content generation tool that writes a draft, then pauses and waits for human approval before proceeding to publish it. This requires the system to stop and resume.
  • Multi-Agent Collaboration: A "team" of AI agents (e.g., a Planner, a Researcher, and a Writer) that pass tasks back and forth, potentially revising work based on feedback from one another. This is a complex web of interactions, not a straight line.

These applications require state (a memory of what has happened) and cycles (the ability to loop or go back). This is where LangGraph shines.

The Core Concepts of LangGraph

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:

1. The State (The Graph's Memory)

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.

  • Analogy: Think of the state as a shared whiteboard. Each worker who comes to the board can see everything written on it, erase parts, and add new information for the next worker.

2. Nodes (The Workers)

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:

  • A function that calls an external tool (e.g., a web search API).
  • An LLM call to generate text or analyze data.
  • A function that formats data or prepares it for another step.

3. Edges (The Pathways)

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.

4. Conditional Edges (The Decision-Makers)

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.

  • Example: A conditional edge could check the state for a field called search_results.
    • If search_results are relevant, it directs the graph to the "Generate Answer" node.
    • If search_results are irrelevant, it directs the graph back to the "Refine Query" node, creating a loop.

This ability to route an application's flow based on its own intermediate results is the key to building autonomous and intelligent agents.

Step-by-Step: Building a Self-Correcting Research Agent

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.

Step 1: Setting Up Your Environment

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”

Step 2: Define the State

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]

Step 3: Define the Nodes

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"}

Step 4: Wire It All Together with LangGraph

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()

Step 5: Visualize and Run!

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.

LangGraph vs. LCEL: When to Use Which?

Choosing the right tool is key. While you could build everything in LangGraph, it's often overkill.

  • Use LCEL when: Your workflow is a straightforward, predictable sequence of steps. It's perfect for data processing pipelines and simple RAG applications. It's the clean, efficient, and direct path.
  • Use LangGraph when: You need cycles, state, and complex conditional logic. It's the tool for building agents, applications with human-in-the-loop components, and any process that requires dynamic routing based on intermediate results. This is essential for anyone looking to move from basic scripting to building truly intelligent systems. For those serious about this transition, diving deep into advanced frameworks is a must, and Uncodemy's courses provide a structured environment to master these cutting-edge skills.

Conclusion : 

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.

Placed Students

Our Clients

Partners

...

Uncodemy Learning Platform

Uncodemy Free Premium Features

Popular Courses