A research agent graph — define nodes (plan, search, analyze, write), define edges and conditions between them, and run a complex multi-step research task with full state visibility at every step.
What LangGraph Adds Over Plain Agents
Plain AgentExecutor is a loop. LangGraph is a directed graph. You control the exact flow: which nodes run, in what order, when to loop back, when to stop. This matters for production because you can add breakpoints, human approval steps, and error recovery.
pip install langgraph
State, Nodes, and Edges
A LangGraph is built from three things: State (a TypedDict shared across all nodes), Nodes (Python functions that transform state), and Edges (connections between nodes, including conditional ones).
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
# 1. Define the state schema
class ResearchState(TypedDict):
topic: str
questions: list
findings: str
report: str
iterations: int
model = ChatOpenAI(model="gpt-4o-mini")
# 2. Define nodes — each takes state, returns updated state
def plan_research(state: ResearchState) -> dict:
response = model.invoke(
f"Generate 3 research questions about: {state['topic']}"
)
questions = [q.strip() for q in response.content.split('\n') if q.strip()]
return {"questions": questions, "iterations": 0}
def gather_findings(state: ResearchState) -> dict:
questions_text = "\n".join(state["questions"])
response = model.invoke(
f"Answer these research questions concisely:\n{questions_text}"
)
return {"findings": response.content, "iterations": state["iterations"] + 1}
def write_report(state: ResearchState) -> dict:
response = model.invoke(
f"Write a 3-paragraph research report on {state['topic']} based on:\n{state['findings']}"
)
return {"report": response.content}
# 3. Build the graph
graph = StateGraph(ResearchState)
graph.add_node("plan", plan_research)
graph.add_node("gather", gather_findings)
graph.add_node("write", write_report)
# 4. Define edges
graph.set_entry_point("plan")
graph.add_edge("plan", "gather")
graph.add_edge("gather", "write")
graph.add_edge("write", END)
app = graph.compile()
# 5. Run it
result = app.invoke({"topic": "LangGraph vs plain LangChain agents"})
print(result["report"])
Conditional edges let you route to different nodes based on state. Add graph.add_conditional_edges("gather", check_quality, {"good": "write", "bad": "gather"}) to loop until quality passes.
Day 5 Complete — What You Learned
- LangGraph's three primitives: State, Nodes, Edges
- Built a multi-node research workflow
- Used TypedDict for typed state management
- Understood conditional routing and cycles
- How LangGraph enables production-grade agents
You finished LangChain in 5 Days
Chains, memory, RAG, agents, and LangGraph. You now know the full LangChain stack. The next step is deploying what you built.