Inicio / Artículos

Diseño de grafos para agentes de IA resilientes: intentos repetidos, soluciones alternativas y GraphRAG

Aprende cómo crear flujos de trabajo para agentes de IA tolerantes a fallos utilizando ramas de error explícitas, lógica de intentos repetidos, LangGraph, y determinar cuándo GraphRAG supera a RAG tradicional o a los bucles de agentes.

14 min de lectura3231 palabras

Cuando ocurren fallos: Planificación de rutas alternativas

Continuando desde donde quedó la discusión anterior, imagine que para este momento el agente de investigación financiera se ha vuelto notablemente más sofisticado.

Recuerde la pregunta de ejemplo que podría plantear un gestor de carteras, algo como preguntar por qué una acción en particular cayó tras su informe de resultados y qué riesgos merecen atención en el futuro. El gráfico puede analizar ese tipo de pregunta, extraer datos de múltiples fuentes, realizar análisis de los resultados, redactar una respuesta, verificarla y enviarla a un revisor humano cuando sea necesario; esencialmente, sigue un patrón de intervención humana.

No obstante, hay un aspecto que aún no hemos abordado: ¿qué sucede cuando se rompe un paso de ese proceso?

Imagínese que el gráfico llega a la rama responsable de los datos del mercado.

Se envía una solicitud para obtener información sobre los movimientos de precios y el volumen de operaciones, pero el proveedor de datos no responde.

En esa situación, pasar directamente a la fase Analyze como si nada hubiera pasado no es una opción viable.

Al mismo tiempo, detener completamente el proceso suele ser demasiado extremo, ya que los sistemas de nivel producción necesitan algún tipo de comportamiento de respaldo.

Por eso precisamente, el fallo merece ser tratado como una rama independiente dentro del diagrama, y no como algo secundario.

El flujo original y sencillo se ve así:

Search Market Data
        ↓
     Analyze

En su lugar, podemos reestructurarlo de la siguiente manera:

                  Search Market Data
                    /          \
                   ↓            ↓
               Success        Failure
                  ↓              ↓
               Analyze          Retry (how to handle this!?)

Con esta estructura, el diagrama indica claramente qué hacer cuando una solicitud falla.

Gestión de la lógica de intentos

Si el intento de repetición tiene éxito, el flujo de trabajo simplemente continúa como normal.

No obstante, si vuelve a fallar, podría tener más sentido pasar a una fuente de datos diferente o solicitar la revisión humana en lugar de enviar repetidamente la misma solicitud.

Aquí hay una versión más detallada de esa estructura ramificada:

                  Search Market Data
                    /          \
                   ↓            ↓
               Success        Failure
                  ↓              ↓
               Analyze         Retry
                                  ↓
                           ┌──────┴──────┐
                           ↓             ↓
                        Success       Failure
                           ↓             ↓
                        Analyze    Alternative
                                      Source

Lo importante aquí no es cuántas intentonas se permitan, sino el hecho de que el manejo de fallos está integrado en el diseño del grafo desde el principio. Como muestra el diagrama, diferentes tipos de fallos pueden llevar a rutas distintas.

Supongamos que la API de datos del mercado simplemente se agota el tiempo de espera. Reintentarlo es razonable, ya que el problema probablemente sea temporal.

Pero supongamos que la solicitud se procesa sin problemas y simplemente no devuelve nada útil para el período en cuestión. Repetir esa misma solicitud no servirá de nada.

En ese caso, es mejor consultar una fuente de datos alternativa y aprobada.

Y si aún así no se obtiene resultado, probablemente sea necesario elevar la situación a un revisor humano. Este tipo de detalles es lo que distingue un flujo de trabajo frágil de uno fiable.

La función de enrutamiento que gestiona esto podría verse así:

def route_after_market_search(state):
  if state["market_data"]:
          return "analyze"
      if state["retry_count"] < 2:
          return "retry"
      return "human_review"

Estas condiciones establecen límites claros para el grafo: se permite intentar de nuevo, pero no indefinidamente.

El mismo principio se aplica al resto del grafo, ya que pueden ocurrir muchos problemas en el proceso:

  • Un paso de recuperación puede fallar
  • Una llamada al LLM puede fallar
  • Una fuente determinada puede quedar temporalmente inaccesible
  • Una respuesta generada puede no superar la verificación de validación

En lugar de envolver toda la aplicación en un único manejador de errores masivo, se puede decidir, nodo por nodo, qué debe ocurrir justo en el punto en que algo falla.

Esto es parte de las razones por las que modelar un flujo de trabajo como un grafo resulta atractivo. Cuando ocurre un fallo, no te quedas preguntándote algo vago como “¿por qué falló el agente?”

En lugar de eso, puedes rastrear el camino exacto que siguió la ejecución y determinar con precisión dónde ocurrieron los problemas:

Understand
    ↓
Search Filings ✓
    ↓
Search Earnings ✓
    ↓
Search Market Data ✗
    ↓
Retry ✓
    ↓
Analyze
    ↓
Write
    ↓
Check

Eso te proporciona algo concreto en lo que centrarte en lugar de una caja negra.

Naturalmente, a medida que el grafo crece, gestionar todo esto manualmente comienza a requerir un esfuerzo considerable, y eso es una preocupación válida.

En ese punto te enfrentas a la lógica de ejecución, la gestión de estados, el enrutamiento condicional, el manejo de intentos repetidos, la persistencia y alguna forma de inspeccionar lo que realmente sucedió durante una ejecución determinada.

Este es precisamente el tipo de situación en la que un framework te ahorra tener que reinventar la misma maquinaria de orquestación en cada proyecto.

Ese es el vacío que LangGraph está diseñado para llenar.

LangGraph

Con un marco establecido, su flujo de trabajo puede dividirse en tareas de investigación separadas, fusionar esos resultados posteriormente, volver a intentar los pasos fallidos, hacer una pausa para que un humano pueda intervenir y mantener un registro del estado a medida que la ejecución avanza de una etapa a otra.

Por supuesto, definir ese grafo e ejecutarlo realmente sigue requiriendo esfuerzo.

Puede gestionar toda la orquestación por sí mismo, pero eso implica tener que mantener una cantidad considerable de infraestructura alrededor de su lógica de IA principal.

LangGraph está diseñado para manejar precisamente esa capa.

LangGraph es un marco creado para construir flujos de trabajo de agentes basados en grafos y con estado. En lugar de tratar a un agente como un bucle único que sigue preguntando al modelo de lenguaje qué hacer a continuación, se definen explícitamente los nodos, las transiciones entre ellos, el estado compartido y el flujo general de ejecución.

Volviendo al agente de investigación de NVIDIA mencionado anteriormente, su estructura podría esquematizarse de la siguiente manera:

                      Question
                         ↓
                    Understand
                         ↓
              ┌──────────┼──────────┐
              ↓          ↓          ↓
           Filings    Earnings    Market
              ↓          ↓          ↓
              └──────────┼──────────┘
                         ↓
                      Analyze
                         ↓
                       Write
                         ↓
                       Check
                    ↙    ↓    ↘
                Search  Rewrite  Human
                   ↓       ↓     Review
                   └───────┴───────┘
                           ↓
                          Send

Lo notable es que la estructura del grafo y la lógica de aplicación real pueden coexistir en la misma base de código.

Una implementación simplificada de LangGraph para ese mismo flujo de trabajo podría verse así:

from langgraph.graph import StateGraph, END

builder = StateGraph(ResearchState)

builder.add_node("understand", understand)
builder.add_node("search_filings", search_filings)
builder.add_node("search_earnings", search_earnings)
builder.add_node("search_market", search_market)
builder.add_node("analyze", analyze)
builder.add_node("write", write)
builder.add_node("check", check)

builder.set_entry_point("understand")

builder.add_edge("understand", "search_filings")
builder.add_edge("understand", "search_earnings")
builder.add_edge("understand", "search_market")
builder.add_edge("analyze", "write")
builder.add_edge("write", "check")

El fragmento anterior es intencionalmente mínimo para que pueda concentrarse en el modelo mental subyacente: vincular los nodos, las aristas y los conceptos de estado introducidos anteriormente en esta serie.

  • Cada nodo maneja una unidad de trabajo
  • El grafo define cómo esas unidades se conectan entre sí
  • El estado es lo que transmite información de un nodo al siguiente

Eso es realmente todo. Este modelo mental es mucho más fácil de comprender que intentar incluirlo todo en una sola instrucción para un agente masivo.

Puedes observar el gráfico en sí y comprender qué se supone que debe hacer el flujo de trabajo antes incluso de analizar cómo está implementado cada nodo individual.

Supongamos que quieres insertar un paso de aprobación humana antes de que se envíe la respuesta final: tendrías que modificar directamente la estructura del flujo de trabajo:

Check
  ↓
Human Review
  ↓
Send

No hay necesidad de ocultar ese tipo de decisión dentro de algún prompt. La estructura en sí la hace explícita y fácil de seguir para tu equipo.

¿Por qué elegir LangGraph en lugar de un bucle de agente simple?

Un bucle de agente convencional suele seguir esta estructura:

Think
  ↓
Choose Tool
  ↓
Use Tool
  ↓
Think Again
  ↓
Choose Tool
  ↓
...

En este esquema, el modelo tiene una gran libertad para decidir qué sucede a continuación. Esa flexibilidad es realmente valiosa cuando la tarea en cuestión es de naturaleza abierta.

Pero un flujo de trabajo de investigación financiera como el descrito aquí incluye varios puntos de decisión que probablemente querrá mantener bajo un control más estricto. Esta distinción es la clave del asunto.

No todo flujo de trabajo requiere un bucle de agente.

Considere algunos ejemplos:

  • Puede ser necesario que el sistema recopile pruebas específicas antes de poder generar una respuesta.
  • Puede querer que los datos del mercado y los documentos relacionados se obtengan de forma independiente.
  • Puede requerir un paso de verificación antes de que cualquier información sea enviada a un revisor humano.
  • Puede querer que el proceso se detenga automáticamente después de un número determinado de intentos.

Estas no son las decisiones que necesariamente querrá dejar a la improvisación del modelo en cada ejecución. Dentro de un bucle, no hay forma de garantizar que el modelo realice la misma llamada cada vez.

Un grafo permite integrar directamente esas restricciones en la estructura del flujo de trabajo. El modelo sigue podiendo razonar dentro de cada nodo individual, pero el sistema circundante determina a dónde puede dirigirse a continuación.

Esa es la diferencia clave que hay que tener en cuenta. El objetivo no es eliminar el razonamiento del agente, sino decidir deliberadamente dónde debe residir ese razonamiento y dónde es más adecuada una orquestación determinista.

A medida que continúas desarrollando flujos de trabajo que operan con datos financieros estructurados, surge una nueva pregunta.

Por ahora, nuestro agente obtiene documentos y cifras de diversas fuentes. Pero, ¿qué sucede cuando la información subyacente contiene conexiones que realmente son importantes?

  • Las empresas emplean ejecutivos
  • Esos ejecutivos suelen formar parte de los consejos directivos corporativos
  • Una empresa puede adquirir a otra
  • Un documento regulatorio podría mencionar una empresa completamente diferente
  • Un mismo portafolio puede incluir muchas empresas
  • Cada empresa pertenece a algún sector industrial
  • Hasta ahora, hemos tratado cada dato de forma aislada. Sin embargo, los vínculos mostrados anteriormente son difíciles de representar si su base de conocimientos no es más que un conjunto de documentos independientes.

    Esto nos lleva a otro concepto fundamental: GraphRAG.

    GraphRAG

    Hasta el momento, hemos utilizado los grafos principalmente para regular cómo se comporta el agente. Pero los grafos también pueden servir para un segundo propósito:

    organizar el conocimiento en sí.

    En nuestro ejemplo, una configuración convencional de RAG podría extraer documentos que mencionen las ganancias de NVIDIA, sus proyecciones futuras, cifras de ingresos, márgenes y la reacción del mercado.

    Ese enfoque funciona bien cuando la respuesta se encuentra principalmente dentro de unos pocos documentos relevantes. Pero las preguntas financieras no siempre están tan delimitadas.

    Una respuesta significativa a menudo depende de vincular información dispersa en varios documentos separados.

    Imagínese ahora que quiere comprender no solo lo que reportó NVIDIA, sino también cómo las distintas partes de ese informe se relacionan entre sí (que es exactamente la situación con la que nos enfrentamos).

    Es precisamente allí donde un grafo de conocimiento demuestra su utilidad.

    En lugar de almacenar el conocimiento únicamente como fragmentos de texto, podemos modelar las entidades importantes y las relaciones entre ellas:

    NVIDIA ──→ produces ──→ GPUs
       │
       ├──→ reports ──→ Earnings
       │
       ├──→ depends on ──→ Suppliers
       │
       ├──→ competes with ──→ AMD
       │
       └──→ operates in ──→ AI Infrastructure
    

    El grafo ahora captura conexiones que podrían no surgir al leer cualquier documento por separado.

    RAG en comparación con GraphRAG

    El RAG estándar suele funcionar al obtener fragmentos relevantes y proporcionárselos al modelo como contexto. Aquí hay una visión simplificada de ese flujo:

    Question
       ↓
    Retrieve relevant chunks
       ↓
    LLM
       ↓
    Answer
    

    GraphRAG introduce una capa adicional. El sistema puede aprovechar las relaciones entre entidades para determinar cuál información es realmente importante:

    Question
       ↓
    Identify entities
       ↓
    Traverse relationships
       ↓
    Retrieve relevant information
       ↓
    LLM
       ↓
    Answer
    

    Para nuestro agente de investigación financiera, esto resulta valioso cada vez que una pregunta requiere relacionar múltiples entidades o documentos al mismo tiempo.

    Supongamos que el gestor de carteras pregunta: ¿qué riesgos podrían afectar a NVIDIA si disminuye la demanda de infraestructura para IA?

    Responder bien a esta pregunta podría requerir vincular a NVIDIA con sus productos, sus clientes, sus proveedores, sus competidores, las condiciones del mercado en general y los riesgos que ya ha señalado en informes anteriores.

    Un grafo proporciona al sistema de recuperación una ruta estructurada para explorar todas esas conexiones.

                          NVIDIA
                        /   |   \
                       /    |    \
                  Products Suppliers Competitors
                     |         |         |
                     ↓         ↓         ↓
                 AI GPUs   Supply Risk    AMD
                     |
                     ↓
              AI Infrastructure
                     |
                     ↓
                   Demand
    

    A partir de ahí, el modelo puede razonar sobre todo lo obtenido de esas entidades vinculadas.

    Esto no implica que GraphRAG siempre sea mejor que RAG tradicional. La estructura adicional resulta útil especialmente cuando las relaciones entre los datos son clave para la pregunta planteada.

    Si la respuesta se encuentra de manera clara dentro de un único informe financiero, es probable que un pipeline de recuperación convencional sea suficiente.

    Si responder a la pregunta implica reunir información dispersa en muchas entidades y fuentes, un sistema basado en grafos resulta mucho más atractivo.

    También hay otra distinción importante que debe tenerse en cuenta: su grafo de flujo de trabajo y su grafo de conocimiento son dos cosas completamente diferentes.

    El grafo de flujo de trabajo responde a la pregunta de qué debe hacer el agente a continuación. El grafo de conocimiento responde a la pregunta de qué está conectado con qué dentro de los datos con los que se trabaja.

    En nuestro sistema, ambos pueden coexistir uno al lado del otro:

    WORKFLOW GRAPH:
    
    Question
       ↓
    Retrieve
       ↓
    Analyze
       ↓
    Write
       ↓
    Check
    

    Mientras que, en el fondo, la capa de recuperación opera sobre:

    KNOWLEDGE GRAPH:
    NVIDIA
     ├── Products
     ├── Suppliers
     ├── Competitors
     ├── Executives
     ├── Filings
     └── Industry
    

    Observe la división de responsabilidades: una estructura regula la ejecución, mientras que la otra organiza el conocimiento y las relaciones dentro de él.

    Una vez que estas dos ideas comienzan a reforzarse mutuamente, el agente de investigación financiera se vuelve considerablemente más capaz.

    • El flujo de trabajo determina cómo se lleva a cabo la investigación.
    • El grafo de conocimiento determina qué piezas de información están conectadas.

    Por supuesto, esto plantea una pregunta adicional: si los grafos brindan tanto control, ¿debería construirse cada flujo de trabajo como uno?

    No necesariamente.

    En muchos casos, un simple bucle de agente es todo lo que realmente necesita el problema.

    Así que, en lugar de convertir por defecto cada flujo de trabajo de IA en un grafo, vale la pena comparar directamente los dos enfoques y determinar cuándo la complejidad adicional de la ingeniería de grafos realmente rinde frutos.

    Es importante recordar que los grafos le otorgan más control, pero ese control viene acompañado de trabajo adicional: ahora debe diseñar y mantener esa estructura por sí mismo.

    Si la tarea subyacente es realmente simple, envolverla en un grafo puede hacer que el sistema sea más difícil de seguir sin ofrecerle muchos beneficios a cambio.

    Volvamos al ejemplo del agente de investigación financiera. Supongamos que el usuario pregunta algo como: resuma el último informe de resultados de NVIDIA.

    Esa es una solicitud específica y bien delimitada.

    Puedes manejarla extrayendo el informe relevante y entregándoselo al modelo para que genere un resumen:

    Question
       ↓
    Retrieve Report
       ↓
    Summarize
       ↓
    Answer
    

    No hay ramificaciones reales ni lógica complicada que gestionar. Un pipeline RAG sencillo o un bucle básico de agente serían suficientes para esto.

    Ahora compáralo con una solicitud más amplia, en la que el usuario quiere entender qué causó la caída del precio de las acciones después de los resultados, desea que ese resultado se compare con lo proyectado por los analistas, quiere una lista de riesgos que merezcan seguimiento en el futuro y desea tener la oportunidad de aprobar los hallazgos antes de que se incluyan en un informe de cartera.

    Ese es un tipo de problema completamente diferente.

    Esta versión implica varios tipos de investigación, recurre a fuentes diferentes, necesita validación, puede requerir múltiples intentos e incluye un paso de revisión humana.

    El flujo de trabajo ahora se parece más a esto:

                          Question
                             ↓
                        Understand
                             ↓
                  ┌──────────┼──────────┐
                  ↓          ↓          ↓
               Filings    Earnings    Market
                  ↓          ↓          ↓
                  └──────────┼──────────┘
                             ↓
                          Analyze
                             ↓
                           Write
                             ↓
                           Check
                        ↙    ↓    ↘
                    Search  Rewrite  Human
                       ↓       ↓     Review
                       └───────┴──────┘
                               ↓
                              Send
    

    A este nivel de complejidad, detallar explícitamente el flujo de trabajo comienza a ser beneficioso.

    Entonces, ¿cuándo es suficiente un bucle de agente?

    Un bucle de agente suele ser la opción adecuada cuando el modelo se beneficia de cierta libertad para elegir qué herramienta utilizar a continuación.

    Por ejemplo:

    Question
       ↓
    LLM decides what to do
       ↓
    Tool
       ↓
    LLM decides what to do next
       ↓
    Tool
       ↓
    Answer
    

    Cuando la tarea es exploratoria y no se puede predecir de antemano el número de pasos, esa flexibilidad es realmente valiosa.

    El agente podría decidir que necesita verificar un extracto de ingresos, luego obtener una métrica específica y después buscar más contexto. No es necesario planificar cada posible ruta con antelación.

    ¿Cuándo un grafo comienza a tener más sentido?

    Un grafo cobra sentido una vez que el flujo de trabajo cuenta con reglas realmente importantes.

    En el sistema de investigación financiera, esas reglas podrían ser:

    Retrieve evidence
          ↓
    Run analysis
          ↓
    Generate draft
          ↓
    Verify claims
          ↓
    Human review
          ↓
    Publish
    

    Se trata de restricciones a nivel de flujo de trabajo, y un grafo permite codificarlas directamente en lugar de esperar que el modelo las infiera por sí mismo.

    El compromiso

    Un grafo le brinda control, pero también implica asumir más responsabilidades arquitectónicas.

    Ahora debe considerar:

    • cómo está estructurado el estado
    • la lógica de enrutamiento
    • qué ocurre cuando algo falla
    • el comportamiento de reintentos
    • la persistencia
  • Observabilidad
  • Pruebas
  • Versionado
  • Ninguno de estos elementos es inherentemente negativo; simplemente significa que el grafo debe justificar la sobrecarga que introduce.

    En el caso del agente de investigación de NVIDIA, no tendría sentido construir todo el grafo desde el principio solo porque los grafos son interesantes.

    En lugar de eso, la estructura adicional debería introducirse únicamente cuando el flujo de trabajo lo exija realmente:

    • Comience con algo simple.
    • Agregue ramificaciones una vez que realmente sean necesarias.
    • Agregue ejecución en paralelo una vez que las tareas puedan ejecutarse de forma independiente.
    • Agregue puntos de control una vez que el flujo de trabajo necesite pausarse o recuperarse de una interrupción.
    • Agregue un paso de revisión humana una vez que la importancia del proyecto justifique esa fricción adicional.
    • Introduzca GraphRAG una vez que las relaciones dentro del conocimiento en sí comiencen a ser relevantes.

    De esa manera, el grafo existe porque el problema lo requiere, no porque esté disponible.

    Pensamientos finales

    Esta es probablemente la lección central al trabajar en este diseño.

    Un grafo no existe para hacer que un sistema de IA parezca sofisticado. Existe para facilitar la comprensión y el control del flujo de trabajo.

    El agente de investigación financiera desarrollado a partir de esta discusión ahora puede ramificarse, intentarlo de nuevo, pausarse, incluir una revisión humana e incluso aprovechar las relaciones entre los distintos conocimientos cuando sea útil hacerlo.

    Aun así, nada de esto significa que todo sistema necesite un grafo. A veces, un simple pipeline RAG es la cantidad adecuada de infraestructura. Otras veces, un bucle de agente cubre todo lo que el problema exige.

    La verdadera habilidad consiste en reconocer el punto en el que un problema se vuelve lo suficientemente complicado como para que un gráfico valga la inversión.

    Lecturas relacionadas

  • Qué significan las advertencias sobre seguridad de la IA de exinvestigadores de Anthropic para los desarrolladores — Este artículo explica por qué las advertencias de los investigadores sobre los riesgos de la IA son importantes para los desarrolladores cotidianos, y cómo la autonomía de los agentes y las brechas en su alineación deben influir en hábitos prácticos de seguridad.