Los agents basados en LLM que solo usan el patrón “while tool_call: execute” funcionan para tareas simples pero se desmoronan en flujos complejos: pierden contexto, hacen loops infinitos, no se pueden reanudar tras fallo. LangGraph (del equipo LangChain) propone modelar agentes como grafos de estados explícitos: nodos que hacen trabajo, edges condicionales que deciden siguiente paso, estado persistente que se puede inspeccionar y replay.
El problema con agents “simples”
Un agente básico:
while True:
response = llm.invoke(messages + [prompt])
if tool_call in response:
result = execute_tool(tool_call)
messages.append(result)
else:
return response
Problemas:
- Loops infinitos si el LLM insiste en el mismo tool.
- Sin persistencia: si falla, empiezas de cero.
- No hay control fino: no sabes en qué “paso” estás.
- Difícil de testear: caja negra.
Para flujos complejos (customer support, investigación multi-paso, procesos ETL con IA), esto escala mal.
El modelo LangGraph
LangGraph modela el agente como:
- State: objeto TypedDict con todo el contexto.
- Nodes: funciones que toman state y devuelven update parcial.
- Edges: conexiones entre nodos, con lógica condicional.
- Graph: compilación de nodos + edges.
from langgraph.graph import StateGraph, END
from typing import TypedDict
class AgentState(TypedDict):
messages: list
next_step: str
def classify(state: AgentState) -> AgentState:
# Clasificar intent
return {"next_step": "search" if needs_search else "respond"}
def search(state: AgentState) -> AgentState:
# Hacer búsqueda
return {"messages": state["messages"] + [search_result]}
def respond(state: AgentState) -> AgentState:
# Generar respuesta final
return {"messages": state["messages"] + [response]}
graph = StateGraph(AgentState)
graph.add_node("classify", classify)
graph.add_node("search", search)
graph.add_node("respond", respond)
graph.set_entry_point("classify")
graph.add_conditional_edges("classify", lambda s: s["next_step"])
graph.add_edge("search", "respond")
graph.add_edge("respond", END)
app = graph.compile()
result = app.invoke({"messages": [user_msg]})
Cada paso es explícito, testeable, observable.
Features clave
Persistent state (checkpointing)
LangGraph puede persistir el estado del grafo en cada paso a SQLite, Postgres, Redis:
from langgraph.checkpoint.postgres import PostgresSaver
checkpointer = PostgresSaver.from_conn_string("postgres://...")
app = graph.compile(checkpointer=checkpointer)
# Ejecutar con thread_id para estado persistente
config = {"configurable": {"thread_id": "user-123"}}
result = app.invoke(state, config=config)
# Luego reanudar
result = app.invoke(None, config=config) # Continúa desde último paso
Esto permite:
- Agentes de larga duración (días, semanas).
- Chat con memoria real entre sesiones.
- Recovery tras fallo.
- Human-in-the-loop: agente pausa para aprobación humana.
Streaming por paso
for event in app.stream(state, config=config):
print(event)
Obtienes updates en tiempo real de qué nodo se está ejecutando y qué devuelve. Útil para UIs interactivas.
Loops con condiciones
graph.add_conditional_edges(
"react_step",
lambda s: "continue" if not s["done"] else "END",
{"continue": "react_step", "END": END}
)
Loops explícitos con condición de parada clara.
Subgraphs
Grafos complejos pueden construirse componiendo subgrafos — reusabilidad y modularidad.
Patterns comunes
ReAct pattern clásico
graph = StateGraph(...)
graph.add_node("agent", agent_node)
graph.add_node("tool_executor", execute_tools)
def should_continue(state):
if state["messages"][-1].tool_calls:
return "continue"
return "end"
graph.add_conditional_edges("agent", should_continue, {
"continue": "tool_executor",
"end": END
})
graph.add_edge("tool_executor", "agent")
ReAct estándar pero con estado explícito y checkpointing.
Human-in-the-loop
graph.add_node("human_approval", lambda s: interrupt("Aprobar?"))
# Ejecución pausa en interrupt
# Operator aprueba/rechaza via API
app.update_state(config, {"approved": True})
app.invoke(None, config=config) # Continúa
Crítico para agentes que ejecutan acciones reales (envíos de email, transacciones bancarias).
Multi-agent colaboration
Varios grafos cooperando, cada uno con su especialidad, coordinados por un supervisor agent.
Comparación con alternativas
| Aspecto | LangGraph | LangChain AgentExecutor | CrewAI | AutoGen |
|---|---|---|---|---|
| Modelo | Grafo de estados | Loop simple | Roles de equipo | Conversaciones |
| Persistencia | Nativa | No | Manual | Limitada |
| Streaming | Sí | Sí | Sí | Sí |
| Debuggability | Alta | Baja | Media | Media |
| Curva aprendizaje | Media | Baja | Media | Media |
LangGraph es más complejo pero más robusto para producción.
Integración con LangSmith
LangSmith (observability de LangChain) visualiza runs de LangGraph:
- Ver cada nodo ejecutado.
- Input/output por paso.
- Latencias y tokens.
- Replay y debug.
Para desarrollo iterativo de agentes complejos, es prácticamente imprescindible.
Cuándo LangGraph vale la pena
Encaja en:
- Workflows multi-paso con lógica condicional compleja.
- Agentes de larga duración (minutos+).
- Human-in-the-loop (approval flows).
- Multi-agent systems.
- Production observability importante.
No encaja en:
- Chatbot simple de 1-turno.
- Tool calling sencillo (un solo round).
- Prototipos rápidos donde setup de grafo es overkill.
Limitaciones
- Learning curve: entender state + nodes + edges toma tiempo.
- Dependencia de LangChain: sigues en ecosystem LangChain (pros y cons).
- Maduración: API sigue cambiando (aunque estabilizándose).
- Python only (JS/TS tiene versión pero menos madura).
Alternativas a evaluar
- LlamaIndex Workflows: similar enfoque de workflows.
- Haystack pipelines: modelado de pipelines.
- Flowise: visual low-code para builds similares.
- Propio framework: para casos muy específicos, roll-your-own tiene sentido.
Conclusión
LangGraph es una evolución importante en cómo construir agentes LLM productivos. Su modelo explícito de estado y flujo soluciona muchos problemas que agents naïve tenían. Para producción seria con flujos complejos, human-in-the-loop, o multi-agent, es de las opciones más maduras. Para casos simples, el overhead no compensa. La integración con LangSmith para observability lo hace el pack más completo actualmente. Con el ritmo de evolución, próximas releases cerrarán las pocas asperezas actuales.
Síguenos en jacar.es para más sobre agents LLM, LangChain y arquitecturas IA.