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
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
Define el estado inicial con
mensaje="Quiero ver mi saldo".Ejecuta
clasificary conserva todos los campos existentes.Enruta solo cuando
intencion == "saldo".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:
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.

Mapa de prácticaUn 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:
- Define el estado del agente usando Pydantic, incluyendo memoria como historial de conversación.
- 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), ygenerate_response(genera la respuesta final). - Conecta los nodos con aristas: desde
receive_inputaclassify_intentsiempre, luego condicionalmente ause_toolsi se necesita una herramienta, o directamente agenerate_responsesi no. - Implementa la lógica de cada nodo; por ejemplo,
use_toolpodrí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:
| Nodo | Función | Herramienta asociada |
|---|---|---|
| entrada | Recibe "¿Dónde está mi pedido #123?" | Ninguna |
| validar | Extrae el ID del pedido | Expresión regular |
| consultar | Busca el estado en la BD | API de base de datos |
| responder | Genera mensaje amigable | LLM 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 aENDdespué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
- ¿Definiste el estado del agente con tipos estrictos (ej., usando Pydantic)?
- ¿Cada nodo tiene una responsabilidad única y clara (ej., procesamiento, herramienta, respuesta)?
- ¿Las aristas incluyen condiciones para ramificar el flujo basado en datos del estado?
- ¿Integraste al menos una herramienta externa (ej., API o base de datos) en un nodo?
- ¿Probaste el grafo con entradas variadas para cubrir todos los caminos posibles?
- ¿Documentaste el diseño del grafo con un diagrama o comentarios en el código?
- ¿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:
- Define una clase
HotelStatecon Pydantic que incluya:user_query(str),intent(str, opcional),tool_result(dict, opcional), yresponse(str, opcional). - 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.
- Construye el grafo conectando los nodos: desde
parse_inputadetermine_intentsiempre, luego condicionalmente acall_booking_apisolo si la intención es "reservar", y finalmente agenerate_output. - 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 dedetermine_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.
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.