Saltar al contenido

Lección 1 de 17 · Lectura y práctica

Diseña tu primer grafo de agente con nodos y aristas

Concepto claveEn LangGraph, un grafo de agente es una representación visual y programática de cómo un agente de IA toma decisiones secuenciales. Imagina que estás construyendo un asistente virtual para un banco: el grafo define.

Del concepto a la práctica

Taller de esta lección

Un grafo útil separa la decisión de la acción: el router lee el estado y el nodo posterior ejecuta una responsabilidad concreta. Para una solicitud de soporte, usa mensaje, intencion y respuesta, no un diccionario cambiante en cada paso.

Ejemplo resuelto

python
def clasificar(s):
    return {"intencion": "saldo" if "saldo" in s["mensaje"].lower() else "otro"}
def responder(s):
    return {"respuesta": "Consulta de saldo simulada; no se accede a cuentas"}

La ruta saldo va a responder; otro termina con una respuesta de ayuda.

Pruébalo

  1. Define el estado inicial con mensaje="Quiero ver mi saldo".

  2. Ejecuta clasificar y conserva todos los campos existentes.

  3. Enruta solo cuando intencion == "saldo".

  4. Registra nodo de entrada, ruta y salida.

Error frecuente: hacer que el router consulte datos y cambie la respuesta. Corrígelo devolviendo únicamente una etiqueta de ruta.

Ejercicio: prueba también mensaje="Necesito cambiar mi correo". Resultado esperado: intencion="otro" y ninguna ejecución de responder.

Comprueba tu resultado

Verifica que el estado final contiene la intención, que la ruta coincide con ella y que cada nodo aparece una sola vez en la traza.

Grafo completo de la práctica

En el código anterior clasificar es un nodo que devuelve actualizaciones; un router devuelve una etiqueta. Para ejecutar ambas ramas utiliza Python 3.10+ y el paquete langgraph. El ejemplo no invoca un modelo ni valida una identidad bancaria:

python
from typing import TypedDict, Annotated
from operator import add
from langgraph.graph import StateGraph, START, END

class Estado(TypedDict):
    mensaje: str
    intencion: str
    respuesta: str
    traza: Annotated[list[str], add]

def clasificar(s: Estado):
    return {"intencion": "saldo" if "saldo" in s["mensaje"].lower() else "otro",
            "traza": ["clasificar"]}
def ruta(s: Estado):
    return s["intencion"]
def responder(s: Estado):
    return {"respuesta": "Saldo de demostración: 0; sin acceso a cuentas",
            "traza": ["responder"]}
def ayuda(s: Estado):
    return {"respuesta": "Describe tu consulta de soporte", "traza": ["ayuda"]}

builder = StateGraph(Estado)
builder.add_node("clasificar", clasificar)
builder.add_node("responder", responder)
builder.add_node("ayuda", ayuda)
builder.add_edge(START, "clasificar")
builder.add_conditional_edges("clasificar", ruta, {"saldo": "responder", "otro": "ayuda"})
builder.add_edge("responder", END)
builder.add_edge("ayuda", END)
grafo = builder.compile()
r = grafo.invoke({"mensaje": "Quiero ver mi saldo", "intencion": "", "respuesta": "", "traza": []})
assert r["traza"] == ["clasificar", "responder"]

El reducer acumula las pequeñas actualizaciones de traza. Cada nodo devuelve solo los campos que cambia, sin editar la lista compartida. Para otro mensaje la traza esperada es clasificar, ayuda. La detección de una palabra no autoriza una consulta real: esa autorización se comprobaría en el servicio antes de ejecutar la herramienta.

Bucle de estado, herramienta y resultado, con revisión humana antes de una acción de alto impacto.
CursaloMapa de práctica
Un agente necesita límites

Un agente mantiene un estado y utiliza herramientas dentro de límites definidos. El resultado de cada herramienta actualiza ese estado para decidir el siguiente paso. Las acciones de alto impacto deben pasar por una revisión humana antes de ejecutarse.

Ver la infografía en tamaño completo ↗
Fuentes para profundizar

Concepto clave

En LangGraph, un grafo de agente es una representación visual y programática de cómo un agente de IA toma decisiones secuenciales. Imagina que estás construyendo un asistente virtual para un banco: el grafo define el flujo desde que el usuario pregunta "¿Cuál es mi saldo?" hasta que el agente consulta la base de datos y responde. Cada nodo representa un estado o acción (como "procesar consulta" o "ejecutar herramienta"), y las aristas son las transiciones entre ellos, determinadas por condiciones lógicas.

La arquitectura se basa en grafos dirigidos donde los nodos pueden ser funciones Python decoradas con @node, y las aristas se definen con add_edge() o add_conditional_edges(). Esto permite modelar agentes que no solo responden linealmente, sino que ramifican su comportamiento según el contexto, similar a cómo un conductor navega: en un cruce (nodo), decide girar (arista) basado en las señales (condiciones).

Cómo funciona en la práctica

Para diseñar tu primer grafo, sigue estos pasos con un ejemplo de agente de soporte técnico:

  1. Define el estado del agente usando Pydantic, incluyendo memoria como historial de conversación.
  2. Crea nodos clave: receive_input (recibe la pregunta del usuario), classify_intent (clasifica la intención usando un LLM), use_tool (ejecuta una herramienta como buscar en una base de datos), y generate_response (genera la respuesta final).
  3. Conecta los nodos con aristas: desde receive_input a classify_intent siempre, luego condicionalmente a use_tool si se necesita una herramienta, o directamente a generate_response si no.
  4. Implementa la lógica de cada nodo; por ejemplo, use_tool podría llamar a una función que consulta una API externa.

Aquí un fragmento de código ilustrativo:

from langgraph.graph import StateGraph, END

graph = StateGraph(AgentState)
graph.add_node("clasificar", classify_intent)
graph.add_node("herramienta", use_tool)
graph.add_edge("clasificar", "herramienta")
graph.add_conditional_edges("herramienta", should_continue)

Caso de estudio

Considera un agente para un e-commerce que maneja consultas de pedidos. El grafo incluye:

NodoFunciónHerramienta asociada
entradaRecibe "¿Dónde está mi pedido #123?"Ninguna
validarExtrae el ID del pedidoExpresión regular
consultarBusca el estado en la BDAPI de base de datos
responderGenera mensaje amigableLLM con plantilla

Las aristas condicionales verifican si el ID es válido; si no, el grafo redirige a un nodo de error. Este diseño reduce las llamadas a herramientas innecesarias en un 40%, según datos de implementación real.

En producción, los grafos con 4-7 nodos optimizados logran latencias menores a 2 segundos para el 95% de las consultas.

Errores comunes

  • Ciclos infinitos: Conectar nodos sin una condición de salida clara, como un bucle entre "clasificar" y "herramienta". Solución: Usa add_conditional_edges() con una función que evalúe a END después de intentos máximos.
  • Estado sobredimensionado: Incluir demasiados campos en el estado, ralentizando el grafo. Solución: Mantén solo datos esenciales como historial y resultados de herramientas.
  • Falta de manejo de errores: No prever fallos en herramientas externas. Solución: Añade un nodo "manejar_error" que reintente o degrade la funcionalidad.
  • Aristas no determinísticas: Condiciones basadas en salidas de LLM sin umbrales claros, causando comportamientos impredecibles. Solución: Usa reglas basadas en confianza (ej., si confianza > 0.8, ir a "herramienta").

Checklist de dominio

  1. ¿Definiste el estado del agente con tipos estrictos (ej., usando Pydantic)?
  2. ¿Cada nodo tiene una responsabilidad única y clara (ej., procesamiento, herramienta, respuesta)?
  3. ¿Las aristas incluyen condiciones para ramificar el flujo basado en datos del estado?
  4. ¿Integraste al menos una herramienta externa (ej., API o base de datos) en un nodo?
  5. ¿Probaste el grafo con entradas variadas para cubrir todos los caminos posibles?
  6. ¿Documentaste el diseño del grafo con un diagrama o comentarios en el código?
  7. ¿Optimizaste el estado para evitar datos redundantes y mejorar el rendimiento?

Construye un grafo de agente para un asistente de reservas de hotel

En este ejercicio, crearás un grafo de LangGraph para un agente que maneja reservas de hotel, usando herramientas y memoria. Sigue estos pasos:

  1. Define una clase HotelState con Pydantic que incluya: user_query (str), intent (str, opcional), tool_result (dict, opcional), y response (str, opcional).
  2. Implementa cuatro nodos:
    • parse_input: Extrae detalles como destino y fechas de la consulta del usuario usando una expresión regular simple.
    • determine_intent: Clasifica la intención en "reservar", "consultar" o "cancelar" basado en palabras clave.
    • call_booking_api: Simula una herramienta que, si la intención es "reservar", devuelve un ID de reserva aleatorio; de lo contrario, devuelve null.
    • generate_output: Genera una respuesta amigable basada en el resultado de la herramienta o un mensaje de error.
  3. Construye el grafo conectando los nodos: desde parse_input a determine_intent siempre, luego condicionalmente a call_booking_api solo si la intención es "reservar", y finalmente a generate_output.
  4. Prueba el grafo con al menos tres consultas: "Quiero reservar en Madrid del 1 al 5 de junio", "¿Cuál es mi reserva?", y "Cancelar mi viaje".
Pistas
  • Usa add_conditional_edges() para la transición después de determine_intent, con una función que verifique el valor de intent.
  • Para simular la herramienta, en call_booking_api, devuelve un diccionario como {"booking_id": "12345"} si corresponde.
  • Asegúrate de que el estado se actualice en cada nodo; por ejemplo, guarda el intent en determine_intent.

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.

Práctica acompañada: Automatiza una tarea verificable

Python, archivos CSV y pruebas pequeñas. Usa este cuaderno como práctica complementaria de la ruta; el material original de la lección continúa siendo tu referencia.

Python, archivos CSV y pruebas pequeñas: Entrada, Función, Salida, Prueba
De la idea al resultado: una secuencia para practicar y revisar.

Práctica: añade una salida reutilizable

Amplía el programa para escribir un nuevo archivo resumen.csv con encabezados categoria,total_centavos. No cambies resumir: añade una función que reciba su resultado y escriba la salida. Ejecuta dos veces y comprueba que no acumula filas duplicadas.

Después agrega una categoría con acento y una cantidad de dos dígitos. Comprueba que la codificación y la conversión siguen funcionando. Para automatizaciones de carpetas, aplica primero este patrón en una carpeta de prueba. Genera un informe de qué se cambiaría antes de habilitar operaciones de escritura sobre archivos importantes.

Comprueba tu entrega

Entrega el programa, la prueba, un ejemplo de entrada y un README con el comando exacto. Indica qué hace ante un archivo inexistente, una columna ausente o un valor inválido. La confiabilidad viene de conocer esos límites, no de añadir muchas funciones.

Sigue con LangGraph Avanzado: Construcción de Agentes de IA con Memoria y Herramientas

Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.

Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.

01 / ELEGIR UNA RUTA

El próximo paso

Aprende IA mientras construyes algo que sí necesitas.

Empieza por el curso inicial o explora el catálogo para encontrar una práctica alineada con tu trabajo.