Lesson 1.1: The "Hello World" Graph

In a standard script, you call function A, get the result, and pass it to function B. In LangGraph, you don’t call functions directly. You place them on a “board” (the Graph) and draw lines between them. The Graph manages the execution.

The 4-Step Recipe

Every LangGraph application follows the exact same 4-step structure:

  1. Define State: What data are we passing around?
  2. Define Nodes: What functions will modify that data?
  3. Build Graph: Add the nodes and connect them with edges.
  4. Compile & Run: Turn the blueprint into an executable app.

The Code

Here is the simplest possible graph: A “Start” node that passes a message to an “End” node.

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

# --- STEP 1: Define the State ---
# Think of this as the "Protocol". 
# Every node MUST accept this dictionary and return a part of it.
class SimpleState(TypedDict):
    message: str

# --- STEP 2: Define the Nodes ---
# Nodes are just Python functions. 
# They receive the current State and return an update.
def shout_node(state):
    print(f"Node 'Shout' received: {state['message']}")
    # We return an update: capitalize the message
    return {"message": state['message'].upper()}

def whisper_node(state):
    print(f"Node 'Whisper' received: {state['message']}")
    # We return an update: add 'shh'
    return {"message": state['message'] + " (shh)"}

# --- STEP 3: Build the Graph ---
# We initialize the builder with our State structure
builder = StateGraph(SimpleState)

# Add our workers (Nodes)
builder.add_node("shout", shout_node)
builder.add_node("whisper", whisper_node)

# Create the flow (Edges)
# 1. Start at 'shout'
builder.set_entry_point("shout")
# 2. Go from 'shout' to 'whisper'
builder.add_edge("shout", "whisper")
# 3. Go from 'whisper' to the End (Finish execution)
builder.add_edge("whisper", END)

# --- STEP 4: Compile & Run ---
# Compile freezes the structure
graph = builder.compile()

# Invoke with an initial state
result = graph.invoke({"message": "hello world"})

print("-" * 20)
print(f"Final Result: {result['message']}")

Output

Node 'Shout' received: hello world
Node 'Whisper' received: HELLO WORLD
--------------------
Final Result: HELLO WORLD (shh)

Key Concept: The Graph vs. The Chain

You might look at this and say, “This looks like a lot of boilerplate just to run two functions.”

If you just wanted a linear chain ($A \to B$), you are right. But notice what we didn’t do:

  • shout_node did not call whisper_node.
  • shout_node doesn’t even know whisper_node exists.

This decoupling is critical. It means later we can easily insert a “Check Safety” node between them without rewriting the shout function. We just change the edge.

Leave a Comment