LangGraph 101: Build a Stateful Agent
LangGraph extends LangChain with a graph-based execution model that gives your agents persistent state, branching logic, and the ability to loop until a task is truly done.
Key Takeaways
- Comprehensive strategies proven to work at top companies
- Actionable tips you can implement immediately
- Expert insights from industry professionals
LangChain chains are powerful but linear. They pass data from node to node in a straight line and stop when they reach the end. Most real agent tasks are not linear. They require branching, looping, and tracking state across many steps. That is what LangGraph is for.
LangGraph models an agent as a directed graph. Nodes are Python functions. Edges define which node runs next. A shared state object flows through the graph, getting updated at every step. The result is an agent that can loop, branch, and remember where it is in a complex task.
The Three Building Blocks: State, Nodes, Edges
Before writing any code, understand these three concepts.
State is a typed Python dictionary that every node can read and write. It is the agent's working memory. Define it as a TypedDict with all the fields your agent needs to track. State persists across the entire execution of the graph.
Nodes are Python functions that take the current state, do something (call an LLM, run a tool, make a decision), and return a partial state update. LangGraph merges the update into the full state automatically.
Edges connect nodes. A fixed edge always goes from node A to node B. A conditional edge inspects the current state and routes to one of several possible next nodes based on a condition you define. Conditional edges are where the branching logic lives.
Build: A Simple Research Agent
Here is a three-node graph: a researcher node that searches for information, a writer node that drafts a report, and a router that decides whether the research is complete or needs another search pass.
from typing import TypedDict, List
from langgraph.graph import StateGraph, END
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage
model = ChatAnthropic(model='claude-3-5-sonnet-20241022')
# 1. Define the state schema
class ResearchState(TypedDict):
question: str
search_results: List[str]
draft: str
iterations: int
# 2. Define nodes
def researcher(state: ResearchState) -> dict:
results = [f'Search result for: {state["question"]}']
return {
'search_results': state['search_results'] + results,
'iterations': state['iterations'] + 1
}
def writer(state: ResearchState) -> dict:
context = '
'.join(state['search_results'])
response = model.invoke([
HumanMessage(content=f'Write a brief report on {state["question"]}. Context: {context}')
])
return {'draft': response.content}
def router(state: ResearchState) -> str:
if state['iterations'] >= 2 or len(state['search_results']) >= 3:
return 'write'
return 'research'
# 3. Build and compile the graph
graph = StateGraph(ResearchState)
graph.add_node('research', researcher)
graph.add_node('write', writer)
graph.set_entry_point('research')
graph.add_conditional_edges('research', router, {'research': 'research', 'write': 'write'})
graph.add_edge('write', END)
app = graph.compile()
Running the Graph
Once compiled, the graph runs with a single invoke call. Pass in the initial state and it executes nodes in order, following edges, until it reaches END.
initial_state = {
'question': 'What are the main drivers of SaaS churn?',
'search_results': [],
'draft': '',
'iterations': 0
}
result = app.invoke(initial_state)
print(result['draft'])
Prompt
"You are a research agent. Your job is to gather enough information to write a confident, accurate report. If your current search results are incomplete or contradictory, indicate that you need more research. If the results are sufficient, indicate that you are ready to write."
Why State Changes Everything
Compared to a LangChain chain, the critical difference is that the graph can revisit nodes. The researcher node can run twice, three times, or ten times, each time appending to the same state. The router decides when to stop. This loop-until-done pattern is what makes LangGraph agents feel genuinely autonomous rather than just running a fixed script.
Want to build this live with Aki?
Join a Lightning Lesson and go deeper on this topic. Browse upcoming sessions →
Aki Wijesundara
Expert team of AI professionals and career advisors with experience at top tech companies. We've helped 500+ students land internships at Google, Meta, OpenAI, and other leading AI companies.
Ready to Launch Your AI Career?
Join our comprehensive program and get personalized guidance from industry experts who've been where you want to go.
Table of Contents
Share Article
Get Weekly AI Career Tips
Join 5,000+ professionals getting actionable career advice in their inbox.
No spam. Unsubscribe anytime.