Articles

LangGraph Tutorial: Complete Guide to Building AI Workflows

LangGraph is a powerful Python library that simplifies creating, managing, and visualizing complex AI workflows. Built on the popular LangChain framework, LangGraph makes it straightforward to handle stateful workflows, conditional logic, loops, and multistep interactions.

Think of LangGraph as a visual flowchart builder for AI logic. LangGraph helps you see how data moves through your application, making it simple to manage and debug.

Key characteristics of LangGraph

  • Visual: Visualize complex AI workflows as intuitive graphs.
  • Stateful: Maintain state information easily across multiple workflow steps.
  • Conditional: Create flexible workflows with conditional branching and loops.
  • User-friendly: Build sophisticated applications without messy, nested logic.

Let’s dive deeper and discover how LangGraph works!

  • Understand AI agents from the ground up in this beginner-friendly course covering autonomous systems and agentic workflows.
    • Beginner Friendly.
      < 1 hour
  • Learn to build AI chatbots and agents with Flowise's no-code platform—no programming required. Perfect for business professionals.
    • Beginner Friendly.
      1 hour

Installing LangGraph locally

Getting started with LangGraph is straightforward. All you need to do to install LangGraph is use pip.

pip install langgraph

That’s it! We’re ready to build our first workflow.

Creating our first workflow

LangGraph allows us to define workflows as graphs, where each function (called a “node”) performs a task and passes state to the next. This example walks you through building a simple workflow that prints a welcome message and a question using LangGraph.

Here is the step-by-step breakdown of the process:

Step 1: Defining the state and node functions

First, we need to define the state of our graph. The state is a Python object (typically a dictionary) that gets passed between nodes. We must define its structure upfront using TypedDict.

Each node is a Python function that accepts the state object and returns a dictionary with the modifications to that state.

In your main.py, start by writing the following code:

from typing import TypedDict
from langgraph.graph import StateGraph, END
# Define the structure of our state
class GraphState(TypedDict):
"""
Represents the state of our graph.
Attributes:
message: The welcome message.
question: The follow-up question.
"""
message: str
question: str
# Define the node functions
def welcome(state: GraphState) -> dict:
"""Adds a welcome message to the state."""
state["message"] = "Welcome to LangGraph!"
return state
def question(state: GraphState) -> dict:
"""Adds a follow-up message to the state."""
state["question"] = "How can I help you today?"
return state
def display(state: GraphState) -> dict:
"""Retrieves messages and prints them to the console."""
print(state["message"])
print(state["question"])
return {} # This node doesn't modify the state

Here’s what each part does:

  • GraphState defines that our state dictionary will contain string keys named message and question.
  • welcome(state) adds a welcome message to the state.
  • question(state) adds a follow-up message to the state.
  • display(state) retrieves both and prints them to the console.

Step 2: Initializing the graph and adding nodes

Now, we create a StateGraph instance, passing our GraphState definition to its constructor. Then, we add our functions as named nodes.

# The graph needs to know what the state schema is
graph = StateGraph(GraphState)
# Add the three functions as named nodes
graph.add_node("welcome", welcome)
graph.add_node("question", question)
graph.add_node("display", display)

Each node is given a string label (e.g., “welcome”) and the corresponding function.

Step 3: Defining the execution order with edges

Use set_entry_point() to define the first node to run and add_edge() to specify the flow between nodes.

graph.set_entry_point("welcome")
graph.add_edge("welcome", "question")
graph.add_edge("question", "display")
graph.add_edge("display", END)

Here’s the explanation for each line:

  • The workflow will start at the welcome node.
  • After welcome finishes, control moves to question.
  • After question, control moves to display.
  • END is a special keyword that signals the completion of the workflow.

Step 4: Compile and run the workflow

Finally, compile the graph into a runnable application and invoke it with an initial empty state.

# This creates the runnable app
app = graph.compile()
# Run the app with an empty initial state
app.invoke({})

This will trigger the full sequence, and you will see the expected output:

Welcome to LangGraph!
How can I help you today?

And just like that, you’ve created a simple, clear, and functional workflow. Not only that, but we can also use LangGraph to build more complex workflows, as shown below.

How to manage complex workflows?

LangGraph shines brightest when handling conditional logic. You can easily create branches in your workflow that execute based on the current state.

Let’s imagine this scenario: Your application needs to respond differently based on a user’s query.

First, we define the state and the functions. The key here is a node (check_query) that returns a decision that LangGraph can use to route to the next step.

Next, we set up the conditional workflow in a single, runnable script:

from typing import TypedDict
from langgraph.graph import StateGraph, END
# Define the state for this conditional graph
class ConditionalState(TypedDict):
input: str # User's query
next: str # The next node to route to
# Define the functions
def check_query(state: ConditionalState) -> dict:
"""Checks the query and returns a routing decision."""
query = state.get("input", "").lower()
if "pricing" in query:
return {"next": "pricing"}
else:
return {"next": "general"}
def pricing_info(state: ConditionalState) -> dict:
"""Provides pricing information."""
print("Here’s detailed pricing information.")
return {}
def general_info(state: ConditionalState) -> dict:
"""Provides general information."""
print("Here’s some general information.")
return {}
# Set up the graph
graph = StateGraph(ConditionalState)
graph.add_node("check", check_query)
graph.add_node("pricing", pricing_info)
graph.add_node("general", general_info)
# Set the entry point and the conditional edges
graph.set_entry_point("check")
graph.add_conditional_edges(
"check", # The source node for the decision
lambda state: state["next"], # A function to extract the routing key from the state
{
# A map of routing keys to destination nodes
"pricing": "pricing",
"general": "general"
}
)
# Add edges from the final nodes to the end
graph.add_edge("pricing", END)
graph.add_edge("general", END)
# Compile and run
app = graph.compile()
app.invoke({"input": "I need to know about your pricing plans."})

When you run this code, the check_query node will see the word “pricing” in the input and update the state’s next value to "pricing". The add_conditional_edges logic will then route the workflow to the pricing_info node.

Output:

Here’s detailed pricing information.

LangGraph simplifies complex branching logic into a clean and natural workflow. Let’s explore why we should consider using LangGraph.

Why consider using LangGraph?

While LangChain helps you build AI chains, LangGraph takes workflow management to another level by:

  • Visualizing how each part of your AI logic connects.
  • Managing complex branching and decision-making tasks effortlessly.
  • Handling state and memory so your AI remembers essential information throughout the workflow.

This means you spend less time debugging logic and more time enhancing your AI’s capabilities. Let’s look at the key components of LangGraph next.

Key components of LangGraph

LangGraph operates using these simple yet powerful building blocks:

  • Nodes: Individual actions or tasks your AI performs, such as asking a question or processing input.
  • Edges: The connections between nodes that define your workflow’s sequence and logic.
  • States: The data retained between steps, ensuring your AI remembers context. You must define the schema for this state.
  • Conditional Logic: Decision-making branches based on real-time conditions or user input.

Together, these components form dynamic, interactive, and intelligent workflows.

Real-world applications of LangGraph

LangGraph isn’t just theoretical. It’s powering real-world use cases like:

  • AI Assistants: Intelligent virtual assistants with conversational memory.
  • Research Agents: Agents that search, summarize, and remember data.
  • Customer Support: Smart agents that resolve queries intelligently and autonomously.

LangGraph simplifies managing these complex tasks, making AI practical and accessible.

Conclusion

In this guide, we explored how to use LangGraph to easily build, visualize, and manage complex AI workflows—from simple setups and conditional branching to complete multistep research agents. We covered installing dependencies, defining states, setting up nodes, and structuring your workflows using LangGraph’s graph-based approach.

Additionally, we discussed practical, real-world applications where LangGraph shines, such as virtual assistants, intelligent research agents, and smart customer-support bots, demonstrating how LangGraph simplifies complex AI tasks.

For a deeper dive, explore our Creating AI Applications using Retrieval-Augmented Generation (RAG) course to enhance AI with external knowledge sources.

Frequently asked questions

1. What is LangGraph used for?

LangGraph simplifies building and managing complex, stateful AI workflows, representing them as clear, visual graphs.

2. How do you visualize workflows in LangGraph?

LangGraph has built-in visualization features that can generate graphical representations of your workflows (e.g., as PNG images), simplifying debugging and management.

3. What is the difference between LangGraph and LangChain?

LangChain provides the core components (LLMs, tools, etc.), while LangGraph is a library for orchestrating these components into robust, agent-like loops and graphs with cycles and state.

4. Is LangGraph suitable for production use?

Absolutely! LangGraph’s clarity, scalability, and maintainability make it ideal for building and deploying complex AI applications in production environments.

5. What is the purpose of state in LangGraph?

State allows the workflow to retain essential information across different steps. It’s the memory of your graph, ensuring continuity and context for long-running tasks.

6. What is the purpose of TypedDict in LangGraph?

Using TypedDict to define the state schema enforces a clear data structure, enhancing code readability, enabling static analysis, and reducing potential errors by ensuring nodes access and modify the state consistently.

Codecademy Team

'The Codecademy Team, composed of experienced educators and tech experts, is dedicated to making tech skills accessible to all. We empower learners worldwide with expert-reviewed content that develops and enhances the technical skills needed to advance and succeed in their careers.'

Meet the full team

Learn more on Codecademy

  • Understand AI agents from the ground up in this beginner-friendly course covering autonomous systems and agentic workflows.
    • Beginner Friendly.
      < 1 hour
  • Learn to build AI chatbots and agents with Flowise's no-code platform—no programming required. Perfect for business professionals.
    • Beginner Friendly.
      1 hour
  • Ready to learn how to use AI for coding? Learn how to use generative AI tools like ChatGPT to generate code and expedite your development.
    • Beginner Friendly.
      1 hour