Del bucle implícito al grafo
argumentarás, con una avería concreta delante, por qué un agente fiable es una máquina de estados explícita y no un while+if opaco. Sabrás qué te compra LangGraph 1.x, dónde NO te compra nada, y tendrás fijado el stack del curso.
1.1El reembolso que nadie vio venir
Conoce a Elcano: el agente de operaciones de cuenta que vas a construir y endurecer durante todo el curso. Recibe peticiones de clientes que terminan en una acción consecuente, casi siempre irreversible. "Cancela mi suscripción y reembolsa el último cargo." "Bájame al plan básico."
Elcano investiga con herramientas de solo-lectura —consulta la cuenta, los cargos, la política de reembolso—, planifica los pasos y ejecuta la acción: emite el reembolso o cambia la suscripción. Hoy está escrito como un agente ReAct a mano: un bucle que llama al modelo, ejecuta las tools que el modelo pide y vuelve a empezar.
1# ops_agent.py — Elcano, versión "bucle implícito" (baseline N0)
2MAX_PASOS = 10
3
4def agente(peticion: str) -> str:
5 mensajes = [{"role": "system", "content": SYSTEM},
6 {"role": "user", "content": peticion}]
7 for _ in range(MAX_PASOS): # contador mágico
8 salida = modelo_con_tools.invoke(mensajes) # decisión del modelo
9 mensajes.append(salida)
10 if not salida.tool_calls: # ¿terminó? implícito
11 return salida.content
12 for tc in salida.tool_calls:
13 resultado = TOOLS[tc["name"]](**tc["args"]) # ejecuta lo que sea
14 mensajes.append(_a_tool_msg(resultado, tc["id"]))
15 return "(límite de pasos alcanzado)" # termina por contadorFunciona en la demo. Después, en producción, llega esta traza. Un cliente pide un reembolso. La red tiembla, el modelo no recibe respuesta de la tool y la vuelve a pedir. emitir_reembolso se ejecuta dos veces. El cliente cobra dos reembolsos.
Abres el código para entender qué pasó. Y ahí está el problema de fondo: no puedes. El estado vive en una variable local mensajes. La decisión de reembolsar y su ejecución ocurren en la misma línea, dentro de un for. No hay forma de mirar el estado a mitad de run, ni de ver en qué punto el agente decidió tocar el dinero. Tu compañero propone subir MAX_PASOS. No es eso.
Esta lección existe para que sepas nombrar lo que falla aquí —y por qué un grafo explícito lo hace visible o imposible.
1.2Qué vas a poder hacer
Al terminar sabrás:
- Explicar por qué un
while+ifopaco esconde el estado y las transiciones que un agente fiable necesita auditar. - Distinguir qué es decisión del modelo y qué es control de flujo, sobre la traza de Elcano.
- Situar LangGraph 1.x como vehículo —y citar el criterio honesto de cuándo NO usar framework.
- Trabajar sobre el stack fijado del curso, sin perseguir APIs que cambiaron de nombre.
Necesitas saber antes:
- Qué es un agente ReAct: un modelo que alterna razonar y llamar herramientas en un bucle, hasta que decide responder.
- Cómo funciona el tool-calling: el modelo emite
tool_calls, tu código las ejecuta y le devuelve el resultado. - Python async a nivel intermedio (lo usarás de verdad en N1).
Esta lección no construye el grafo todavía. Construye el porqué. Sin él, LangGraph parece burocracia; con él, es control sobre el flujo de tu agente.
1.3Recupera
Antes de seguir, responde de memoria. No mires la pista hasta tener tu respuesta.
- En el bucle de Elcano, ¿qué estructura hace que vuelva a llamar al modelo tras ejecutar una tool?
- ¿Qué dato concreto guarda la "memoria" del agente entre vueltas del bucle?
- ¿Cómo decide el bucle que ya puede parar?
Comprueba tu respuesta
- El
for _ in range(MAX_PASOS): cada vuelta vuelve a invocar al modelo con los mensajes actualizados. El bucle es el motor del agente. - La lista
mensajes: una variable local que acumula system, user, las salidas del modelo y los resultados de tools. Esa lista es todo el estado. - Cuando el modelo deja de pedir tools (
not salida.tool_calls) devuelve su texto. Si no para, el bucle se corta por el contadorMAX_PASOS.
Quédate con esto: el estado es una variable local y la condición de parada está enterrada en un if. Volveremos a las dos.
1.4El concepto: bucle implícito frente a máquina de estados
Empecemos por nombrar las dos formas, luego por el coste real de la primera, y al final por qué LangGraph entra aquí.
El bucle implícito
Un bucle implícito es un agente cuyo control de flujo vive enterrado en while/for e if, y cuyo estado es una variable local que pasa de una iteración a otra. Implícito porque las transiciones —cuándo se llama al modelo, cuándo a una tool, cuándo se para— no tienen nombre ni existen como objeto: están disueltas en el código.
La analogía: es un GPS que solo dice "sigue" o "para", sin enseñarte el mapa. Llegas a destino las más de las veces. Pero cuando te lleva por un sitio raro, no puedes señalar el cruce donde se equivocó. Límite de la analogía: el mapa de un GPS es fijo. Tu agente decide en runtime qué cruce toma, así que necesitas el mapa de los cruces posibles, no el del camino tomado.
Qué te cuesta de verdad
El bucle de Elcano tiene cuatro costes, y los cuatro aparecieron en la avería del reembolso doble.
- Estado invisible. No puedes inspeccionar
mensajesa mitad de run sin meterprint. No hay un punto donde "leer el estado". - Transiciones sin nombre. La decisión de reembolsar y su ejecución comparten línea. No hay frontera entre el modelo decidió y el sistema actuó.
- Parada por contador, no por condición.
MAX_PASOSno es una regla de negocio. Es un fusible. Cuando salta, no sabes si el agente terminó o se rindió. - Efectos sin compuerta.
emitir_reembolsose ejecuta dentro delfor, sin un sitio donde un humano —o una guarda— pueda intervenir antes de tocar el dinero.
Estos cuatro costes no son bugs que se arreglen con más líneas. Son consecuencia de la forma. Subir MAX_PASOS no cura ninguno.
La máquina de estados explícita
La alternativa tiene nombre viejo. Una máquina de estados modela un sistema como un conjunto de estados nombrados y transiciones nombradas entre ellos. Aplicada a un agente: cada responsabilidad es un nodo (decidir, ejecutar tools, planificar) y cada paso posible es una arista (edge). El estado deja de ser una variable local: pasa a ser un objeto compartido y explícito que cada nodo lee y actualiza.
La representación, sobre Elcano, cabe en un diagrama:
1 ┌──────────┐ ¿pide tools? ┌──────────┐
2 START ───▶│ modelo │────── sí ────────▶│ tools │
3 └──────────┘ └──────────┘
4 ▲ │ no │
5 │ ▼ │
6 │ END │
7 └───────────────────────────────┘
8 (vuelve al modelo)Lee el diagrama, no el código que aún no existe. El bucle sigue ahí —modelo → tools → modelo— pero ahora cada estado tiene nombre, cada transición es una arista, y la parada es una condición explícita (¿pide tools? no → END), no un contador. El estado que antes era mensajes ahora es un objeto que puedes leer en cualquier punto del recorrido.
Ese es el enduring understanding de todo N0: un agente fiable es una máquina de estados explícita, no un bucle con suerte. Hacer explícitos el estado y las transiciones es lo que lo vuelve auditable y depurable.
Dónde entra LangGraph (y dónde no)
LangGraph es la librería que usaremos para escribir esa máquina de estados. Se diseñó para dar controllability —control explícito— sobre el flujo del agente. Harrison Chase, CEO de LangChain, lo enmarca así: el agente de producción es una "custom cognitive architecture… where there's a certain way of doing things that you generally want an agent to do… Otherwise you would just code it" (Sequoia, Training Data, 2024-25).
Lee la última frase con atención: si no, lo codificarías a mano. El grafo es el medio, no el fin. Cuando el flujo de tu agente cabe en un if, un grafo es overhead.
Por eso un dato de mercado honesto, de un análisis independiente del propio LangChain (no neutral del todo —O'Reilly tiene sus incentivos— pero sí ajeno al vendor), acompaña a este curso desde el principio. LangGraph se consolidó como "the graph-based orchestration leader" en un paisaje fragmentado (O'Reilly, The AI Agents Stack 2026, 8 jun 2026). El mismo artículo advierte, verbatim:
"Most teams pick too much framework. If your agent calls a model and a few tools, you don't need LangGraph."
Guarda esa frase. Es el ángulo que recorre el curso entero y que decides con datos en N4: qué te compra el framework aquí, y dónde sobra. En N0 te compra justo lo que Elcano necesita —estado y transiciones explícitas, auditables— porque Elcano toca dinero.
El stack, fijado
Antes de escribir una línea de grafo, fijamos el terreno. Las APIs de agentes cambian rápido; el curso se ancla a una versión concreta.
- LangGraph 1.2.6 (18 jun 2026), Python ≥ 3.10, clasificado "Production/Stable". El 1.0.0 GA salió el 17 oct 2025; antes existía la serie 0.x, que queda atrás.
- La serie 1.x mantiene compatibilidad hacia atrás. El cambio notable de 0.x→1.0: se deprecó
create_react_agent(estaba enlanggraph.prebuilt) y su funcionalidad migró alangchain.agents.create_agent. create_react_agentestá deprecado y emiteDeprecationWarning. El reemplazo vigente escreate_agent, y no es un reemplazo drop-in —cambia la firma—. Lo veremos en L4.
Si lees un tutorial de 2024 que dice "LangGraph 0.4" o que importa create_react_agent sin más, está desfasado. Trabajamos sobre 1.2.x.
1.5Míralo: dónde se esconde el bug en el bucle
Volvamos al código de Elcano. Vamos a marcar, línea a línea, dónde vive cada uno de los cuatro costes. Lee primero el bloque entero; después la anotación.
1def agente(peticion: str) -> str:
2 mensajes = [...] # (A) el ESTADO es una var local
3 for _ in range(MAX_PASOS): # (B) parada por CONTADOR
4 salida = modelo_con_tools.invoke(mensajes) # (C) DECISIÓN del modelo
5 mensajes.append(salida)
6 if not salida.tool_calls: # (D) transición implícita: ¿fin?
7 return salida.content
8 for tc in salida.tool_calls:
9 resultado = TOOLS[tc["name"]](**tc["args"]) # (E) EFECTO sin compuerta
10 mensajes.append(_a_tool_msg(resultado, tc["id"]))
11 return "(límite de pasos alcanzado)"- (A) El estado es
mensajes. Para auditarlo a mitad de run, no hay API: tendrías que parar el proceso. Cuando el reembolso se duplicó, no había forma de leer qué creía el agente en el paso 4. - (B) La parada real del bucle es el contador. Si Elcano entra en un ciclo —pide la misma tool una y otra vez—, no para por una regla; para porque se acaban los pasos. El síntoma se confunde con "tarea larga".
- (C) y (D) Aquí está la frontera que el código borra: (C) es decisión del modelo, (D) es control de flujo. En el bucle comparten cuerpo. No puedes intervenir entre "el modelo decidió reembolsar" y "el sistema reembolsó".
- (E) El efecto irreversible se ejecuta en plena iteración. No hay un nodo separado donde meter, en N1, un gate de aprobación humana o una guarda de idempotencia. Tendrías que romper el bucle para insertarlo.
Self-explanation —respóndela tú antes de seguir: ¿por qué subir MAX_PASOS no arregla el reembolso doble?
Razónalo y comprueba
Porque el reembolso doble no es un problema de cuántos pasos. Es un problema de forma: el efecto irreversible vive dentro del bucle, sin un punto de control antes de ejecutarse. El reintento de la tool ocurre sin que nadie distinga "ya lo hice" de "hazlo". MAX_PASOS solo cambia cuándo se rinde el bucle. La cura es estructural: separar la decisión (un nodo) de la ejecución (otro nodo) y hacer el efecto idempotente o ponerlo tras una compuerta. Eso es lo que N0 prepara y N1 ejecuta.
1.6Hazlo tú
Ejercicio — nombra el estado y las transiciones
Vas a traducir el bucle a la lengua de la máquina de estados, sin escribir código todavía. Sobre el agente() de Elcano, responde:
- ¿Qué es el estado? Lista los datos que sobreviven de una vuelta del bucle a la siguiente.
- ¿Cuántos nodos —responsabilidades únicas— ves? Nómbralos.
- ¿Qué transiciones hay entre esos nodos, y cuál de ellas es condicional (depende de una decisión)?
Comprueba tu respuesta
- Estado: la conversación (
mensajes: system, petición, salidas del modelo, resultados de tools). En cuanto Elcano planifique, el estado incluirá también el plan y los pasos hechos —lo tipas en L2—. - Dos nodos como mínimo: un nodo modelo (decide: responder o pedir tools) y un nodo tools (ejecuta las tools pedidas). Es la responsabilidad única que el bucle mezclaba.
- Transiciones:
START → modelo; demodelosale una transición condicional (¿pidió tools? →tools, o no →END); ytools → modelo(el ciclo). La condicional es la que reemplaza alif not salida.tool_calls.
Si nombraste exactamente estos dos nodos y la transición condicional, ya tienes el grafo de C0 en la cabeza. Lo construyes en L3 y L4.
Elaborative interrogation —respóndela antes de leer: ¿por qué separar "modelo" y "tools" en dos nodos distintos importa para un agente que toca dinero, y no solo por estética?
Ver razonamiento
Porque la frontera entre nodos es exactamente donde puedes insertar control. Con "decidir" y "ejecutar" en nodos separados, la arista entre ellos es un sitio físico donde, en N1, pones el gate de aprobación humana antes de emitir_reembolso. En el bucle, esa frontera no existe: decisión y efecto comparten línea, así que no hay dónde colgar la compuerta. La separación no es orden; es la precondición de poder controlar el efecto irreversible.
1.7Comprueba
Sin pistas. Cuatro afirmaciones sobre el bucle implícito y la máquina de estados. Marca verdadera o falsa y di por qué.
A. "El bucle de Elcano se arregla subiendo MAX_PASOS a 50."
B. "En un grafo, la parada del ciclo modelo↔tools es una condición explícita, no un contador."
C. "LangGraph conviene siempre que un agente llame a un modelo y una herramienta."
D. "El estado de un agente-bucle vive en una variable local, y por eso no puedes auditarlo a mitad de run sin parar el proceso."
Ver respuesta razonada
A es falsa. El contador no toca ninguno de los cuatro costes estructurales. El reembolso doble nace de un efecto sin compuerta dentro del bucle; más pasos no lo curan (§1.5).
B es verdadera. El ciclo termina cuando el modelo deja de pedir tools y la transición condicional enruta a END. Es una condición de la lógica, no un fusible.
C es falsa. Es el error contrario, y cuesta dinero igual. O'Reilly lo dice: "if your agent calls a model and a few tools, you don't need LangGraph" (8 jun 2026). El grafo te compra control cuando hay estado, ciclos o efectos consecuentes; cuando no los hay, es overhead.
D es verdadera. El estado es mensajes, una local. No hay API para leerlo en el paso 4; tendrías que detener el proceso e instrumentar a mano (§1.5).
Feedback formativo:
- Si acertaste las cuatro: dominas el núcleo de N0 —el problema no es de tamaño, es de forma, y el framework es un medio con coste—. En L3 conviertes este modelo mental en un
StateGraphreal. - Si marcaste C como verdadera: es el sesgo más caro del curso. Reaprende la cita de O'Reilly: el framework se justifica por estado/ciclos/efectos, no por usar tools. Lo decidirás con datos en N4.
- Si fallaste A o B: confundiste el síntoma (el bucle no para) con la causa (la parada es un contador, no una condición). Vuelve a §1.4, "Qué te cuesta de verdad", y al diagrama.
1.8Conecta
Vuelve al reembolso doble del §1.1. La cura no era subir el contador. Era cambiar la forma: separar decidir de ejecutar, dar nombre a las transiciones, hacer el estado legible. Eso es una máquina de estados, y LangGraph es como la escribimos.
Lo que viene en N0 desmonta el bucle pieza a pieza:
- En L2 dejas de tener
mensajescomo variable local: tipas el estado de Elcano y decides, campo a campo, qué se acumula y qué se reescribe. - En L3 montas el grafo: nodos, edges, la transición condicional y el ciclo que termina por condición.
- En L4 reescribes este mismo
agente()como grafo y lo haces inspeccionable constream. Ese es el entregable de C0.
Y esto es lo que cambia al cerrar el nivel: hoy tienes una anécdota —"el reembolso se duplicó y no sé por qué"—. Al final de N0 tendrás un grafo tipado y auditable donde ese fallo es visible en la traza, o imposible por construcción. Aún sin persistencia ni gate humano: esos son N1. N0 te da la estructura sobre la que todo lo demás se apoya.
1.9Reflexiona
Tómate dos minutos. Estas preguntas consolidan más que releer.
- Con tus palabras: ¿qué distingue un agente que "funciona en la demo" de uno auditable en producción?
- ¿Qué le dirías a un compañero que propone subir
MAX_PASOSpara arreglar un agente que se duplica? - ¿Qué sigue sin estar claro? Si es "¿cómo se ve esto en código LangGraph?", es la pregunta correcta —la responden L3 y L4—.
Referencia rápida
- Bucle implícito: control de flujo enterrado en
while/if, estado en variable local. Cuatro costes: estado invisible, transiciones sin nombre, parada por contador, efectos sin compuerta. - Máquina de estados explícita: nodos (responsabilidades), edges (transiciones), estado compartido y legible. El enduring understanding de N0.
- LangGraph: vehículo para escribir esa máquina; da controllability sobre el flujo (Harrison Chase, Sequoia). El grafo es el medio, no el fin.
- Cuándo NO: "if your agent calls a model and a few tools, you don't need LangGraph" (O'Reilly, 8 jun 2026). Se decide con datos en N4.
- Stack del curso: LangGraph 1.2.6 (jun 2026), Python ≥ 3.10; 1.0 GA oct 2025; serie 1.x compatible hacia atrás.
create_react_agentdeprecado →create_agent(no drop-in). - No usar nunca: "LangGraph 0.4";
create_react_agentcomo si fuera el camino vigente; subir el contador como arreglo de un efecto duplicado.