AI — AI Agent Development

Building AI Agents with LangGraph

Direct answer

LangGraph models an agent as a state machine: you define a typed state schema, add nodes (functions that update state), wire edges including conditional routing, and compile with a checkpointer for persistence. It earns its complexity when you need cycles, human-in-the-loop interrupts, or resumable long-running workflows. For a single model-plus-tools loop, a plain while loop is less code and easier to debug.

LangGraph is what I reach for when an agent stops being a loop and becomes a workflow — approval pauses, branching strategies, resumable state across restarts. Here's how I structure a LangGraph agent in practice, and the honest cases where I skip the framework entirely.

Key facts, with sources

  • LangChain's State of Agent Engineering survey of 1,340 practitioners found 57.3 percent of organizations have agents running in production, with another 30.4 percent actively developing them. (LangChain)
  • The same LangChain survey found 89 percent of organizations have implemented observability for their agents but only 52 percent do systematic evaluation. (LangChain)
  • Deloitte predicts 25 percent of companies using generative AI launched agentic AI pilots in 2025, growing to 50 percent by 2027. (Deloitte Insights)
  • By December 2025 the Model Context Protocol had over 97 million monthly SDK downloads and more than 10,000 active MCP servers in production use. (Pento)
  • PwC's AI agent survey found 79 percent of companies report AI agents are already being adopted, and 66 percent of adopters say agents deliver measurable value through increased productivity. (PwC)
  • In December 2025 Anthropic donated the Model Context Protocol to the Agentic AI Foundation under the Linux Foundation, co-founded with Block and OpenAI, making the agent connector layer vendor-neutral. (Anthropic)

A graph, not a loop

LangGraph's core move is making control flow explicit data: nodes are units of work, edges declare what runs next, and cycles are first-class rather than a while-loop you maintain by hand. The payoff isn't elegance — it's inspectability. Every transition is a defined point where state can be checkpointed, logged, or interrupted, which is exactly the surface you need for approvals and debugging.

When a plain-loop agent misbehaves, you add print statements; when a graph agent misbehaves, you replay the state at each node boundary. That difference feels academic on a demo and decisive on a workflow with ten steps, two approval gates, and a retry branch.

Define the state schema first

The state schema is the contract every node reads from and writes to, and I design it before writing any node. LangGraph state is typically a TypedDict where each field can carry a reducer — the messages field uses an append-style reducer so nodes contribute messages without overwriting history, while plain fields get replaced.

Keep it lean: messages plus a few typed fields like retry counts, a status enum, or a pending-approval marker. Everything in state gets serialized on every checkpoint, so large blobs — full documents, raw API dumps — belong in external storage with references in state. A bloated state schema is the LangGraph equivalent of the ever-growing prompt: it works in the demo and hurts everywhere else.

Nodes, edges, and conditional routing

The canonical agent graph has two nodes and one decision. The agent node calls the model with the current messages; the tools node executes whatever tool calls the model produced. A conditional edge inspects the last message: tool calls present means route to tools, otherwise end. The tools node routes back to the agent, forming the loop.

What I like about this shape is how naturally it extends. Add a validation node between agent and end to enforce output structure; add an approval node before a dangerous tool; add a fallback branch when retries exhaust. Each addition is a visible node and edge in the graph definition rather than another indentation level inside a monolithic loop.

Canonical LangGraph agent with checkpointing
from typing import Annotated, TypedDict

from langchain.chat_models import init_chat_model
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import END, START, StateGraph
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode

MODEL = "anthropic:<latest-claude-model-id>"  # use the latest model id

class AgentState(TypedDict):
    messages: Annotated[list, add_messages]

llm = init_chat_model(MODEL).bind_tools(tools)

def agent(state: AgentState) -> dict:
    return {"messages": [llm.invoke(state["messages"])]}

def route(state: AgentState) -> str:
    return "tools" if state["messages"][-1].tool_calls else END

graph = StateGraph(AgentState)
graph.add_node("agent", agent)
graph.add_node("tools", ToolNode(tools))
graph.add_edge(START, "agent")
graph.add_conditional_edges("agent", route, {"tools": "tools", END: END})
graph.add_edge("tools", "agent")
app = graph.compile(checkpointer=MemorySaver())

result = app.invoke(
    {"messages": [("user", "Summarize open tickets for account 42")]},
    config={"configurable": {"thread_id": "task-42"}},
)

Checkpointing and interrupts are the real features

Checkpointing is where LangGraph stops being a nicer syntax and starts being infrastructure. Compile the graph with a checkpointer and every node transition persists state under a thread ID: a conversation can continue across requests, a crashed process resumes where it stopped, and you can inspect historical state for debugging. In-memory checkpointing is for development; production wants one of the persistent checkpointer backends so state survives restarts.

Interrupts build human-in-the-loop directly into the graph: configure the graph to pause before a sensitive node, and execution stops with state saved until you resume it — with or without modifications. That's the approval-gate pattern I otherwise build by hand with job queues, provided by the framework.

When LangGraph is overkill

For a chatbot with a handful of tools and a linear loop, LangGraph adds a state schema, a graph definition, reducer semantics, and a framework dependency between you and every bug — while a plain loop over a model SDK is fewer lines and transparent. I've removed the framework from projects where it was pure ceremony, and the code got shorter and clearer.

My adoption rule: reach for LangGraph when you need at least one of interrupts for approval flows, durable resumable state across process boundaries, or genuinely branching workflows with retries and fallbacks. If none apply today, a boring loop preserves the option — migrating a clean loop into a graph later is straightforward, because the nodes are just your existing functions.

When to hire senior help

Bring in senior help when the agent must touch production systems or customer data, because integration, security, and reliability are where inexperienced builds fail rather than model quality. If a pilot is stuck at the demo stage, an experienced engineer adding evals and guardrails is usually faster and cheaper than rebuilding from scratch. If your stack includes React Native + Python + AI, a senior engineer who owns the full product beats coordinating multiple juniors.

Bottom line

Dhairya Senjaliya ships AI — AI Agent Development projects worldwide — book a scoping call to discuss your specific situation.

Common pitfalls to avoid

  • Shipping agents with logging but no evals, so teams can see traces but never measure task success rates and regressions ship silently
  • Giving one agent dozens of tools instead of a focused toolset, which degrades tool-selection accuracy and inflates token costs
  • Hand-rolling custom integration glue for every data source instead of using MCP, which is now the vendor-neutral standard backed by Anthropic, OpenAI, and the Linux Foundation
  • Validating only on happy-path demo prompts and skipping failure-mode testing, a core reason roughly 88 percent of agent pilots never reach production

Frequently asked questions

When should I use LangGraph instead of a simple agent loop?

Use LangGraph when you need what a hand-rolled loop makes painful: pausing execution for human approval and resuming later, durable state that survives process restarts, or branching workflows with retries and fallback strategies. For a linear model-plus-tools loop, a plain SDK loop is less code, easier to debug, and simpler to maintain — adopt the framework when requirements demand it.

How does LangGraph handle human-in-the-loop approvals?

Through interrupts and checkpointing: you configure the graph to pause before a sensitive node, and execution stops with the full state persisted under a thread ID. A reviewer inspects the pending action, optionally modifies state, and resumes the graph — which continues exactly where it stopped, even in a different process. This replaces the custom job-queue suspension logic you'd otherwise build.

Is LangGraph production-ready?

It's widely used in production agent systems, and the core graph, checkpointing, and interrupt mechanics are solid. The practical risks are operational: choose a persistent checkpointer backend rather than in-memory state, pin versions because the ecosystem moves quickly, and keep nodes thin so business logic stays testable outside the framework. Treat it like any young, fast-moving dependency — valuable, but versioned deliberately.

How long does it take to build a production-ready AI agent?

A convincing prototype takes days, but production-grade agents with evals, guardrails, monitoring, and integration into real systems typically take six to twelve weeks. The gap between demo and production is exactly where most pilots stall, so budget for the hardening phase up front.

Which agent framework should we use?

Framework choice matters less than evaluation and observability discipline; plenty of production teams run thin custom loops directly on the model provider's SDK. Pick based on your team's stack and tolerance for lock-in, and standardize integrations on MCP so tools are portable across frameworks.

What does an AI agent cost to run?

Agent tasks routinely consume several times the tokens of a single chat call because of tool loops and retries, so cost scales with loop length and model tier. Prompt caching, batch processing, and routing subtasks to cheaper models typically cut agent costs by 50 to 90 percent.

Bottom line: Dhairya Senjaliya ships AI — AI Agent Development projects worldwide. Book a scoping call at https://dhairyasenjaliya.com/#book-call.

Sources

Related guides

Keep up with new guides

New deep-dive guides on React Native, Python, and AI ship regularly. Subscribe via RSS or follow on LinkedIn.

Want help implementing this?

30-minute scoping call · Clear milestones · Senior engineer ownership