LangGraph: grafos de estados para agentes más robustos
Actualizado: 2026-05-03
El entusiasmo con los agentes LLM se ha topado con una pared incómoda: el patrón clásico de bucle —invocar al modelo, mirar si pide una herramienta, ejecutarla y repetir— funciona en demos y se desmorona en cuanto la tarea tiene tres pasos y una condición. Los agentes pierden contexto, entran en bucles infinitos, no se pueden reanudar tras un fallo y, cuando algo sale mal, el operador se queda mirando un log plano preguntándose por qué el modelo decidió lo que decidió. LangGraph[1] aborda ese problema tratando al agente como un grafo de estados explícito en lugar de una caja negra conversacional.
Puntos clave
- LangGraph reemplaza el bucle ReAct por nodos, aristas y estado explícito tipado.
- El checkpointing sobre SQLite, Postgres o Redis habilita agentes de larga duración y recuperación ante fallos.
- El streaming por paso permite a las UIs mostrar progreso en tiempo real sin esperar el resultado final.
- Los bucles explícitos con condición de salida evitan la recursión infinita que mata los agentes naive.
- No compensa para chatbots de un turno; sí para flujos con lógica condicional no trivial o duración superior a un minuto.
Por qué los agentes “simples” se rompen
El agente tipo ReAct escrito a mano es siempre la misma plantilla: un bucle que llama al LLM con el historial de mensajes, comprueba si la respuesta contiene una llamada a herramienta, la ejecuta, concatena el resultado y vuelve a empezar. Termina cuando el modelo responde sin pedir herramientas. Esa forma es elegante sobre papel pero tiene cuatro problemas que escalan mal:
- Sin límite natural: si el modelo se obsesiona con la misma herramienta, giras indefinidamente hasta agotar tokens.
- Sin persistencia: un corte de red, un timeout o un reinicio del contenedor te devuelven al punto de partida.
- Sin observabilidad: el “paso” en el que estás es implícito, existe solo en la longitud del historial de mensajes.
- Imposible de testear por piezas: toda la lógica vive dentro del mismo bucle.
Cuando el flujo es “agente de soporte que escala a humano, investigación multipaso sobre varias fuentes, proceso ETL con validaciones intermedias”, estos problemas aparecen en la primera semana.
El modelo mental de LangGraph
LangGraph cambia la unidad de composición. En vez de un bucle que encadena llamadas, defines cuatro cosas:
- Estado: diccionario tipado que representa todo lo que el agente sabe en un momento dado.
- Nodos: funciones puras que reciben el estado y devuelven una actualización parcial.
- Aristas: conexiones incondicionales o condicionales entre nodos.
- Grafo: compilación de todo eso en un objeto ejecutable.
from langgraph.graph import StateGraph, END
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", route_from_classify)
graph.add_edge("search", "respond")
graph.add_edge("respond", END)
app = graph.compile()Cada paso del agente es ahora una función independiente, con un contrato claro de entrada y salida, testeable en aislamiento y observable desde fuera. Encaja bien con pipelines de RAG estructurado —ver Frameworks de evaluación para retrieval— donde cada paso de recuperación es un nodo distinto.
Las tres funciones que hacen el trabajo
Tres características hacen que LangGraph pague el coste de aprenderlo:
Checkpointing: LangGraph persiste el estado del grafo en cada transición sobre SQLite, Postgres o Redis. Al compilar el grafo con un checkpointer y ejecutar con un thread_id, cada paso queda guardado. Una invocación posterior con el mismo thread_id y entrada nula continúa desde el último punto. Esto habilita el patrón de humano en el bucle: el grafo se detiene en un nodo de aprobación, un operador revisa mediante una API, actualiza el estado y el grafo retoma.
Streaming por paso: el método stream emite un evento por cada nodo ejecutado con la actualización parcial del estado. Las interfaces pueden mostrar al usuario qué está haciendo el agente en cada momento sin esperar al resultado final.
Bucles explícitos con condición de salida: un nodo puede apuntar hacia sí mismo a través de una arista condicional que distingue entre “sigue” y “termina”. Es el patrón ReAct de siempre, pero con la condición de parada declarada en un solo sitio.
Comparativa con lo que había antes
| Aspecto | AgentExecutor (LangChain) | LangGraph | CrewAI / AutoGen |
|---|---|---|---|
| Persistencia | No nativa | Nativa (checkpointer) | Variable |
| Depuración | Difícil | Por nodo | Media |
| Lógica condicional | Limitada | Declarativa | Rol-based |
| Curva de aprendizaje | Baja | Media | Media |
Frente al AgentExecutor de LangChain, LangGraph gana en persistencia nativa, facilidad de depuración y capacidad para modelar lógica condicional no trivial. Frente a frameworks como CrewAI o AutoGen, LangGraph es más bajo nivel: no te da un modelo predefinido de roles, te da primitivas. La integración con LangSmith[2] para observabilidad inclina la balanza para equipos ya en el ecosistema LangChain. Ver también embeddings con nomic-embed-text para construir la capa de recuperación que alimenta los nodos de búsqueda.
Cuándo compensa y cuándo no
LangGraph paga su coste cuando el flujo tiene:
- Lógica condicional no trivial entre nodos.
- Duración del agente superior al minuto.
- Necesidad de intervención humana o aprobación en pasos intermedios.
- Observabilidad en producción como requisito duro.
No compensa para:
- Un chatbot de un turno o una llamada única a una herramienta.
- Prototipos exploratorios donde montar el grafo es más ceremonia que producto.
- Agentes que caben en quince líneas de bucle y nunca corren más de diez segundos.
La heurística práctica: si tienes que explicar a alguien del equipo “por qué el agente hizo X en el paso Y”, necesitas LangGraph. Si no, probablemente no.
Conclusión
LangGraph es una de esas bibliotecas que parecen un rodeo hasta que te enfrentas al segundo agente serio en producción. El argumento de fondo no es técnico sino organizativo: el bucle ReAct casero obliga a que la lógica del flujo, el control de errores, la persistencia y la observabilidad convivan en el mismo cuerpo de código, y eso envejece mal. Un grafo de estados separa esas capas casi por diseño, y eso tiene un valor que se nota en cada semana de mantenimiento.