LangGraph Support Agent Flow

Yes

No

Yes

No

User Request

Intent Classification Node

Intent = order_status?

Order Status Tool Node

Skip Tool Node

Response Drafting Node

Needs Human Review?

Human Approval Node

Final Response

This diagram shows a practical LangGraph agent flow: classify intent, conditionally call a tool, draft a response, and optionally route to human approval before returning the final answer.

If you’ve experimented with LLM apps, you’ve likely hit the same wall: linear chains work for demos, but real applications need loops, branching, retries, tool calls, and memory. That’s exactly why developers choose LangGraph. In this guide, you’ll learn how to create an agent using LangGraph in a practical, production-minded way. We’ll cover what LangGraph is, why it helps, how to build your first agent, where to add real-world capabilities, and how to deploy with confidence.

# What Is LangGraph and Why Use It for Agents?

LangGraph is a framework for building stateful, multi-step AI workflows as graphs. Instead of a fixed chain, you define nodes (steps), edges (transitions), and shared state (data passed between steps). This model is ideal for agents because agents rarely follow a straight path—they reason, decide, act, observe results, and iterate.

# What problems it solves

  • Control flow: Add conditional routes (e.g., call a tool only when needed).
  • Durability: Checkpoint state to resume failed or interrupted runs.
  • Observability: Trace node-level execution for debugging and monitoring.
  • Composability: Build reusable nodes for retrieval, validation, tool execution, and response formatting.

# When LangGraph is the right choice

Use LangGraph when your app needs:

  • More than one model/tool call
  • Decision logic (if/else routing)
  • Human-in-the-loop checkpoints
  • Recoverability in production

Rule of thumb: If your LLM app needs a loop or branching, move from simple chains to a graph.

# Core Building Blocks: State, Nodes, Edges, and Checkpoints

Before coding, get the mental model right. A robust agent depends more on graph design than on prompt tricks.

# 1) State (the shared memory of a run)

State is a typed object passed across nodes. Typical fields include messages, tool results, user profile, and status flags.

from typing import TypedDict, List, Dict, Any

class AgentState(TypedDict, total=False):
    messages: List[Dict[str, str]]
    intent: str
    tool_result: Dict[str, Any]
    final_answer: str
    needs_human_review: bool

# 2) Nodes (units of work)

A node takes state in, returns state updates. Examples: classify intent, call model, execute tool, validate output.

# 3) Edges (how the graph moves)

You can define direct edges (A → B) and conditional edges (route based on state values).

# 4) Checkpointing (production safety net)

With checkpoints, you can persist progress and resume after crashes, timeouts, or human approval waits.

Production tip: Keep state minimal and explicit. Overloading state with raw logs or large blobs can slow execution and complicate debugging.

# How to Create an Agent Using LangGraph (Step-by-Step)

Let’s build a practical agent: a customer support triage agent that classifies incoming tickets, optionally calls an order-status tool, and drafts a response.

# Step 1: Install dependencies

pip install langgraph langchain langchain-openai

# Step 2: Define tools and model

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

def get_order_status(order_id: str):
    # Replace with real API call
    fake_db = {"A123": "Shipped", "B456": "Delayed due to weather"}
    return {"order_id": order_id, "status": fake_db.get(order_id, "Not found")}

# Step 3: Define graph nodes

import re
from typing import Dict, Any


def classify_intent(state: Dict[str, Any]):
    user_msg = state["messages"][-1]["content"]
    prompt = f"Classify this support message into: order_status, refund, general. Message: {user_msg}"
    intent = llm.invoke(prompt).content.strip().lower()
    return {"intent": intent}


def maybe_call_tool(state: Dict[str, Any]):
    if state.get("intent") != "order_status":
        return {"tool_result": {"skipped": True}}

    user_msg = state["messages"][-1]["content"]
    match = re.search(r"\b([A-Z]\d{3})\b", user_msg)
    order_id = match.group(1) if match else "UNKNOWN"
    result = get_order_status(order_id)
    return {"tool_result": result}


def draft_response(state: Dict[str, Any]):
    user_msg = state["messages"][-1]["content"]
    tool_result = state.get("tool_result", {})
    intent = state.get("intent", "general")

    prompt = f"""
    You are a helpful support agent.
    Intent: {intent}
    Tool result: {tool_result}
    User message: {user_msg}
    Write a clear, polite response in 3-5 sentences.
    """
    answer = llm.invoke(prompt).content
    return {"final_answer": answer}

# Step 4: Build and compile the graph

from langgraph.graph import StateGraph, END

workflow = StateGraph(dict)
workflow.add_node("classify_intent", classify_intent)
workflow.add_node("maybe_call_tool", maybe_call_tool)
workflow.add_node("draft_response", draft_response)

workflow.set_entry_point("classify_intent")
workflow.add_edge("classify_intent", "maybe_call_tool")
workflow.add_edge("maybe_call_tool", "draft_response")
workflow.add_edge("draft_response", END)

app = workflow.compile()

# Step 5: Invoke and test

input_state = {
    "messages": [
        {"role": "user", "content": "Hi, can you check order A123? It still hasn't arrived."}
    ]
}

result = app.invoke(input_state)
print(result["intent"])
print(result["tool_result"])
print(result["final_answer"])

Beginner win: Start with 3 nodes. Once stable, add conditional branching, retries, and human review nodes.

# Real-World Patterns You Should Add Next

# Conditional routing

Instead of always executing the same path, route dynamically:

  • If intent = refund, route to policy lookup node.
  • If confidence is low, route to human-review node.
  • If tool call fails, route to retry/backoff node.

# Retrieval-augmented responses (RAG)

Add a retrieval node before drafting responses so the agent can cite your knowledge base or docs.

# Human-in-the-loop approvals

For high-risk actions (refund approvals, account changes), insert a pause node and await human confirmation.

# Guardrails and validation

Create an output validation node that checks:

  • Required fields exist
  • No policy-violating language
  • No hallucinated order status without tool confirmation

Key takeaway: Great agents are not just smart—they are controlled, auditable, and safe.

# Production Checklist: Reliability, Cost, and Observability

# Reliability

  • Enable checkpointing/persistence
  • Add retries with exponential backoff for external APIs
  • Set timeouts for every network-dependent node

# Cost control

  • Use small models for classification nodes
  • Cache deterministic tool results
  • Truncate message history intelligently

# Observability

  • Log node input/output metadata (not sensitive content)
  • Track per-node latency and token usage
  • Instrument success/failure rates by route
# Pseudocode example for lightweight instrumentation
import time

def timed_node(fn):
    def wrapper(state):
        start = time.time()
        out = fn(state)
        duration_ms = int((time.time() - start) * 1000)
        print({"node": fn.__name__, "duration_ms": duration_ms})
        return out
    return wrapper

# Common Mistakes (and How to Avoid Them)

  • Mistake: Putting everything in one mega-node.
    Fix: Split by responsibility (plan, act, validate, respond).
  • Mistake: No fallback when tools fail.
    Fix: Add retry and graceful user-facing degradation.
  • Mistake: Unbounded memory growth.
    Fix: Summarize old turns and keep compact state.
  • Mistake: Blind trust in model outputs.
    Fix: Add policy and schema validation nodes.

# Conclusion

Now you know how to create an agent using LangGraph in a way that works beyond tutorials. Start with a small graph: define typed state, add focused nodes, route with clear logic, and validate outputs. Then harden it for production with checkpointing, observability, and guardrails. If you treat your agent as a state machine—not just a prompt—you’ll build systems that are easier to debug, safer to operate, and far more useful in real business workflows.