Build Your First LangGraph Graph Step by Step

Now let’s build a small, complete graph from scratch and watch it run step by step. Here are the steps with the code.

What we are building

A text analyzer with two nodes:

START -> count_words -> label_length -> END
  • count_words counts the words in a text
  • label_length labels the text as short, medium, or long

The full code

from typing import TypedDict
from langgraph.graph import StateGraph, START, END

# 1. State
class State(TypedDict):
    text: str
    word_count: int
    level: str

# 2. Nodes
def count_words(state: State):
    return {"word_count": len(state["text"].split())}

def label_length(state: State):
    count = state["word_count"]
    if count < 10:
        level = "short"
    elif count < 30:
        level = "medium"
    else:
        level = "long"
    return {"level": level}

# 3. Build the graph
builder = StateGraph(State)

builder.add_node("count_words", count_words)
builder.add_node("label_length", label_length)

builder.add_edge(START, "count_words")
builder.add_edge("count_words", "label_length")
builder.add_edge("label_length", END)

# 4. Compile and run
graph = builder.compile()

result = graph.invoke({"text": "LangGraph helps you build AI apps as graphs"})
print(result)

Output:

{'text': 'LangGraph helps you build AI apps as graphs', 'word_count': 8, 'level': 'short'}

How it works

  1. We pass in only text. The fields word_count and level don’t exist yet. They appear once a node writes them.
  2. count_words splits the text into words and stores the count (8).
  3. label_length reads that count, which was written by the previous node, and picks a label.
  4. The final state contains all three fields.

Watching each step with stream()

invoke() gives only the final result. To see what each node did, use stream():

for step in graph.stream(
    {"text": "LangGraph helps you build AI apps as graphs"},
    stream_mode="updates",
):
    print(step)

Output:

{'count_words': {'word_count': 8}}
{'label_length': {'level': 'short'}}

Each line shows the node’s name and the update it returned. This is very useful for debugging, and we will use it a lot later.

invoke() vs stream()

  • invoke() returns the final state only. Use it when you just want the result.
  • stream() returns updates as they happen. Use it when you want to see progress or debug.

Try different inputs

long_text = "word " * 35
print(graph.invoke({"text": long_text})["level"])

Output:

long

The same graph handles any input. You define the workflow once and reuse it.

Common mistakes in your first graph

  • Reading a field before it exists: if label_length ran before count_words, state[“word_count”] would raise a KeyError. Edge order matters.
  • Node name mismatch: add_edge(“count_word”, …) (missing the “s”) fails because that node doesn’t exist.
  • Returning a value instead of a dict: a node must return {“word_count”: 8}, not just 8.

Summary

  • A complete graph follows five steps: define state, write nodes, add nodes, connect edges, compile
  • Nodes pass data to each other through the shared state
  • invoke() returns the final state, and stream() shows every step
  • Fields you haven’t written yet simply don’t exist in the state

Practice

  1. Add a third node, count_characters, that stores the character count in a new field
  2. Use stream() to confirm that all three nodes run in order
  3. Change the thresholds in label_length so “medium” starts at 5 words

If you liked the tutorial, spread the word and share the link and our website, Studyopedia, with others.


For Videos, Join Our YouTube Channel: Join Now


Read More:

LangGraph Setup: Install LangGraph and Create Your Project
LangGraph State: TypedDict, Pydantic, and Reducers
Studyopedia Editorial Staff
contact@studyopedia.com

We work to create programming tutorials for all.

No Comments

Post A Comment