Choosing APIs in LangGraph

A developer's guide to building AI workflows with the Graph API, covering StateGraph, nodes, edges, and production best practices.

Understanding the Graph API: Core Concepts

LangGraph models agent workflows as graphs, where you define behavior using three key components: State, Nodes, and Edges. The State represents the current snapshot of your application--typically a TypedDict or Pydantic model that defines the schema of data flowing through your graph. Nodes are functions that encode the logic of your agents, receiving the current state as input, performing computation, and returning an updated state. Edges determine which node to execute next based on the current state, enabling both fixed transitions and conditional branching.

The StateGraph class is the main graph class to use when building LangGraph applications. It is parameterized by a user-defined State object that defines the schema for data passing through the graph.

For developers building sophisticated AI applications, understanding these core concepts enables the creation of complex, stateful workflows that go beyond simple linear chains. The graph-based approach provides flexibility for multi-agent systems, human-in-the-loop approvals, and intelligent routing based on context. If you're new to LangChain, start with our LangGraph Overview to understand the foundational concepts before diving deeper into the Graph API.

When to Use LangGraph vs LangChain

The choice between LangChain and LangGraph depends on your application's complexity requirements. LangChain provides a linear chain-based approach (DAGs) ideal for simple, sequential workflows like RAG pipelines and basic chatbots. LangGraph offers a graph-based architecture with native support for cycles, loops, and state persistence--essential for complex, stateful multi-agent systems.

For production deployments, LangGraph is recommended when you need persistent state across multiple conversation turns, human-in-the-loop approval workflows, time-travel debugging, or streaming responses. Our web development team specializes in building production-ready AI agents using LangGraph's powerful architecture.

Graph API Core Components

State Management

Define state using TypedDict or Pydantic models with reducers for handling updates

Nodes

Create custom node functions that transform state and encode agent logic

Edges

Connect nodes with normal edges for fixed flows and conditional edges for dynamic routing

Command Pattern

Use imperative control flow for human-in-the-loop workflows and tool integration

LangChain vs LangGraph: Framework Comparison
FeatureLangChainLangGraph
ArchitectureLinear, chain-based (DAGs)Graph-based with cycles
State ManagementPass through chainFirst-class persistent state
Human-in-the-LoopLimited supportBuilt-in interrupts
DebuggingStandard loggingTime-travel debugging
Best ForSimple, linear workflowsComplex, stateful multi-agent systems

State: The Foundation of Your Graph

Defining State with TypedDict

The main documented way to specify the schema of a graph is by using a TypedDict. If you want to provide default values in your state, use a dataclass. LangGraph also supports using a Pydantic BaseModel as your graph state if you want recursive data validation, though note that Pydantic is less performant than TypedDict or dataclass.

from typing import TypedDict

class AgentState(TypedDict):
 messages: list[str]
 current_step: str
 pending_approval: bool

Using Pydantic Models for State

By default, the graph will have the same input and output schemas. If you want to change this, you can also specify explicit input and output schemas directly. This is useful when you have a lot of keys, and some are explicitly for input and others for output.

Reducers: Managing State Updates

Reducers specify how to apply updates to the state. When a node returns a dictionary, the reducer determines how those updates are merged with the existing state. By default, LangGraph uses a simple update behavior where keys in the returned dictionary overwrite keys in the state.

For complex applications, consider implementing custom reducers that handle list appending, nested updates, or conditional merging based on your specific requirements.

Nodes: The Building Blocks of Your Workflow

Defining Custom Nodes

Nodes are Python functions that accept the state object and return a dictionary with the modifications to that state. Each node is given a string label and the corresponding function when added to the graph.

def analyze_query(state: AgentState) -> dict:
 """Analyzes the user query and updates state."""
 query = state.get("messages", [])[-1]
 return {"current_step": "analyzing", "query_analysis": query}

START and END Nodes

START is a special node that represents the entry point to your graph. When you invoke the graph, the initial state is passed to the START node, which then routes to the next node based on your edge definitions. END is a special keyword that signals the completion of the workflow--no further nodes will execute after reaching END.

Node Caching

LangGraph includes node caching to optimize performance for repeated executions with the same state. This feature is particularly useful when debugging or when your workflow requires revisiting the same node with identical state values. Understanding caching behavior helps you design efficient workflows that balance performance with state consistency.

Edges: Controlling Workflow Flow

Normal Edges

Use set_entry_point() to define the first node to run and add_edge() to specify the flow between nodes. Normal edges create fixed transitions where execution always proceeds from one node to another.

graph.set_entry_point("analyze")
graph.add_edge("analyze", "process")
graph.add_edge("process", END)

Conditional Edges

Conditional edges enable dynamic routing based on the current state. You define a function that returns a routing key, and a mapping of routing keys to destination nodes.

def route_query(state: AgentState) -> str:
 """Route based on query type."""
 query = state.get("query_analysis", "").lower()
 if "pricing" in query:
 return "pricing"
 else:
 return "general"

graph.add_conditional_edges(
 "analyze",
 route_query,
 {
 "pricing": "pricing_info",
 "general": "general_info"
 }
)

Entry Points and Conditional Entry Points

The entry point defines where execution begins when the graph is invoked. For simple cases, use set_entry_point() with a fixed node. For more complex scenarios where the starting node depends on input, use conditional entry points.

This flexibility enables sophisticated workflows where different entry conditions trigger different initial paths through your graph, supporting use cases like multi-tenant routing or context-aware initialization.

The Command Pattern: Advanced Control Flow

When to Use Command

The Command API provides imperative control over graph execution, allowing you to pause execution for human input, navigate to specific nodes in a parent graph, or use inside tools for dynamic state management.

Human-in-the-Loop Workflows

LangGraph's interrupt feature enables human approval before critical operations. You can pause execution at specific points, wait for human review, then resume or cancel based on the input.

app = workflow.compile(
 checkpointer=memory,
 interrupt_before=["execute"]
)

# After human review
if user_approves:
 final_state = app.invoke(None, config=config)

Using Command Inside Tools

Tools can use Command to dynamically influence graph execution, enabling sophisticated agent behaviors where tools can request specific workflow paths or trigger interrupts based on detected conditions.

This pattern is particularly valuable for production AI systems requiring oversight, compliance checkpoints, or quality gates before executing sensitive operations. Our AI automation services team can help you implement these patterns in your production systems.

Runtime Context: Managing Execution Limits

Understanding Recursion Limits

LangGraph includes a recursion limit to prevent infinite loops in graphs. By default, the recursion limit is set to 25 steps, but this can be configured based on your application's needs.

Accessing the Recursion Counter

def check_recursion(state: AgentState, config) -> dict:
 """Check current step count and handle recursion."""
 step_count = config.get("recursion_count", 0)
 if step_count >= 20:
 return {"next_step": "finalize"}
 return {"next_step": "continue"}

Other Available Metadata

The runtime context provides additional metadata for debugging and monitoring your graph execution. This includes execution timestamps, node transition history, and state snapshots that enable powerful debugging capabilities like time-travel inspection of your graph's execution path.

For production deployments, leveraging runtime metadata alongside observability tools helps identify performance bottlenecks, unexpected branching patterns, and state mutation issues that may arise in complex multi-agent workflows.

Compiling Your Graph

Compiling your graph provides a few basic checks on the structure of your graph, such as detecting orphaned nodes. It is also where you specify runtime arguments like checkpointers and breakpoints. You must compile your graph before you can use it.

from langgraph.checkpoint.memory import MemorySaver

memory = MemorySaver()
app = graph.compile(checkpointer=memory)

Compiling validates your graph structure and prepares it for execution. The compilation step is also where you configure checkpointers that persist state across sessions, enabling conversation memory and recovery from interruptions. For production deployments, this is a critical step in ensuring your AI agents can maintain context and recover gracefully from failures.

Understanding the compilation process helps you catch structural issues early and ensures your graph is properly configured with the checkpointers, interrupts, and other runtime options your production deployment requires.

Best Practices for Production

  1. Use appropriate state schema: Prefer TypedDict for performance, Pydantic for validation
  2. Implement checkpointing: Use MemorySaver for development, SqliteSaver or PostgresSaver for production
  3. Add error handling: Implement retries with exponential backoff for resilient agents
  4. Enable observability: Use LangSmith for tracing and monitoring agent behavior
  5. Configure rate limiting: Prevent abuse with per-user rate limits
  6. Use interrupts for sensitive actions: Implement human approval for critical operations

Memory and Checkpointing Options

CheckpointerUse CasePersistence
MemorySaverDevelopmentIn-memory only
SqliteSaverSingle-server productionFile-based
PostgresSaverDistributed deploymentsDatabase

Production Deployment Checklist

  • State schema defined (TypedDict preferred)
  • Checkpointer configured for persistence
  • Error handling with retries
  • LangSmith observability enabled
  • Rate limiting implemented
  • Human-in-the-loop for sensitive operations

Following these best practices ensures your LangGraph applications are reliable, observable, and maintainable. Each consideration addresses a specific aspect of production readiness, from performance optimization to operational oversight. Partner with our web development team to ensure your LangGraph implementation meets enterprise standards for reliability and scalability.

Frequently Asked Questions

When should I use LangGraph instead of LangChain?

Use LangGraph when you need persistent state across conversation turns, human-in-the-loop approval workflows, time-travel debugging, or streaming responses. LangChain is suitable for simple linear workflows like RAG pipelines.

What is the difference between TypedDict and Pydantic for state?

TypedDict is recommended for better performance as it doesn't add validation overhead. Use Pydantic BaseModel when you need recursive data validation or complex nested structures.

How do conditional edges work in LangGraph?

Conditional edges use a routing function that returns a key. This key is mapped to a destination node, enabling dynamic routing based on the current state.

What is the Command pattern used for?

The Command pattern provides imperative control for human-in-the-loop workflows, navigating to nodes in parent graphs, and dynamic state management inside tools.

Build Intelligent AI Agents with LangGraph

Our team specializes in building production-ready AI agents using LangGraph's powerful graph-based architecture.

Sources

  1. LangChain Docs - Graph API - Official documentation covering StateGraph, nodes, edges, reducers, and runtime context
  2. LangChain Docs - Using the Graph API - Practical examples of using the Graph API with Pydantic models
  3. Digital Applied - LangChain AI Agents Guide - LangGraph vs LangChain comparison, production patterns, best practices
  4. Codecademy - LangGraph Tutorial - Step-by-step workflow building, state management, conditional edges