Módulo 7: Flujos Avanzados

Introducción: Workflows Complejos del Mundo Real

Descripción

Tu Research Agent v1 funciona. Recibe un tema, descompone en sub-queries, busca en paralelo, sintetiza un reporte. En el happy path, es impecable. Pero el happy path no existe en producción.

Ejecuta tu agente contra una API de búsqueda real durante un día completo. Esto es lo que vas a encontrar:

  • A las 2:47 PM, la API devuelve 429 Too Many Requests. Tu agente crashea.
  • A las 3:12 PM, una fuente tarda 15 segundos en responder. Tu agente se queda esperando.
  • A las 4:05 PM, un servicio externo está caído. Tu agente retorna un error sin resultados parciales — aunque las otras dos fuentes respondieron perfectamente.

Nada de esto es un bug en tu código. Es la realidad de sistemas que dependen de APIs externas, redes inestables, y servicios de terceros. El agente que construiste en el Módulo 6 hace todo lo que le pediste. Lo que no hace es sobrevivir al mundo real.

Este módulo cierra esa brecha. Vas a agregar los patrones que convierten un prototipo funcional en un sistema que un equipo puede poner en producción sin miedo.


¿Dónde estamos en la guía?

Este es el Módulo 7 de la guía LangChain & LangGraph: From Chains to Agents. Es el último módulo del Bloque 2 (LangGraph Fundamentals).

Bloque 1: LangChain Core (Módulos 1-4)           ✅ Completado
Bloque 2: LangGraph Fundamentals (Módulos 5-7)   ← ESTÁS AQUÍ (Módulo 7)
Bloque 3: LangGraph Avanzado (Módulos 8-10)
Bloque 4: Producción (Módulos 11-12)
Tu progreso:

Bloque 1 — LangChain Core                   ✅ Completado
    │
    │  Módulo 1: Modelos y Proveedores       ✅
    │  Módulo 2: Tools y Tool Calling        ✅
    │  Módulo 3: Agents (create_agent)       ✅
    │  Módulo 4: Middleware y Customización   ✅
    │
    ▼
Bloque 2 — LangGraph Fundamentals
    │
    │  Módulo 5: Introducción a LangGraph    ✅ Completado
    │  Módulo 6: Functional API              ✅ Completado
    │  Módulo 7: Flujos Avanzados            ← ESTÁS AQUÍ
    │
    ▼
Bloques 3-4 — Avanzado + Producción         🔒

En el Módulo 5 dominaste la Graph API: StateGraph, nodos, edges, conditional edges, estado tipado. En el Módulo 6 aprendiste la Functional API: @entrypoint, @task, control flow nativo, y construiste el Research Agent v1. Ahora agregas los patrones que hacen ese agente resistente a fallos, rápido, y modular.


El puente: de "funciona" a "funciona en el mundo real"

Lo que ya sabes hacer

Después de los Módulos 5 y 6, puedes:

  • ✅ Construir grafos con StateGraph, nodos tipados, conditional edges
  • ✅ Crear workflows con @entrypoint y @task
  • ✅ Usar control flow de Python (if/else, for, try/except) dentro de entrypoints
  • ✅ Ejecutar tasks en paralelo con Futures
  • ✅ Combinar Graph API y Functional API en el mismo proyecto
  • ✅ Construir un agente end-to-end (Research Agent v1)

Lo que falta

Sabes construir grafos y workflows funcionales. Pero producción no es limpio — las APIs fallan, las búsquedas tardan demasiado, la lógica se complica, y los errores se propagan de formas que no anticipaste. Lo que falta no es conocimiento de LangGraph. Es conocimiento de ingeniería de sistemas aplicado a LangGraph.


Los problemas reales que motivan este módulo

Cada patrón que aprenderás aquí nace de un problema concreto. No son "features nice-to-have" — son soluciones a problemas que vas a enfrentar la primera semana que tu agente esté en producción.

Problema 1: Tu API de búsqueda devuelve 429 Too Many Requests

Estás haciendo 50 búsquedas por minuto. La API tiene un rate limit de 30 por minuto. A partir de la búsqueda 31, recibes 429 Too Many Requests. Sin retry, tu agente crashea y el usuario ve un error. Con retry inmediato, haces 20 requests más en un segundo — empeoras el problema. Lo que necesitas es retry con backoff exponencial: esperar 1 segundo, luego 2, luego 4, con jitter aleatorio para no sincronizar con otros clientes.

Solución: Ciclos y retry patterns (Cápsula 02)

Problema 2: Buscar en 3 fuentes secuencialmente toma 9 segundos

Tu agente busca en web, papers académicos, y noticias. Cada fuente tarda ~3 segundos. Secuencialmente: 3 + 3 + 3 = 9 segundos. Tu usuario espera 9 segundos mirando una pantalla vacía. Pero las tres búsquedas son independientes — no hay razón para esperar a que una termine antes de lanzar la siguiente.

Solución: Branching y merge (Cápsula 03) — ejecutas las 3 en paralelo: ~3 segundos total

Problema 3: El patrón "buscar + resumir" se repite para cada fuente

Para cada fuente haces lo mismo: llamar a la API, parsear la respuesta, extraer los puntos clave, generar un resumen parcial. Esa secuencia de 4 pasos la repites 3 veces (una por fuente). Si la copias y pegas, tienes 12 nodos con lógica duplicada. Si la fuente de papers necesita un parser diferente, tienes que encontrar y modificar los nodos correctos entre los 12.

Solución: Subgraphs (Cápsula 04) — encapsulas "buscar + resumir" en un subgrafo reutilizable

Problema 4: Una fuente está completamente caída

La API de papers académicos lleva 3 horas devolviendo 503 Service Unavailable. Tus retries se agotan. Sin fallback, tu agente devuelve un error completo — aunque web y noticias respondieron perfectamente con resultados útiles. El usuario no obtiene nada cuando podría obtener un reporte parcial con 2 de 3 fuentes.

Solución: Error handling y graceful degradation (Cápsulas 05-06) — tu agente retorna resultados parciales con una nota explicando qué fuente no estuvo disponible


Los patrones que cubre este módulo

PatrónProblema que resuelveImpacto
Ciclos y retryAPIs que fallan intermitentementeEl agente se recupera automáticamente de errores transitorios
Branching y mergeBúsquedas secuenciales lentasEjecución 3x más rápida con paralelismo
SubgraphsLógica duplicada entre fuentesComposición modular, un cambio afecta todos los usos
Map-reduceProcesar colecciones en paraleloEscalable a N fuentes sin cambiar la topología
Error handlingFallos que crashean el sistema completoGraceful degradation con resultados parciales
Patterns de producciónTimeouts, rate limits, loggingSistema observable y controlable

Mapa del módulo

CápsulaTemaQué aprenderás
01IntroducciónContexto, motivación, roadmap, conexión con el proyecto (esta cápsula)
02Ciclos y loops: retry patternsCiclos en grafos, retry con backoff exponencial + jitter, recursion_limit, StateGraph vs Functional API
03Branching y merge: ejecución paralelaFan-out/fan-in, Send API, parallel branches, merge de resultados, deduplicación
04Subgraphs: composición modularGrafos como nodos, estado compartido, encapsulación de lógica, reutilización
05Map-reduce: procesar coleccionesSend API para colecciones dinámicas, map paralelo, reduce con aggregation
06Error handling y fallback patternsTry/except en grafos, fallback nodes, graceful degradation, circuit breaker
07Patterns de producciónTimeouts por nodo, rate limiting interno, structured logging, health checks
08Proyecto: Research Agent v2Integrar retry, branching paralelo, y error handling en el Research Agent

Flujo de aprendizaje: Empiezas con el patrón más inmediato — retry cuando una API falla (02). Luego aceleras con ejecución paralela (03). Con parallelismo dominado, encapsulas lógica repetida en subgraphs (04) y escalas a colecciones con map-reduce (05). Error handling (06) se integra en todos los patrones anteriores, no es un tema aislado. Patterns de producción (07) agrega la capa final de observabilidad. En la cápsula 08, todo converge en el Research Agent v2.


El proyecto evoluciona: Research Agent v1 → v2

Este módulo no reescribe el Research Agent. Lo mejora. Cada cambio es una capa sobre el código que ya escribiste en el Módulo 6.

Antes (Módulo 6 — v1)

@entrypoint()
def research_agent(inputs: dict) -> dict:
    query = inputs["query"]

    # Descomponer en sub-queries
    sub_queries = decompose_query(query).result()

    # Buscar secuencialmente — una fuente a la vez
    all_results = []
    for sq in sub_queries:
        result = search_source(sq).result()  # Bloquea hasta completar
        all_results.append(result)

    # Sintetizar reporte
    report = synthesize_report(all_results).result()
    return report

Problemas:

  • ❌ Búsqueda secuencial — si cada fuente tarda 3s, 3 fuentes = 9s
  • ❌ Sin retry — si una API devuelve 429, el agente crashea
  • ❌ Sin fallback — si una fuente está caída, todo falla
  • ❌ Sin timeouts — una fuente lenta bloquea todo el pipeline
  • ❌ Sin logging — no sabes dónde falló ni cuánto tardó cada paso

Después (Módulo 7 — v2)

@entrypoint()
def research_agent(inputs: dict) -> dict:
    query = inputs["query"]

    # Descomponer en sub-queries
    sub_queries = decompose_query(query).result()

    # Buscar en paralelo — todas las fuentes simultáneamente
    search_futures = [search_with_retry(sq) for sq in sub_queries]
    results = []
    for future in search_futures:
        try:
            results.append(future.result())
        except SourceUnavailableError:
            results.append(partial_result(future.source, reason="unavailable"))

    # Sintetizar con resultados parciales si es necesario
    report = synthesize_report(results).result()
    return report

Mejoras:

  • ✅ Búsqueda paralela — 3 fuentes en ~3s (3x más rápido)
  • ✅ Retry con backoff — reintentos automáticos ante errores transitorios
  • ✅ Graceful degradation — si una fuente falla, retorna resultados parciales
  • ✅ Timeouts por fuente — ninguna fuente lenta bloquea el pipeline completo
  • ✅ Structured logging — cada paso registra duración, errores, y resultados

El código del Módulo 6 sigue ahí. Lo que cambia es cómo ejecutas la búsqueda (paralelo en vez de secuencial), cómo manejas errores (retry + fallback en vez de crash), y cómo observas el sistema (logging en vez de silencio).


Conexión con el Bloque 3: lo que viene después

El Módulo 7 cierra el Bloque 2 (LangGraph Fundamentals). Después de este módulo, tu Research Agent es robusto y rápido. Lo que todavía no tiene:

Bloque 3MóduloQué agrega al Research Agent
LangGraph AvanzadoM8: Memoria y PersistenciaSi el agente crashea a mitad de una investigación, resume donde quedó. Recuerda investigaciones anteriores entre sesiones.
LangGraph AvanzadoM9: Human-in-the-LoopAntes de ejecutar búsquedas costosas, pide aprobación humana. El usuario puede modificar sub-queries antes de que se ejecuten.
LangGraph AvanzadoM10: Multi-Agent SystemsEn vez de un solo agente que hace todo, un equipo: Researcher busca, Analyst analiza, Writer redacta, Supervisor coordina.
Módulo 7 (tú estás aquí):
    Research Agent v2 — robusto, paralelo, con error handling
        │
        ▼
Módulo 8: + Persistencia
    El agente guarda estado. Puede resumir si crashea.
        │
        ▼
Módulo 9: + Aprobación humana
    El agente pide permiso antes de acciones costosas.
        │
        ▼
Módulo 10: + Multi-agente
    Un equipo de agentes especializados con supervisor.

Para que la persistencia del M8 funcione, tu agente necesita manejar errores correctamente (si crashea con un estado corrupto, resumir no sirve). Para que human-in-the-loop del M9 funcione, tu agente necesita estar diseñado con pausas y continuaciones (que los subgraphs facilitan). Para que multi-agent del M10 funcione, tu agente necesita ser modular (que los subgraphs habilitan).

Este módulo no es solo "agregar robustez." Es construir las bases técnicas que hacen posibles los próximos tres módulos.


Setup técnico

Prerequisitos

Antes de continuar, verifica que tienes:

  • Módulos 5 y 6 completados — sabes construir grafos con StateGraph y workflows con Functional API
  • Research Agent v1 funcionando — el proyecto del Módulo 6 ejecuta end-to-end
  • Python 3.11+ instalado
  • ✅ Al menos una API key de un proveedor (OpenAI recomendado)

Instalación

Si completaste los Módulos 5-6, ya tienes todo instalado. Verifica:

pip install langgraph langchain-openai python-dotenv

No hay paquetes nuevos en este módulo. Los patrones avanzados (retry, branching, subgraphs, map-reduce) son parte de langgraph core.

Paquetes nuevos de la biblioteca estándar

Este módulo usa dos paquetes de la biblioteca estándar de Python que no usaste en los módulos anteriores:

PaquetePara qué lo usas en este módulo
timetime.sleep() para implementar backoff entre reintentos
randomrandom.uniform() para agregar jitter al backoff

No necesitas instalar nada — son parte de Python. Pero los vas a usar constantemente en las cápsulas de retry y branching.

Verificar que todo funciona

import time
import random
from typing import TypedDict, Annotated
import operator
from langgraph.graph import StateGraph, START, END
from langgraph.func import entrypoint, task

print(f"time: {time.__name__}")
print(f"random: {random.__name__}")
print(f"StateGraph: {StateGraph.__name__}")
print(f"entrypoint: {entrypoint.__name__}")
print(f"task: {task.__name__}")
print("Setup completo para Módulo 7")
# Output esperado:
# time: time
# random: random
# StateGraph: StateGraph
# entrypoint: entrypoint
# task: task
# Setup completo para Módulo 7

Ambas APIs en juego

En este módulo vas a usar tanto la Graph API como la Functional API. Algunos patrones (ciclos, branching con Send API) se expresan naturalmente en StateGraph. Otros (retry con while loop) se expresan mejor con la Functional API. Parte del aprendizaje es desarrollar criterio sobre cuándo usar cada una.

PatrónAPI recomendadaPor qué
Ciclos/retryAmbasStateGraph si el retry es visible; Functional si es interno
Branching (Send API)StateGraphLa Send API es una feature de la Graph API
SubgraphsStateGraphComposición de grafos es un concepto de la Graph API
Map-reduceStateGraphSend API para fan-out dinámico
Error handlingAmbastry/except nativo en Functional; fallback nodes en StateGraph
Timeouts, loggingAmbasSon patrones de código, no de topología

Qué NO cubre este módulo

  • Persistencia y checkpointing avanzado — Se cubre en Módulo 8. Aquí mencionarás checkpoints como contexto, pero no los implementas en profundidad.
  • Human-in-the-loop (interrupts, aprobaciones) — Se cubre en Módulo 9. Aquí diseñas el agente para que sea "pausable," pero no implementas los interrupts.
  • Multi-agent systems — Se cubre en Módulo 10. Aquí construyes subgraphs modulares que después se convertirán en agentes independientes.
  • LangSmith y observabilidad completa — Se cubre en Módulo 12. Aquí agregas structured logging básico, pero la instrumentación completa viene después.
  • Deployment — Los patterns de producción de este módulo son a nivel de código (timeouts, rate limiting, logging). El deployment a infraestructura es tema del Módulo 12.

Evidencia de éxito

Al terminar este módulo, sabrás que tuviste éxito si:

  • ✅ Puedes implementar un ciclo de retry con backoff exponencial y jitter — y explicar por qué retry sin backoff es un anti-patrón
  • ✅ Tu agente busca en 3 fuentes en paralelo y toma ~3s en vez de ~9s
  • ✅ Si una fuente está caída, tu agente retorna resultados parciales con las fuentes que sí respondieron
  • ✅ Puedes encapsular lógica repetida en subgraphs y reutilizarla
  • ✅ Tu Research Agent v2 no crashea ante errores transitorios — retries, degrada gracefully, y loggea qué pasó
  • ✅ Sabes cuándo usar StateGraph vs Functional API para cada patrón

El mindset de este módulo: ingeniería de sistemas

Los Módulos 5 y 6 enseñaron herramientas: StateGraph, Functional API, nodos, edges, tasks, entrypoints. Este módulo enseña pensamiento de sistemas.

La diferencia:

  • Herramientas: "¿Cómo hago un retry en LangGraph?"
  • Pensamiento de sistemas: "Mi agente depende de 3 APIs externas. ¿Cuál es mi failure budget? ¿Qué pasa si dos de tres fallan? ¿Cuánto puede esperar el usuario? ¿Qué le muestro mientras espera?"

Cada patrón de este módulo responde una pregunta de ingeniería, no una pregunta de API. El retry no es "una feature de LangGraph" — es un principio de sistemas distribuidos que implementas usando LangGraph. El branching paralelo no es "una optimización elegante" — es la diferencia entre 3 segundos y 9 segundos de latencia que tus usuarios van a notar.

Piensa como ingeniero de sistemas. Las herramientas son el medio, no el fin.

Las preguntas que vas a aprender a responder

Antes de este módulo, tu proceso de diseño era: "¿Qué nodos necesito? ¿Cómo los conecto?" Después de este módulo, tu proceso incluirá:

Pregunta de ingenieríaPatrón que la responde
"¿Qué pasa si la API X no responde?"Retry con backoff → fallback
"¿Cuánto puede esperar el usuario máximo?"Timeout budget por operación
"¿Puedo hacer estas operaciones simultáneamente?"Branching paralelo (fan-out/fan-in)
"¿Esta lógica se repite en varios lugares?"Subgraph reutilizable
"¿Qué le muestro al usuario si fallo parcialmente?"Graceful degradation
"¿Cómo sé que mi agente está sano en producción?"Structured logging + health checks

Estas preguntas no son específicas de LangGraph. Son preguntas que todo ingeniero de sistemas se hace al diseñar un servicio. Lo que cambia es cómo las respondes — usando grafos, nodos, y conditional edges en vez de middleware HTTP o circuit breakers a nivel de infraestructura.

El error más común: optimizar el happy path

Tu Research Agent v1 tiene un happy path perfecto: descompone, busca, sintetiza. El reporte sale impecable. Y el instinto natural es pulir ese happy path — mejor prompts, mejor formato, más fuentes.

Resiste ese instinto. Un sistema que funciona perfectamente el 95% del tiempo pero explota el 5% restante no está listo para producción. Ese 5% es donde los usuarios pierden confianza. Es donde tu sistema se gana la reputación de "inestable."

Este módulo se enfoca en el 5%. En que tu agente sea predecible, no solo en el mejor caso, sino también en el peor. El happy path ya funciona. Ahora haz que el unhappy path sea aceptable.


Resumen

  • Estás en el Módulo 7 de 12, cerrando el Bloque 2 (LangGraph Fundamentals). Después de los Módulos 5-6, sabes construir grafos y workflows funcionales. Este módulo agrega los patrones de producción
  • Cuatro problemas reales motivan este módulo: APIs que devuelven 429 (→ retry), búsquedas secuenciales lentas (→ branching paralelo), lógica duplicada entre fuentes (→ subgraphs), fuentes caídas que crashean todo (→ graceful degradation)
  • El Research Agent evoluciona de v1 (secuencial, sin error handling, crashea ante fallos) a v2 (paralelo, retry automático, degradación elegante). El código del M6 sigue ahí — este módulo agrega capas encima
  • Seis patrones: ciclos/retry, branching/merge, subgraphs, map-reduce, error handling, patterns de producción. Cada uno nace de un problema concreto
  • Conexión con Bloque 3: los patrones de este módulo son prerequisitos técnicos para memoria (M8), human-in-the-loop (M9), y multi-agent (M10)
  • Ambas APIs en juego: algunos patrones se expresan mejor en StateGraph (branching, subgraphs) y otros en Functional API (retry). Parte del aprendizaje es desarrollar criterio sobre cuándo usar cada una
  • El mindset: piensa como ingeniero de sistemas, no como usuario de API. Los patrones son principios de ingeniería implementados con LangGraph

Recursos adicionales

  1. LangGraph — Concepts: Cycles — Documentación oficial sobre ciclos y recursion_limit en LangGraph
  2. LangGraph — How to create branches for parallel node execution — Guía oficial de fan-out/fan-in con Send API
  3. LangGraph — How to add and use subgraphs — Guía oficial para componer grafos dentro de grafos
  4. LangGraph — How to create map-reduce branches — Guía oficial de map-reduce con Send API
  5. Exponential Backoff and Jitter (AWS Architecture Blog) — El artículo de referencia sobre backoff con jitter. Lectura obligatoria
  6. Release It! — Michael Nygard — El libro que popularizó circuit breakers y patterns de estabilidad. Contexto avanzado

Módulo 7 — LangChain & LangGraph: From Chains to Agents

Siguiente cápsula: Ciclos y Loops: Retry Patterns — tu API de búsqueda falla 10% de las veces. Vas a implementar retry con backoff exponencial + jitter en StateGraph y Functional API, y entenderás por qué retry sin backoff es un anti-patrón que amplifica los problemas en vez de resolverlos.

Cápsula anterior: Proyecto Evolutivo: Research Agent Base (v1) — el agente funcional end-to-end que ahora vas a hacer robusto y rápido.