Graph engineering: cuándo tu agente deja de ser un bucle

Un grafo de agentes son tres cosas: un estado compartido, unos nodos que lo modifican y unas aristas que deciden qué nodo va después. Eso es todo. Lo difícil no es entenderlo, es saber cuándo tu bucle de siempre se te quedó corto.
Y la respuesta que se repite por ahí, que pases a grafo cuando tengas "varias especialidades" o necesites "paralelo y junta", es la menos útil de todas. El motivo real es más concreto y casi nadie lo menciona: la ejecución durable.
Vamos por partes, porque el vocabulario está bastante enturbiado.
Qué es un grafo de agentes
La documentación de LangGraph lo define en tres piezas, y conviene quedarse con ellas antes de nada:
- State. Una estructura de datos compartida que representa la instantánea de la aplicación. Es lo que todos los nodos leen y escriben.
- Nodes. Funciones que ejecutan lógica y actualizan el estado.
- Edges. Funciones que deciden el flujo de ejecución entre nodos.
Lo importante de esa definición es lo que dice a continuación: los nodos y las aristas pueden contener llamadas a LLM o código normal. Un nodo no tiene que ser un agente. Puede ser un if, una consulta a base de datos o un curl.
En código se ve así de aburrido, que es justo la gracia:
from langgraph.graph import StateGraph
from typing import TypedDict
class AgentState(TypedDict):
messages: list
current_tool: str
retry_count: int
def should_continue(state):
if state["retry_count"] > 3:
return "end"
elif state["current_tool"] == "search":
return "process_search"
else:
return "call_llm"
workflow = StateGraph(AgentState)
workflow.add_node("call_llm", call_llm_node)
workflow.add_node("process_search", search_node)
workflow.add_conditional_edges("call_llm", should_continue)Fíjate en should_continue. Es una función Python normal, sin ninguna IA dentro, y es la que decide el flujo. Ese es el cambio de fondo: el control deja de estar en el modelo y pasa a estar en tu código.
El vocabulario real no es "loop vs graph"
Aquí conviene parar, porque hay un término de moda que no viene de donde parece.
Si buscas "loop engineering vs graph engineering" te van a salir seis o siete artículos que dicen exactamente lo mismo, con la misma tabla comparativa, y ninguno cita una fuente. Es vocabulario de marketing de contenidos, no de ingeniería.
Anthropic, en el artículo que sirve de referencia canónica para esto, ni siquiera usa esas palabras. Distingue otra cosa:
Workflows son sistemas donde los LLM y las herramientas se orquestan mediante rutas de código predefinidas. Agents son sistemas donde los LLM dirigen dinámicamente sus propios procesos y su uso de herramientas, manteniendo el control sobre cómo realizan las tareas.
Esa sí es la distinción que importa, y no va de la forma del diagrama: va de quién decide el siguiente paso. Si lo decide tu código, es un workflow. Si lo decide el modelo, es un agente. Un grafo puede ser cualquiera de los dos, según dónde pongas las aristas condicionales.
Y de ahí salen los cinco patrones que Anthropic nombra, que son mucho más útiles que la etiqueta "graph engineering":
| Patrón | Qué hace |
|---|---|
| Prompt chaining | Descompone la tarea en pasos donde cada llamada procesa la salida de la anterior |
| Routing | Clasifica la entrada y la dirige a una tarea especializada |
| Parallelization | Divide en subtareas independientes, o corre la misma varias veces para tener diversidad |
| Orchestrator-workers | Un LLM central descompone, delega en trabajadores y sintetiza los resultados |
| Evaluator-optimizer | Un LLM genera y otro evalúa y da feedback, en bucle |
Ninguno de esos cinco necesita que digas la palabra "grafo" para implementarlo.
Un bucle ya es un grafo
Esta es la parte que la comparativa de moda se salta, y que hace que la pregunta esté mal planteada.
Un bucle es un grafo de un solo nodo con una arista que apunta a sí mismo. Y al revés: cada nodo de tu grafo puede tener un bucle dentro. La propia documentación de LangGraph dice que la combinación de nodos y aristas permite "workflows con bucles".
No son dos paradigmas rivales entre los que elegir. Uno contiene al otro. Lo que cambia no es la topología, es cuánta estructura declaras por adelantado:
- En un bucle agéntico, declaras el objetivo y dejas que el modelo decida el camino en cada vuelta.
- En un grafo, declaras el camino, o al menos las bifurcaciones posibles, y el modelo decide dentro de los carriles.
El Ralph loop es el extremo de lo primero: un while de shell, el mismo prompt cada vuelta, y el sistema de archivos como memoria. Cero estructura declarada. Funciona sorprendentemente bien para lo que funciona.
Lo que de verdad compras con un grafo
Aquí está el argumento que no vas a encontrar en las comparativas, y es el que decide en producción.
Cuando aceptas la complejidad de un grafo, lo que obtienes a cambio no es "modularidad" ni "separación de responsabilidades", que son palabras que no pagan facturas. Es esto:
Reanudar en vez de reempezar
Un grafo con checkpointer guarda el estado después de cada nodo. Si la corrida se cae en el minuto 40 de 50, reanuda desde el último checkpoint: los nodos ya completados no se reejecutan, porque sus resultados están guardados.
En un bucle, una caída a mitad significa volver a empezar. Y si cada vuelta cuesta tokens, volver a empezar cuesta dinero.
from langgraph.checkpoint.memory import MemorySaver
memory = MemorySaver()
app = workflow.compile(checkpointer=memory)Es literalmente una línea. Ese es el precio de entrada a todo lo demás.
Parar a pedir permiso
La función interrupt() detiene la ejecución dentro de un nodo, expone lo que haga falta y espera a que un humano responda:
from langgraph.types import interrupt
def review_node(state: State):
edited_content = interrupt({
"instruction": "Review and edit this content",
"content": state["generated_text"],
})
return {"generated_text": edited_content}La ejecución se reanuda después con Command(resume=...). Sin checkpoints esto no puede existir, porque no habría a dónde volver.
Si tu agente hace algo irreversible, mandar un correo, tocar producción, mover dinero, esta es la razón por la que quieres un grafo y no un bucle.
Reintentos por nodo, no globales
workflow.add_node(
"search_documentation",
search_documentation,
retry_policy=RetryPolicy(max_attempts=3),
)El nodo que llama a una API inestable reintenta tres veces. El nodo que escribe en base de datos, ninguna. En un bucle, el reintento es todo o nada.
Bifurcar desde el pasado
Los checkpoints permiten reproducir una corrida desde un punto anterior, o bifurcar cambiando el estado y ver qué habría pasado:
history = list(graph.get_state_history(config))
before_joke = next(s for s in history if s.next == ("write_joke",))
fork_config = graph.update_state(before_joke.config, values={"topic": "chickens"})
fork_result = graph.invoke(None, fork_config)Para depurar un agente que se portó raro hace tres días, esto es la diferencia entre investigar y adivinar. Con un aviso: los nodos posteriores al checkpoint sí se reejecutan, incluidas las llamadas al LLM, así que el resultado puede salir distinto.
El patrón que justifica el paso
Si tuviera que elegir uno solo para explicar por qué existen los grafos, sería orchestrator-workers, porque es el que un bucle no sabe hacer.
Un nodo planifica y decide cuántos trabajadores hacen falta, cosa que no se sabe al escribir el código. La API Send crea esas aristas en tiempo de ejecución:
from langgraph.types import Send
def assign_workers(state: State):
"""Un trabajador por cada sección del plan"""
return [Send("llm_call", {"section": s}) for s in state["sections"]]
builder.add_conditional_edges("orchestrator", assign_workers, ["llm_call"])Y como todos escriben a la vez sobre la misma clave del estado, hace falta decirle cómo combinarlas. Eso es un reducer:
import operator
from typing import Annotated
class State(TypedDict):
sections: list[Section]
completed_sections: Annotated[list, operator.add] # todos acumulan aquíSin el Annotated[list, operator.add], cada trabajador pisaría al anterior, porque el comportamiento por defecto es sobrescribir. Es el detalle que rompe la primera vez que alguien monta esto.
Cuándo NO montar un grafo
Es la parte que más falta en los artículos que venden la arquitectura, así que la digo con la cita delante. Anthropic:
Recomendamos encontrar la solución más simple posible, y aumentar la complejidad solo cuando haga falta.
Y también:
Los sistemas agénticos suelen cambiar latencia y coste por mejor rendimiento en la tarea, y deberías considerar cuándo compensa ese intercambio.
Traducido a decisiones concretas, no montes un grafo si:
- Tu tarea dura dos minutos. Reanudar no vale nada si reempezar es barato. El argumento entero de la ejecución durable se cae.
- No tienes un paso irreversible. Sin nada que aprobar,
interrupt()sobra. - El camino es siempre el mismo. Si no hay bifurcaciones reales, un grafo lineal es un
forcon ceremonia. - Todavía no sabes qué pasos hay. Declarar la estructura por adelantado exige conocerla. Al explorar, el bucle es mejor herramienta precisamente porque no te obliga a decidir.
Hay una cuarta trampa, menos evidente: montar el grafo para "estar preparado". La estructura que declaras hoy es la que tienes que mantener mañana, y la de un agente que todavía cambia cada semana envejece muy rápido.
Sin framework también se puede
Un apunte que ahorra discusiones, y viene del mismo artículo de Anthropic: recomiendan empezar con llamadas directas a la API antes que con un framework, porque muchos de estos patrones se implementan en unas pocas líneas de código.
Un routing es un if. Un prompt chaining son tres llamadas seguidas. Una parallelization es un asyncio.gather. Nada de eso necesita un grafo declarado.
Lo que sí es difícil de hacer a mano es la parte de arriba: checkpoints, reanudar tras una caída, pausar para aprobación humana y bifurcar desde el pasado. Ahí es donde un framework de grafos deja de ser ceremonia y empieza a ser infraestructura.
O sea que la pregunta útil no es "¿bucle o grafo?". Es "¿necesito persistencia entre pasos?". Si la respuesta es no, casi todo lo demás sobra.
Preguntas frecuentes
¿Qué es graph engineering?
Diseñar sistemas de agentes declarando su estructura como un grafo: un estado compartido, nodos que lo modifican y aristas que deciden el flujo. Conviene saber que el término circula sobre todo en blogs y no en la documentación de los proveedores: Anthropic habla de "workflows" frente a "agents", y LangGraph simplemente de grafos con estado.
¿Un bucle y un grafo son cosas distintas?
No son categorías excluyentes. Un bucle es un grafo de un nodo con una arista hacia sí mismo, y cada nodo de un grafo puede contener un bucle. Lo que cambia es cuánta estructura declaras por adelantado y quién decide el siguiente paso, si tu código o el modelo.
¿Cuándo paso de un bucle a un grafo?
Cuando necesites que la ejecución sobreviva a una caída, cuando haya un paso irreversible que requiera aprobación humana, o cuando el número de subtareas se decida en tiempo de ejecución. Si tu tarea dura minutos y no toca nada irreversible, el bucle es suficiente.
¿Qué es la ejecución durable en LangGraph?
Guardar el estado después de cada nodo mediante un checkpointer. Permite reanudar tras un error sin reejecutar los nodos que ya terminaron, pausar con interrupt() para aprobación humana, y reproducir o bifurcar la ejecución desde un checkpoint anterior.
¿Necesito LangGraph para esto?
No. Anthropic recomienda empezar con llamadas directas a la API, porque la mayoría de los patrones son unas pocas líneas. Lo que un framework de grafos aporta de verdad es la persistencia entre pasos: checkpoints, reanudación y aprobación humana. Si no necesitas eso, probablemente no necesites el framework.
¿Qué es un reducer y por qué me rompe el paralelismo?
Es la función que decide cómo se combinan las escrituras de varios nodos sobre la misma clave del estado. Por defecto la nueva escritura sobrescribe a la anterior, así que en ejecución paralela cada trabajador pisa al anterior. Con Annotated[list, operator.add] se acumulan en lugar de pisarse.
Fuentes
- Building Effective AI Agents, Anthropic. La referencia canónica de los cinco patrones y de la distinción entre workflows y agents.
- Graph API overview, documentación de LangGraph: State, Nodes, Edges,
Sendy reducers. - Use time travel, sobre reproducir y bifurcar desde un checkpoint.
- Interrupts, la pausa para intervención humana.
- Workflows and agents, los cinco patrones de Anthropic implementados en LangGraph.