LangChain chains are perfect for A → B → C flows. But production applications need:
State: A typed dictionary that persists across all nodes. It's the
working memory of the workflow.
Nodes: Python functions that receive the state and return an updated state.
They can call LLMs, tools, databases, or any other operation.
Edges: Connections between nodes. They can be direct (A always goes to B) or
conditional (depending on the state, it goes to B, C, or D).
Checkpointing: LangGraph can save state to Redis or PostgreSQL to
pause, resume, debug, and roll back to any point.
The most common pattern: the agent generates a response, evaluates it, and if it's not good
enough, improves it. The graph has 3 nodes: generate → reflect → [if OK: END | if not: generate].
Used in: code generation, legal analysis, and diagnostics where accuracy is critical.
A router agent analyzes the query and directs it to the right specialist:
For high-impact actions (transfers, mass communications, critical changes),
LangGraph supports pausing for human approval. The flow reaches the
wait_for_approval node, saves the state via checkpointing, and waits.
A human reviews and approves. The flow resumes exactly where it left off.
Critical for compliance in banking, healthcare, and government.
# LangGraph: Agent with a reflection cycle
from langgraph.graph import StateGraph, END
from typing import TypedDict
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-sonnet-4-6")
class AgentState(TypedDict):
task: str
draft: str
iterations: int
approved: bool
def generate(state: AgentState) -> AgentState:
response = llm.invoke(f"Complete: {state['task']}")
return {**state, "draft": response.content, "iterations": state["iterations"] + 1}
def reflect(state: AgentState) -> AgentState:
feedback = llm.invoke(
f"Evaluate: {state['draft']}\nRespond only APPROVED or IMPROVE"
)
approved = "APPROVED" in feedback.content or state["iterations"] >= 3
return {**state, "approved": approved}
def route(state: AgentState) -> str:
return END if state["approved"] else "generate"
graph = StateGraph(AgentState)
graph.add_node("generate", generate)
graph.add_node("reflect", reflect)
graph.set_entry_point("generate")
graph.add_edge("generate", "reflect")
graph.add_conditional_edges("reflect", route, {"generate": "generate", END: END})
app = graph.compile()
result = app.invoke({"task": "Write a welcome email", "draft": "", "iterations": 0, "approved": False})
print(result["draft"])Carlos Montiel is an enterprise AI solutions architect with experience in LLMs, Agents, RAG, and orchestration in Guatemala and Latin America.
Contact Carlos Montiel