LangGraph Tutorial 2026: Complete Python Guide for Building AI Agents from Scratch
LangGraph Tutorial 2026: Complete Python Guide for Building AI Agents from Scratch
Are you ready to build smart AI agents that can think, act, and even decide what to do next? Imagine creating a digital helper that can research topics, answer complex questions, or even write stories, all by itself. This langgraph tutorial 2026 python guide is your starting point for this exciting journey. We’ll explore how LangGraph helps you create these intelligent systems using Python, step by step.
In this comprehensive guide, you will learn everything from setting up your environment to building powerful AI agents. By the end, you’ll have a solid understanding of how to use LangGraph to make your AI dreams a reality. Get ready to dive into the future of AI agent development.
What is LangGraph? Understanding the Basics
LangGraph is a super cool tool that helps you build AI agents with a plan. Think of it like a choose-your-own-adventure book for your AI. Each page is a step your AI can take, and the choices you make lead to different pages. This structure lets your AI decide its next move based on what’s happening.
It’s built on top of LangChain, adding even more control and flexibility. With LangGraph, you can create agents that remember things, make decisions, and even go back and try a different path if something doesn’t work out. It’s perfect for creating complex AI workflows.
LangGraph vs. LangChain: Why Choose LangGraph for AI Agents?
You might have heard about LangChain, which is fantastic for building applications with large language models (LLMs). LangChain helps you connect different AI tools, like telling an AI model to use a search engine or a calculator. It provides a great toolkit for many AI tasks.
LangGraph takes that power and adds a super important feature: stateful, multi-actor applications. This means your AI agent can have a memory and can make ongoing decisions. LangChain gives you the tools, but LangGraph gives you the blueprint to build truly interactive and adaptive agents. For a deep dive into building agents, this langgraph tutorial 2026 python focuses on the unique capabilities of LangGraph.
When you use LangGraph, you are explicitly drawing out the steps and decisions your agent will make. This level of control is crucial for building robust AI agents that can handle complex, multi-step tasks. It allows for clearer logic and easier debugging compared to more linear LangChain chains for certain types of problems. You can think of LangChain as a toolbox and LangGraph as a sophisticated assembly line built using that toolbox.
Setting Up Your Python Environment for LangGraph Tutorial 2026 Python
Before we start building amazing AI agents, we need to get our Python environment ready. Think of this as preparing your workshop with all the necessary tools. A clean setup ensures everything runs smoothly for your langgraph tutorial 2026 python projects.
Creating a Virtual Environment
It’s always a good idea to create a virtual environment for your Python projects. This keeps your project’s dependencies separate from other projects on your computer. It prevents conflicts and makes managing packages much easier.
First, open your terminal or command prompt. Then, navigate to the folder where you want to create your project. Once there, you can create a virtual environment using this command.
1
python -m venv langgraph_env
This command creates a new folder named langgraph_env which contains a fresh Python installation. You can choose any name you like instead of langgraph_env. It’s a clean slate for your project.
Activating Your Virtual Environment
After creating the environment, you need to “activate” it. Activating the environment means that any Python commands you run will use the packages installed inside langgraph_env. The way you activate it depends on your operating system.
For macOS and Linux:
1
source langgraph_env/bin/activate
For Windows (PowerShell):
1
.\langgraph_env\Scripts\Activate.ps1
For Windows (Command Prompt):
1
langgraph_env\Scripts\activate.bat
You’ll know it’s active when you see (langgraph_env) at the beginning of your terminal prompt. Now, all our installations will go directly into this isolated environment. This setup is crucial for any serious langgraph tutorial 2026 python development.
Installing Essential Packages
With your virtual environment active, it’s time to install the necessary Python packages. We’ll need langgraph, langchain-community (for some basic tools and LLM integrations), and a package for a Large Language Model (LLM) like openai. If you plan to use a different LLM, you’ll install its specific package instead.
Run the following command in your activated terminal:
1
pip install langgraph langchain_community openai
This command downloads and installs LangGraph, the LangChain community package, and the OpenAI library. These three are the core components you’ll need for most AI agent development in this langgraph tutorial 2026 python. Ensure your internet connection is stable, as these packages can be quite large.
Setting Up API Keys (If Using OpenAI)
If you’re using OpenAI’s models, you’ll need an API key. This key is like a secret password that allows your code to talk to OpenAI’s services. Never share your API key with anyone or embed it directly in your code.
The safest way to handle API keys is to store them as environment variables. You can set it in your terminal before running your script.
For macOS and Linux:
1
export OPENAI_API_KEY="your_openai_api_key_here"
For Windows (Command Prompt):
1
set OPENAI_API_KEY="your_openai_api_key_here"
For Windows (PowerShell):
1
$env:OPENAI_API_KEY="your_openai_api_key_here"
Replace "your_openai_api_key_here" with your actual OpenAI API key. You can get an API key from the OpenAI website after creating an account. This setup makes sure your key is available to your Python scripts without being written into the code itself, which is a good security practice for any langgraph tutorial 2026 python project.
Verifying Your Setup
To make sure everything is installed correctly, you can run a quick Python script. Create a file named check_setup.py and add the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import langgraph
import langchain_community
import openai
import os
print(f"LangGraph version: {langgraph.__version__}")
print(f"LangChain Community version: {langchain_community.__version__}")
print(f"OpenAI version: {openai.__version__}")
if os.getenv("OPENAI_API_KEY"):
print("OPENAI_API_KEY is set!")
else:
print("WARNING: OPENAI_API_KEY is NOT set. Please set it as an environment variable.")
print("Setup verification complete!")
Save the file and run it from your activated virtual environment:
1
python check_setup.py
You should see the versions of the installed packages and a confirmation that your API key is set. If you encounter any errors, double-check your installation steps. This quick check ensures your environment is perfectly prepared for the rest of our langgraph tutorial 2026 python journey.
Building Blocks of LangGraph: Nodes and Edges Basics
At the heart of LangGraph are two main ideas: nodes and edges. Think of nodes as the “action steps” your AI agent can take, and edges as the “paths” that connect these steps. Understanding these basics is crucial for building any kind of AI agent with LangGraph.
What are Nodes?
Nodes are like the individual workers in your AI factory. Each node does one specific job. For example, one node might call an AI model, another might search the internet, and a third might summarize information. Nodes are essentially Python functions that take some input and produce an output.
In LangGraph, you define what each node does. It’s a piece of code that your AI agent will execute when it reaches that point in its “plan.” For this langgraph tutorial 2026 python, we’ll start with simple nodes that just print messages or perform small calculations.
Here’s an example of a simple node function:
1
2
3
4
5
6
7
8
9
def say_hello(state):
print("Hello from the 'say_hello' node!")
return {"output_message": "Hello!"}
def analyze_input(state):
user_input = state.get("user_query", "No query provided.")
print(f"Analyzing input: {user_input}")
analysis = f"Input received: '{user_input}'. Seems like a simple request."
return {"analysis_result": analysis}
Each node function receives the current state of the graph as input and returns a dictionary to update that state. The state is like a shared blackboard where all nodes can read and write information.
What are Edges?
Edges are the connections between your nodes. They define the flow of your AI agent’s logic. An edge tells the graph, “After node A finishes its job, go to node B.” Edges can be simple, meaning they always go to the next node. They can also be conditional, meaning they choose the next node based on some decision.
Think of edges as the arrows on a flowchart. They direct the path of execution. This is where your AI agent’s “thinking” really comes into play, as it decides which path to take. We’ll explore conditional edges later in this langgraph tutorial 2026 python.
For now, let’s consider a simple, unconditional edge. After say_hello runs, we might want to go to analyze_input. LangGraph lets you define these connections easily.
The Graph State: Remembering Information
For your AI agent to be smart, it needs to remember things as it moves from node to node. This “memory” is called the graph’s State. The State is a dictionary or a custom object that holds all the information relevant to the current conversation or task. Each node can read from and write to this State.
For example, if one node searches for information, it can save the search results into the State. A later node can then read those results to summarize them. This shared State is how information flows through your LangGraph. For a more detailed look at state management, see our upcoming section.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from typing import TypedDict, Annotated, List
import operator
class AgentState(TypedDict):
"""
Represents the state of our graph.
Attributes:
user_query: The initial query from the user.
output_message: A message generated by a node.
analysis_result: The result of an analysis step.
chat_history: A list of messages in the conversation.
tool_results: List of results from tool calls.
"""
user_query: str
output_message: Annotated[str, operator.add]
analysis_result: str
chat_history: Annotated[List[str], operator.add]
tool_results: Annotated[List[str], operator.add]
This AgentState is a blueprint for the information our graph will carry. TypedDict helps us define what kind of data each piece of information holds. Annotated with operator.add means that when a node returns a value for output_message or chat_history, it will be added to the existing list or string, instead of replacing it. This is a very powerful feature for managing dynamic state.
Your First LangGraph: A Simple Agent
Now that you understand nodes and edges, let’s build your very first LangGraph. This example will be simple, but it will show you the basic steps of creating a graph, adding nodes, and connecting them. This is the core of any langgraph tutorial 2026 python project.
We’ll create a graph that takes a user’s question, processes it, and then provides a simple response. This sequential flow is a great way to grasp the fundamentals.
1. Defining the Graph State
First, let’s refine our AgentState for a simple agent. This will define what information our agent carries as it moves through its steps.
1
2
3
4
5
6
7
8
9
10
11
from typing import TypedDict, Annotated, List
import operator
from langgraph.graph import StateGraph, END
class SimpleAgentState(TypedDict):
"""
State for our simple AI agent.
"""
user_input: str
processed_message: Annotated[str, operator.add]
final_response: str
Here, user_input holds what the user initially asks. processed_message will accumulate any intermediate messages, and final_response will store the agent’s ultimate answer. Annotated[str, operator.add] means if a node returns a string for processed_message, it will be added to any existing processed_message, creating a combined string.
2. Creating Node Functions
Next, we’ll define a few simple Python functions that will act as our nodes. Remember, each node takes the current state as input and returns a dictionary to update that state.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def receive_input(state: SimpleAgentState) -> SimpleAgentState:
"""A node that simply receives and prints the user input."""
print(f"Node: 'receive_input' - User input received: {state['user_input']}")
# No changes to state needed here, or you could add a timestamp etc.
return {"processed_message": f"Input received: {state['user_input']}\n"}
def process_data(state: SimpleAgentState) -> SimpleAgentState:
"""A node that simulates processing the data."""
input_text = state['user_input']
processed_text = f"Processed '{input_text.upper()}' with some logic."
print(f"Node: 'process_data' - Processing: {input_text}")
return {"processed_message": f"Data processed: {processed_text}\n"}
def generate_response(state: SimpleAgentState) -> SimpleAgentState:
"""A node that generates a final response based on processed data."""
processed_msg = state['processed_message']
final_resp = f"Based on our steps: '{processed_msg.strip()}' -- Here is your final answer!"
print(f"Node: 'generate_response' - Generating final response.")
return {"final_response": final_resp, "processed_message": f"Response generated.\n"} # Append to processed_message
Each function is simple, but they represent distinct steps an AI agent might take. The print statements help us see the flow in this langgraph tutorial 2026 python.
3. Building the Graph Structure
Now, we put these nodes together using StateGraph. This is where we define the starting point, the connections, and the end point of our agent’s journey.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Create a new graph instance with our defined state
workflow = StateGraph(SimpleAgentState)
# Add nodes to the graph
workflow.add_node("input_receiver", receive_input)
workflow.add_node("data_processor", process_data)
workflow.add_node("response_generator", generate_response)
# Set the entry point of the graph
workflow.set_entry_point("input_receiver")
# Define the edges (connections between nodes)
# After 'input_receiver', always go to 'data_processor'
workflow.add_edge("input_receiver", "data_processor")
# After 'data_processor', always go to 'response_generator'
workflow.add_edge("data_processor", "response_generator")
# Set the end point of the graph
workflow.add_edge("response_generator", END) # The END special node means the graph finishes here
In this code, workflow.add_node() registers our functions as nodes in the graph. workflow.set_entry_point() tells the graph where to begin. workflow.add_edge() draws the connections. END is a special LangGraph marker that signifies the end of the execution.
4. Compiling and Running Your First Graph
With the nodes and edges defined, the last step is to compile the graph. Compiling turns our blueprint into a runnable agent. Then, we can invoke it with some input.
1
2
3
4
5
6
7
8
9
10
11
# Compile the graph
app = workflow.compile()
# Run the graph with some input
initial_state = {"user_input": "Tell me about the weather today."}
final_state = app.invoke(initial_state)
print("\n--- Final State ---")
print(f"User Input: {final_state['user_input']}")
print(f"Processed Messages: {final_state['processed_message']}")
print(f"Final Response: {final_state['final_response']}")
When you run this code, you’ll see the print statements from each node showing the execution flow. The final_state will contain all the information gathered and modified by the nodes. This demonstrates a complete, albeit simple, agent workflow using this langgraph tutorial 2026 python.
This simple agent illustrates how information flows through the StateGraph. Each node performs its task, updates the shared state, and the graph moves to the next connected node. This foundational understanding is key to building more complex agents. You can imagine swapping out process_data with a real LLM call or generate_response with a tool use. For more on integrating LLMs, you might find our-other-blog-post-on-llm-integration.md helpful.
State Management Fundamentals in LangGraph
One of the most powerful features of LangGraph, especially for AI agents, is its robust state management. Your agent isn’t just a series of disconnected steps; it remembers what happened before and uses that information to make future decisions. This ‘memory’ is crucial for multi-step conversations and complex tasks. This section of our langgraph tutorial 2026 python dives deep into how this works.
What is Graph State?
As we briefly touched upon, the “Graph State” is the single source of truth for your agent. It’s a collection of all the information your agent needs at any given moment. Every node in your graph can read from this state and, importantly, update it. When a node finishes, it returns a dictionary that represents how it wants to change the current state. LangGraph then merges these changes into the main state.
Defining Your Custom State with TypedDict and Annotated
To make state management clear and error-proof, LangGraph encourages you to define your state explicitly. We use Python’s TypedDict to create a blueprint for our state. This is like creating a form that your agent fills out. Each field in the TypedDict represents a piece of information your agent remembers.
The Annotated type hint, especially with operator.add, is a game-changer. It tells LangGraph how to combine updates for a specific field.
operator.addfor lists: If a node returns{"messages": ["new message"]}, and the current state has{"messages": ["old message"]}, usingAnnotated[List[str], operator.add]will result in{"messages": ["old message", "new message"]}. This is perfect for building a chat history.operator.addfor strings: Similarly, for strings, it will concatenate them. If a node returns{"output_text": "part 2"}, and the state has{"output_text": "part 1"}, it becomes{"output_text": "part 1part 2"}.
Let’s look at a more complex AgentState that could be used for a research agent:
1
2
3
4
5
6
7
8
9
10
class ResearchAgentState(TypedDict):
"""
Represents the state of our research agent.
"""
user_query: str # The initial query from the user
search_results: Annotated[List[str], operator.add] # Accumulates search results
analysis_report: Annotated[str, operator.add] # Accumulates parts of an analysis
current_topic: str # The current sub-topic being researched
steps_taken: Annotated[List[str], operator.add] # Tracks the agent's actions
tool_errors: Annotated[List[str], operator.add] # Records any errors during tool use
In this ResearchAgentState:
user_queryis a simple string.search_resultsis a list of strings that will grow as the agent performs multiple searches.analysis_reportwill accumulate text as different nodes contribute to the report.current_topicmight be updated by a planning node.steps_takenis a list that tracks the agent’s journey.tool_errorswill collect any issues encountered.
How Nodes Update the State
When a node function runs, it receives the current state. It can read any information it needs from state. Then, when it’s done, it returns a dictionary. This dictionary contains only the parts of the state that the node wants to change.
LangGraph then intelligently merges this returned dictionary with the existing state, respecting the Annotated merge behavior.
Let’s illustrate with a search_node:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from langchain_community.tools import DuckDuckGoSearchRun
search_tool = DuckDuckGoSearchRun()
def search_node(state: ResearchAgentState) -> ResearchAgentState:
"""
A node that performs a web search based on the current topic.
"""
current_topic = state.get("current_topic", state["user_query"])
print(f"Node: 'search_node' - Searching for: {current_topic}")
try:
results = search_tool.run(current_topic)
# Assuming results is a string, we might want to split it or process it
# For simplicity, let's treat it as one result for now.
search_list = [results]
return {"search_results": search_list, "steps_taken": ["Performed web search."]}
except Exception as e:
error_msg = f"Error during search: {e}"
print(error_msg)
return {"tool_errors": [error_msg], "steps_taken": ["Attempted web search, got error."]}
def analyze_node(state: ResearchAgentState) -> ResearchAgentState:
"""
A node that analyzes the search results.
(In a real agent, this would involve an LLM)
"""
results = state["search_results"]
if not results:
analysis = "No search results to analyze."
else:
# Simulate LLM analysis
analysis = f"Found {len(results)} search snippet(s). Key info: {results[0][:100]}..."
print(f"Node: 'analyze_node' - Analyzing search results.")
return {"analysis_report": f"Analysis: {analysis}\n", "steps_taken": ["Analyzed search results."]}
Notice how search_node returns {"search_results": search_list, "steps_taken": ["Performed web search."]}. If search_results was already ["old result"], after this node, it would become ["old result", "new result"] because of operator.add. The same applies to steps_taken. This automatic merging is a powerful feature for complex agents in any langgraph tutorial 2026 python.
Initializing and Inspecting State
When you start a graph using app.invoke(), you provide an initial state. This sets up the first pieces of information your agent needs.
1
2
3
# Initializing the graph with some input
initial_research_state = {"user_query": "Latest breakthroughs in AI explainability", "search_results": [], "analysis_report": "", "current_topic": "AI Explainability", "steps_taken": [], "tool_errors": []}
# (Later, you would invoke the compiled app with this state)
During debugging, you can always print the entire state object at the beginning or end of any node to see its contents. This is vital for understanding how information flows and changes.
State management is the backbone of intelligent agents. By carefully defining your state and how each node interacts with it, you empower your AI agent to maintain context, track progress, and make informed decisions across multiple steps. This advanced capability sets LangGraph apart for building sophisticated AI workflows, a core topic in this langgraph tutorial 2026 python.
Making Smart Decisions: Conditional Routing
AI agents need to be flexible and adapt to different situations. They can’t just follow a straight path every time. This is where “conditional routing” comes in. Conditional routing means your agent can choose its next step based on the current situation or information in its state. Think of it like a smart traffic controller for your AI. This is a crucial concept in any advanced langgraph tutorial 2026 python.
What is Conditional Routing?
Instead of an edge always going from Node A to Node B, a conditional edge first runs a special function. This function looks at the current state and decides which node to go to next. For example, if a search didn’t find results, the agent might go to a “rephrase query” node. If it did find results, it might go to an “analyze results” node.
This “decision-making” function is called a “router” or “conditional edge function.” It returns the name of the next node to execute.
Implementing a Conditional Edge
Let’s extend our simple agent with a conditional step. We’ll introduce a “decider” node that checks if a user’s input is a question or a statement.
1. Update the Graph State
First, we might add a field to our SimpleAgentState to store the decision.
1
2
3
4
5
class ConditionalAgentState(TypedDict):
user_input: str
processed_message: Annotated[str, operator.add]
final_response: str
decision: str # To store the outcome of the router
2. Create the Decision-Making Node (Router Function)
This is a special node that will determine the next step. It looks at the state and returns the name of the next node.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def decide_next_step(state: ConditionalAgentState) -> str:
"""
Decides whether to process as a question or a general statement.
"""
user_query = state['user_input'].lower()
print(f"Node: 'decide_next_step' - Evaluating input: '{user_query}'")
if "?" in user_query:
print("Decision: Input is a question. Going to 'answer_question'.")
return "answer_question"
else:
print("Decision: Input is a statement. Going to 'handle_statement'.")
return "handle_statement"
def answer_question_node(state: ConditionalAgentState) -> ConditionalAgentState:
"""Node to handle questions."""
question = state['user_input']
response = f"Agent processing question: '{question}'. Finding an answer..."
print(f"Node: 'answer_question_node' - {response}")
return {"processed_message": f"Question handled: {response}\n", "final_response": response}
def handle_statement_node(state: ConditionalAgentState) -> ConditionalAgentState:
"""Node to handle general statements."""
statement = state['user_input']
response = f"Agent received statement: '{statement}'. Acknowledging..."
print(f"Node: 'handle_statement_node' - {response}")
return {"processed_message": f"Statement handled: {response}\n", "final_response": response}
The decide_next_step function is not a regular node; it’s a “conditional edge” function. It just returns a string representing the next node’s name.
3. Building the Graph with Conditional Edges
Now, we’ll build the graph, adding our new nodes and, most importantly, the conditional edge.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from langgraph.graph import StateGraph, END
# Create a new graph instance with our conditional state
conditional_workflow = StateGraph(ConditionalAgentState)
# Add all the necessary nodes
conditional_workflow.add_node("input_receiver", receive_input) # Re-using our receive_input from before
conditional_workflow.add_node("decider", lambda state: {"decision": decide_next_step(state)}) # The decider itself is often a node, but its return value decides the next edge
conditional_workflow.add_node("answer_question", answer_question_node)
conditional_workflow.add_node("handle_statement", handle_statement_node)
# Set the entry point
conditional_workflow.set_entry_point("input_receiver")
# Define initial sequential flow
conditional_workflow.add_edge("input_receiver", "decider")
# Define the conditional edge from 'decider'
# The `conditional_workflow.add_conditional_edges` method is powerful.
# It takes the source node, the function that decides the next step,
# and a mapping from decision outcomes to target nodes.
conditional_workflow.add_conditional_edges(
"decider",
decide_next_step, # This is the function that returns the next node name
{
"answer_question": "answer_question", # If decide_next_step returns "answer_question", go to answer_question node
"handle_statement": "handle_statement", # If decide_next_step returns "handle_statement", go to handle_statement node
}
)
# After handling the question or statement, both paths should lead to an end point
conditional_workflow.add_edge("answer_question", END)
conditional_workflow.add_edge("handle_statement", END)
In conditional_workflow.add_conditional_edges(), we pass our decide_next_step function. This function’s return value (e.g., “answer_question”) is then looked up in the dictionary {"answer_question": "answer_question", ...} to find the actual target node. This is how LangGraph dynamically routes the execution.
4. Running the Conditional Graph
Let’s test our conditional agent with both a question and a statement.
1
2
3
4
5
6
7
8
9
10
# Compile the conditional graph
conditional_app = conditional_workflow.compile()
print("--- Running with a Question ---")
question_state = conditional_app.invoke({"user_input": "What is the capital of France?"})
print(f"Final Response (Question): {question_state['final_response']}\n")
print("--- Running with a Statement ---")
statement_state = conditional_app.invoke({"user_input": "The sky is blue today."})
print(f"Final Response (Statement): {statement_state['final_response']}\n")
You will observe that for the question, the “answer_question” node executes, and for the statement, the “handle_statement” node executes. This demonstrates the power of conditional routing. By implementing conditional logic, your AI agents can perform different actions based on different inputs or internal states, making them much more intelligent and adaptable. This flexibility is what makes LangGraph so powerful for building complex AI agents in this langgraph tutorial 2026 python. You can chain these conditional routes to build very intricate decision-making processes.
Putting It All Together: Graph Compilation and Running
You’ve designed your agent’s brain with nodes and edges, and taught it how to make decisions. Now, it’s time to bring your creation to life! This section covers the final steps: compiling your graph and then running it to see your AI agent in action. This is the culmination of your efforts in this langgraph tutorial 2026 python.
Graph Compilation: From Blueprint to Engine
Once you have defined all your nodes, set the entry point, and added all the edges (both simple and conditional), your graph is like a detailed blueprint. To make it runnable, you need to “compile” it.
Compilation is the process where LangGraph takes your graph definition and turns it into an optimized, executable object. It essentially builds the internal machinery required to run your agent efficiently.
The compile() method is very straightforward:
1
2
# Assuming 'conditional_workflow' is your defined StateGraph from the previous section
app = conditional_workflow.compile()
The app object you get back is now a Runnable object. This means it behaves like any other LangChain Runnable, making it easy to integrate into larger LangChain applications or just run it directly. It’s the ready-to-go version of your AI agent.
Running Your Graphs: invoke() and stream()
There are a few ways to run your compiled graph, depending on your needs. The most common methods are invoke() and stream().
invoke(): Run Once, Get Final State
The invoke() method runs your graph from start to finish with a single initial input and returns the final state once all processing is complete. It’s like asking your agent a question and waiting for the complete answer.
You pass the initial state (a dictionary matching your TypedDict definition) to invoke().
1
2
3
4
5
6
7
8
# Example from our conditional agent
initial_input_for_invoke = {"user_input": "What is the weather like in Paris?"}
final_output_state = app.invoke(initial_input_for_invoke)
print("\n--- Output from invoke() ---")
print(f"Final User Input: {final_output_state['user_input']}")
print(f"Final Processed Message: {final_output_state['processed_message']}")
print(f"Final Response: {final_output_state['final_response']}")
invoke() is great for tasks where you only care about the end result. It’s simple to use and ideal for situations where the agent’s internal thought process isn’t needed by the user.
stream(): See Every Step as It Happens
Sometimes, you want to see your agent’s thought process unfold in real-time. This is where stream() comes in handy. stream() yields an update for each step (each node execution) in your graph. It’s like watching your agent think and work, node by node.
The stream() method returns a generator that you can iterate over. Each item yielded by the generator is a dictionary representing the state changes at that particular step.
1
2
3
4
5
6
7
8
9
10
11
print("\n--- Streaming output ---")
initial_input_for_stream = {"user_input": "Tell me a joke about AI."}
for s in app.stream(initial_input_for_stream):
print(f"Current state update: {s}")
# You can inspect specific parts of the state at each step if you wish
if "__end__" in s:
# This special key indicates the final state for the entire graph
final_state_from_stream = s["__end__"]
print(f"Final output from stream: {final_state_from_stream['final_response']}")
When you run this stream() example, you’ll see a dictionary printed for each node that executes, showing how the state changes over time. This is incredibly useful for debugging, understanding the agent’s flow, and providing real-time feedback to users in a chat interface. For a more detailed look at real-time updates, you might check out streaming-llm-responses-with-langchain.md.
Understanding the Output
Whether you use invoke() or stream(), the output always relates to your defined AgentState. Each update from stream() or the final output from invoke() will be a dictionary. This dictionary will contain the latest values for all the fields you defined in your TypedDict state.
This app object (the compiled graph) is now the core of your AI agent. You can integrate it into web applications, command-line tools, or other Python scripts. Mastering compilation and execution is essential for bringing your AI agents to life in any langgraph tutorial 2026 python.
Debugging Tips for LangGraph Tutorial 2026 Python
Even the smartest AI agents can sometimes get stuck or do unexpected things. Debugging is a crucial skill when building with LangGraph, just like with any programming project. Knowing how to find and fix issues quickly will save you a lot of time. This section provides practical debugging tips tailored for your langgraph tutorial 2026 python journey.
1. Use print() Statements Liberally
The simplest and often most effective debugging tool is the good old print() statement.
- Inside Nodes: Add
print()statements at the beginning and end of each node function. Print thestateit receives, any intermediate variables, and the dictionary it returns. This helps you trace the flow and see how the state changes at each step.1 2 3 4 5 6 7
def my_problematic_node(state: MyAgentState) -> MyAgentState: print(f"--- Entering my_problematic_node ---") print(f"State received: {state}") # ... your node logic ... new_value = "something_calculated" print(f"Intermediate calculation: {new_value}") return {"output_field": new_value}
- Router Functions: In your conditional routing functions, print the value that the router function returns. This confirms it’s making the correct decision.
1 2 3 4
def decide_next_step_debug(state: ConditionalAgentState) -> str: decision = "node_a" if "key_word" in state["user_input"] else "node_b" print(f"Router decision based on input: {state['user_input']} -> {decision}") return decision
2. Leverage stream() for Step-by-Step Inspection
As discussed, stream() is your best friend for understanding the execution flow. It allows you to see the state changes after every node execution.
1
2
3
4
5
6
7
for step_output in app.stream(initial_input):
print(f"\n--- Step Update ---")
for key, value in step_output.items():
# 'key' will be the node name, or '__end__' for the final state
print(f"Node: {key}")
# 'value' will be the state updates from that node
print(f"State changes: {value}")
By inspecting step_output in your loop, you can pinpoint exactly which node introduced an unexpected value or where the flow diverged from your expectations. This is invaluable for complex agents during this langgraph tutorial 2026 python.
3. Visualize Your Graph
LangGraph can generate a visual representation of your graph using mermaid syntax or even direct images if you have pygraphviz installed. This helps you quickly confirm that your nodes and edges are connected as you intended.
First, you might need to install graphviz system-wide and then pygraphviz if you want image output. For simply printing mermaid syntax:
1
2
3
4
5
6
7
8
9
10
11
12
# Assuming 'app' is your compiled graph
# To print Mermaid syntax
print(app.get_graph().draw_mermaid_ir())
# To draw as an image (requires graphviz and pygraphviz)
try:
from IPython.display import Image, display
display(Image(app.get_graph().draw_png()))
except ImportError:
print("Install pygraphviz and graphviz to draw images directly.")
print("Example mermaid graph (copy to an online mermaid editor like mermaid.live):")
print(app.get_graph().draw_mermaid_ir())
A visual representation makes it easy to spot missing edges, incorrect conditional routings, or unintended loops in your graph. This is a common first step for understanding a complex graph in any langgraph tutorial 2026 python.
4. Check Your AgentState Definition
A frequent source of errors is incorrect state management.
- Missing Fields: If a node tries to read a field that doesn’t exist in your
AgentState, you’ll get aKeyError. Ensure all fields are defined in yourTypedDict. - Incorrect
AnnotatedUsage: If you expect lists to append but they overwrite, or strings to concatenate but they replace, check yourAnnotateddefinitions. Make sureoperator.addis used where aggregation is desired. - Type Mismatches: Although Python is dynamically typed, LangGraph’s
TypedDicthelps. If a node returns anintfor a field expecting astr, it might lead to unexpected behavior later.
5. Isolate and Test Nodes Individually
If a specific node is causing problems, try running that node function by itself with a mock state dictionary. This isolates the logic and helps you determine if the issue is within the node itself or how it interacts with the rest of the graph.
1
2
3
4
# Mock state for testing a single node
mock_state = {"user_input": "Test query for node", "search_results": ["mock result 1"], "steps_taken": []}
result_from_node = analyze_node(mock_state) # Assuming analyze_node is a function from earlier
print(f"Result from isolated node test: {result_from_node}")
6. Use a Debugger (PDB, VS Code Debugger)
For more complex issues, using a full Python debugger like pdb or the integrated debugger in IDEs like VS Code can be invaluable. You can set breakpoints inside your node functions and step through the code line by line, inspecting variable values at each stage.
To use pdb in your script:
1
2
3
4
5
6
import pdb
def my_problematic_node(state: MyAgentState) -> MyAgentState:
pdb.set_trace() # Execution will pause here
# ... rest of your node code ...
return {"output_field": "value"}
Then run your script from the terminal. This provides much deeper insights than print() statements alone.
By following these debugging tips, you’ll be well-equipped to tackle any issues that arise during your langgraph tutorial 2026 python projects. Effective debugging is key to building robust and reliable AI agents.
Real-World Examples of AI Agents with LangGraph
You’ve learned the building blocks, state management, conditional routing, and how to run your graphs. Now, let’s look at how these concepts come together to build practical, real-world AI agents. These examples will illustrate the power and flexibility of LangGraph for complex tasks, bringing our langgraph tutorial 2026 python to practical application.
Example 1: A Research and Reporting Agent
Imagine an agent that can answer complex questions by performing web searches, analyzing results, and then summarizing them into a report. This agent needs to decide when to search, when to analyze, and when to stop.
Agent’s Goal: Answer a user’s question by searching the web and generating a concise report.
Key Components:
- State: Needs to store user query, search results (list), analysis snippets (string), and possibly a “should_continue” flag.
- Nodes:
plan_research: Takes user query, breaks it into search terms. (LLM call)web_search: Executes search based on terms, updatessearch_results. (Tool use: DuckDuckGoSearchRun)analyze_results: Readssearch_results, extracts key info, adds toanalysis_snippets. (LLM call)decide_next_step: Checks if enough information is gathered or if more searching/analysis is needed. (Conditional routing)generate_report: Compilesanalysis_snippetsinto a final report. (LLM call)
- Conditional Routing: After
analyze_results, decide if more searches are needed or if it’s time togenerate_report.
Simplified Workflow:
- Start:
user_queryis provided. plan_researchnode.web_searchnode.analyze_resultsnode.decide_next_step(conditional):- If more info needed: Go back to
web_search(perhaps with newcurrent_topic). - If done: Go to
generate_report.
- If more info needed: Go back to
generate_reportnode.- End.
This agent uses a loop enabled by conditional routing, allowing it to iterate through search and analysis until it’s satisfied. For further details on integrating LLMs with such a loop, you might refer to our blog post on creating-iterative-ai-agents-with-langgraph.md.
Example 2: Multi-Turn Customer Support Chatbot
A more interactive example is a chatbot that can handle customer queries, escalate if necessary, or provide information from a knowledge base. It needs to maintain conversation history.
Agent’s Goal: Respond to user queries, potentially using tools, and maintain context over multiple turns.
Key Components:
- State:
chat_history(list of messages),current_query,tool_output,escalation_neededflag. - Nodes:
llm_respond: Uses an LLM to generate a response based onchat_historyandcurrent_query.tool_router: Decides if a tool (like a knowledge base search or order status checker) is needed. (LLM call + conditional routing)run_tool: Executes the chosen tool.escalate_human: Marks the conversation for human intervention.
- Conditional Routing: After
llm_respond, check iftool_routerwants to use a tool or ifescalation_neededis true.
Simplified Workflow:
- Start:
user_inputenters. llm_respond(generates an initial thought/response).tool_router(conditional):- If tool needed: Go to
run_tool. - If escalation needed: Go to
escalate_human. - Otherwise: Go to
llm_respond(to refine response or end turn).
- If tool needed: Go to
- If
run_toolexecuted, loop back tollm_respondto incorporate tool results. - Loop continues until
llm_responddecides to end orescalate_humanis reached.
This agent demonstrates maintaining context (chat_history) and dynamically deciding between responding directly, using a tool, or escalating. Each turn can involve several steps within the graph.
Example 3: Code Generation and Refinement Assistant
An agent that helps developers write code, debug it, and refactor. This involves multiple steps of generation, execution, and error analysis.
Agent’s Goal: Generate correct and efficient Python code based on a natural language prompt.
Key Components:
- State:
user_request,generated_code,test_results,error_message,refinement_count. - Nodes:
generate_code: Takesuser_request, generates initial Python code. (LLM call)execute_code: Runs thegenerated_code, capturestest_results(stdout/stderr) anderror_message. (Tool use: Python interpreter)analyze_results: Checkstest_resultsfor success/failure, extracts errors. (LLM call)refine_code: If errors exist, uses LLM to modifygenerated_codebased onerror_message.decide_completion: Checks if code is correct, or ifrefinement_countexceeded. (Conditional routing)
- Conditional Routing: After
analyze_results, decide ifrefine_codeis needed, or if code is good, or if max refinements reached.
Simplified Workflow:
- Start:
user_requestfor code. generate_codenode.execute_codenode.analyze_resultsnode.decide_completion(conditional):- If code needs refinement (and
refinement_count< max): Go torefine_code, then loop back toexecute_code. - If code is correct: End (success).
- If
refinement_countmaxed out: End (failure/too many attempts).
- If code needs refinement (and
This example showcases how agents can use tools (code execution) and iteratively refine their outputs based on feedback. The loop is critical for achieving robust code generation. This iterative approach is a hallmark of sophisticated AI agents built with a langgraph tutorial 2026 python.
These real-world examples demonstrate that LangGraph is not just for simple sequential tasks. Its ability to manage state, create loops, and implement complex conditional logic makes it an incredibly powerful framework for building truly intelligent and adaptive AI agents for a wide range of applications.
Looking Ahead: The Future of AI Agents
You’ve now completed a comprehensive langgraph tutorial 2026 python, understanding how to build AI agents from scratch. But this is just the beginning! The world of AI agents is evolving incredibly fast, and LangGraph is at the forefront of this revolution. As we look to 2026 and beyond, expect even more powerful and intuitive ways to build intelligent systems.
Future developments in LangGraph and the broader AI agent space will likely focus on even more complex patterns, better integration with diverse tools, and advanced self-correction capabilities. Imagine agents that can not only fix their own code but also learn from their mistakes to improve future performance. This will further enhance the capabilities you’ve started to explore in this langgraph tutorial 2026 python.
The ability to create agents that can reason, plan, and adapt will unlock new possibilities across every industry. From personalized education to automated scientific discovery, AI agents built with frameworks like LangGraph will be instrumental in shaping our future. You are now equipped with the fundamental skills to contribute to this exciting future.
Conclusion: Your Journey to Building Smart AI Agents Begins Here
Congratulations! You’ve navigated through this extensive langgraph tutorial 2026 python and gained a solid understanding of how to build AI agents. We started by understanding what LangGraph is and how it differs from LangChain, emphasizing its power for multi-step, stateful applications. You successfully set up your Python environment, a crucial first step for any AI project.
You learned the core concepts of nodes and edges, the building blocks of any LangGraph. We then moved on to creating your very first graph, understanding how information flows through the AgentState. Mastering state management is key to building agents that can remember and reason over time. You also explored the vital concept of conditional routing, enabling your agents to make smart decisions and adapt their behavior. Finally, you learned how to compile and run your graphs, bringing your AI agents to life, and picked up essential debugging tips to troubleshoot issues.
With the real-world examples, you saw how these concepts combine to create powerful research, customer support, and code generation agents. The skills you’ve acquired today are foundational for developing sophisticated AI agents that can tackle complex problems.
The journey of building AI agents is continuous and filled with learning. Keep experimenting, keep building, and keep pushing the boundaries of what’s possible. The future of AI is exciting, and you are now an active participant in shaping it. Happy building!
Leave a comment