Use this file to discover all available pages before exploring further.
LangGraph is a framework by LangChain for building stateful, multi-step agent applications. Instead of writing imperative loops, you describe your agent as a directed graph: nodes define what the agent can do, edges define the order in which it does things, and a shared state object carries data between steps. This graph-based model makes it straightforward to add, remove, or reroute steps without touching unrelated code.
Typed state
Use Python TypedDict to define exactly what data flows through your graph.
Composable nodes
Each node is a plain function—easy to test, easy to swap.
Conditional routing
Branch execution paths at runtime based on what the agent has learned so far.
The tutorial in this repository walks through a multi-step text analysis agent that classifies a document, extracts entities, and summarizes it—all in a single graph invocation.
Each node is a function that accepts the current state and returns a dictionary with only the fields it wants to update. LangGraph merges that dictionary back into the full state automatically:
from langchain_core.prompts import PromptTemplatefrom langchain_core.messages import HumanMessagefrom langchain_openai import ChatOpenAIllm = ChatOpenAI(model="gpt-4o-mini", temperature=0)def classification_node(state: State): """Classify text into News, Blog, Research, or Other.""" prompt = PromptTemplate( input_variables=["text"], template="Classify the following text into one of the categories: " "News, Blog, Research, or Other.\n\nText:{text}\n\nCategory:" ) message = HumanMessage(content=prompt.format(text=state["text"])) classification = llm.invoke([message]).content.strip() return {"classification": classification}def entity_extraction_node(state: State): """Extract Person, Organization, and Location entities.""" prompt = PromptTemplate( input_variables=["text"], template="Extract all the entities (Person, Organization, Location) from the " "following text. Provide the result as a comma-separated list.\n\n" "Text:{text}\n\nEntities:" ) message = HumanMessage(content=prompt.format(text=state["text"])) entities = llm.invoke([message]).content.strip().split(", ") return {"entities": entities}def summarization_node(state: State): """Summarize the text in one short sentence.""" prompt = PromptTemplate( input_variables=["text"], template="Summarize the following text in one short sentence.\n\n" "Text:{text}\n\nSummary:" ) message = HumanMessage(content=prompt.format(text=state["text"])) summary = llm.invoke([message]).content.strip() return {"summary": summary}
Pass an initial state dictionary and read back the fully populated result:
sample_text = """OpenAI has announced the GPT-4 model, which is a large multimodal model thatexhibits human-level performance on various professional benchmarks."""result = app.invoke({"text": sample_text})print("Classification:", result["classification"])print("Entities:", result["entities"])print("Summary:", result["summary"])
A linear graph runs every node unconditionally. Conditional edges let you skip steps or take different paths based on runtime data. Define a routing function that returns a key, then map each key to a destination node:
1
Extend the state
Add any fields the routing function needs to read:
Return a value that add_conditional_edges will use as a lookup key:
def route_after_classification(state: EnhancedState) -> bool: category = state["classification"].lower() # Extract entities only for News and Research articles return category in ["news", "research"]
3
Define a sentiment node
def sentiment_node(state: EnhancedState): """Analyze sentiment: Positive, Negative, or Neutral.""" prompt = PromptTemplate( input_variables=["text"], template="Analyze the sentiment of the following text. " "Is it Positive, Negative, or Neutral?\n\nText:{text}\n\nSentiment:" ) message = HumanMessage(content=prompt.format(text=state["text"])) sentiment = llm.invoke([message]).content.strip() return {"sentiment": sentiment}
# News article → goes through entity extractionnews_text = """OpenAI released the GPT-4 model with enhanced performance on academicand professional tasks."""result = conditional_app.invoke({"text": news_text})print("Classification:", result["classification"])print("Entities:", result.get("entities", "Skipped"))print("Summary:", result["summary"])print("Sentiment:", result["sentiment"])# Blog post → skips entity extractionblog_text = """Here's what I learned from a week of meditating in silence.No phones, no talking—just me, my breath, and some deep realizations."""result = conditional_app.invoke({"text": blog_text})print("Classification:", result["classification"])print("Entities:", result.get("entities", "Skipped (not applicable)"))print("Summary:", result["summary"])print("Sentiment:", result["sentiment"])
Run this in a Jupyter notebook to get an interactive diagram. If Mermaid rendering is unavailable, the graph structure is still printed as text: classification_node → entity_extraction → summarization → END.
import osfrom typing import TypedDict, Listfrom langchain_core.prompts import PromptTemplatefrom langchain_core.messages import HumanMessagefrom langchain_openai import ChatOpenAIfrom langgraph.graph import StateGraph, ENDfrom dotenv import load_dotenvload_dotenv()os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)class State(TypedDict): text: str classification: str entities: List[str] summary: strdef classification_node(state: State): prompt = PromptTemplate( input_variables=["text"], template="Classify the following text into one of the categories: " "News, Blog, Research, or Other.\n\nText:{text}\n\nCategory:" ) message = HumanMessage(content=prompt.format(text=state["text"])) return {"classification": llm.invoke([message]).content.strip()}def entity_extraction_node(state: State): prompt = PromptTemplate( input_variables=["text"], template="Extract all the entities (Person, Organization, Location) from the " "following text. Provide the result as a comma-separated list.\n\n" "Text:{text}\n\nEntities:" ) message = HumanMessage(content=prompt.format(text=state["text"])) return {"entities": llm.invoke([message]).content.strip().split(", ")}def summarization_node(state: State): prompt = PromptTemplate( input_variables=["text"], template="Summarize the following text in one short sentence.\n\n" "Text:{text}\n\nSummary:" ) message = HumanMessage(content=prompt.format(text=state["text"])) return {"summary": llm.invoke([message]).content.strip()}workflow = StateGraph(State)workflow.add_node("classification_node", classification_node)workflow.add_node("entity_extraction", entity_extraction_node)workflow.add_node("summarization", summarization_node)workflow.set_entry_point("classification_node")workflow.add_edge("classification_node", "entity_extraction")workflow.add_edge("entity_extraction", "summarization")workflow.add_edge("summarization", END)app = workflow.compile()sample_text = """OpenAI has announced the GPT-4 model, which is a large multimodal model thatexhibits human-level performance on various professional benchmarks. It is developedto improve the alignment and safety of AI systems."""result = app.invoke({"text": sample_text})print("Classification:", result["classification"])print("Entities:", result["entities"])print("Summary:", result["summary"])