LangGraph es la evolución natural de LangChain para construir agentes IA que van más allá de la típica cadena lineal prompt → LLM → salida. Si has intentado montar un agente medianamente complejo con LangChain clásico (bucles de reflexión, escalado condicional a humano, memoria persistente entre sesiones, coordinación multi-agente), habrás chocado con la misma pared: las cadenas se rompen en cuanto necesitas estado, ramas condicionales o ciclos. LangGraph resuelve esto modelando el agente como un grafo dirigido con nodos, aristas y un estado tipado compartido que fluye entre ellos, en la línea de las máquinas de estados de toda la vida pero adaptado a workflows con LLMs.
En este tutorial vas a construir desde cero un agente de customer support en Python que clasifica tickets entrantes, decide si puede resolverlos automáticamente o si debe escalar a un humano, y guarda el resultado en un CRM simulado. Cubriremos la instalación, los conceptos clave (State, Nodes, Edges, conditional edges, checkpointing), la integración con Claude Fable 5 y GPT-5.6 vía sus SDKs oficiales, ejecución local con Ollama y Colibri, persistencia con SQLite y Redis, streaming de tokens con astream_events, y observabilidad con LangSmith. Al final tendrás un patrón replicable para cualquier workflow con estado que no encaje en una cadena lineal.
Qué es LangGraph y por qué supera a LangChain para agentes complejos
LangGraph es una librería Python (y también TypeScript) mantenida por el equipo de LangChain que permite construir aplicaciones LLM como grafos dirigidos. En vez de encadenar componentes en secuencia, defines nodos (funciones que reciben un estado y devuelven una actualización parcial de ese estado) y los conectas con aristas que pueden ser estáticas o condicionales (el destino depende del contenido del estado en ese momento). El grafo puede tener ciclos, ramas paralelas, sub-grafos anidados y checkpointing automático entre pasos.
La diferencia con LangChain clásico es enorme. Una Chain tradicional es un DAG rígido: A llama a B, B llama a C, fin. Si en la mitad necesitas volver atrás, esperar input humano o repetir un paso hasta que un criterio se cumpla, tienes que salir de la cadena y orquestar manualmente. LangGraph, en cambio, trata el agente como una máquina de estados donde el propio modelo o tu código deciden en cada nodo cuál es la siguiente arista a recorrer. Es el mismo salto conceptual que hay entre un script bash lineal y una máquina de estados finitos con transiciones explícitas.
Los tres escenarios donde LangGraph brilla frente a alternativas: agentes con ciclos de reflexión (piensa, actúa, evalúa, repite hasta que la respuesta pase un umbral de calidad), workflows con escalado condicional (si el ticket es simple lo resuelve el LLM, si es complejo lo mete a cola humana) y coordinación multi-agente (un supervisor decide qué agente especialista invoca según el contexto). Si tu caso encaja en cualquiera de los tres, LangGraph te ahorra semanas de plomería. Si vienes del ecosistema no-code, mira primero el tutorial de Zapier Central para ver el mismo problema resuelto sin código; LangGraph es la respuesta cuando necesitas control fino y código real.
Conceptos clave: State, Nodes, Edges, conditional edges, checkpoint
Antes de instalar nada conviene tener claras las cinco piezas del vocabulario:
- State: un diccionario tipado (típicamente un
TypedDict) que fluye por todo el grafo. Cada nodo lo lee y devuelve una actualización parcial que LangGraph fusiona automáticamente. Es el equivalente al contexto compartido en una máquina de estados. - Nodes: funciones Python (síncronas o asíncronas) que reciben el state actual y devuelven un dict parcial con los campos que modifican. Un nodo puede llamar a un LLM, hacer una consulta a base de datos, invocar una API externa o cualquier operación arbitraria.
- Edges: conexiones entre nodos. Las aristas estáticas siempre van de A a B. Las aristas condicionales (
add_conditional_edges) reciben el state y devuelven el nombre del siguiente nodo, permitiendo ramificar el flujo según el contenido del estado. - Entry point y END: todo grafo tiene un nodo inicial declarado con
set_entry_pointy un nodo especialENDque marca el fin de la ejecución. - Checkpoint: LangGraph guarda automáticamente el state después de cada nodo si le proporcionas un checkpointer (SQLite, Redis, Postgres, memoria). Esto permite pausar, reanudar y viajar en el tiempo por la ejecución, algo clave para agentes de larga duración o con human-in-the-loop.
Un grafo típico se parece a esto: entry → clasificador → (arista condicional) → resolver automáticamente | escalar a humano → guardar en CRM → END. Los cinco conceptos anteriores bastan para modelar el 90 por ciento de los workflows reales.
LangGraph vs LangChain vs AutoGen vs CrewAI: cuándo usar cada uno
El ecosistema de frameworks de agentes IA en 2026 está saturado. Esta tabla resume cuándo cada uno es la mejor elección:
| Framework | Fortalezas | Cuándo usarlo |
|---|---|---|
| LangChain | Cadenas lineales, ecosistema enorme de integraciones, RAG clásico | Workflows deterministas sin ciclos ni ramas: extracción, resumen, Q&A sobre documentos |
| LangGraph | Grafos con estado, aristas condicionales, checkpointing, control fino | Agentes con ciclos, human-in-the-loop, workflows complejos, multi-agente coordinado |
| AutoGen | Conversación entre múltiples agentes autónomos, orquestación por chat | Escenarios tipo debate o negociación entre agentes, generación de código colaborativa |
| CrewAI | Abstracción alta con roles predefinidos (researcher, writer, reviewer), curva suave | Prototipado rápido de equipos de agentes con roles claros y tareas secuenciales |
Regla mental: si tu problema es determinista úsalo con LangChain; si es agentic y con ramificación úsalo con LangGraph; si es conversación entre iguales úsalo con AutoGen; si buscas prototipado con roles humanos úsalo con CrewAI. Este tutorial se centra en LangGraph porque cubre el mayor rango de casos serios en producción.
Requisitos previos
Necesitas cuatro cosas para seguir el tutorial sin fricciones:
- Python 3.11 o superior. LangGraph aprovecha type hints modernos y features de asyncio que no están disponibles en versiones anteriores. Comprueba con
python --version. - Un entorno virtual (venv, virtualenv, poetry o uv). Recomendado uv por velocidad:
uv venv .venv && source .venv/bin/activate. - Cuenta con al menos un proveedor de LLM: cuenta Anthropic con clave API para Claude Fable 5, OpenAI con clave para GPT-5.6, o instalación local de Ollama/Colibri si prefieres modelos on-device sin coste variable. Puedes combinar los tres en el mismo grafo.
- Editor con soporte Python decente: VS Code con Pylance, Cursor, PyCharm o Neovim con pyright. LangGraph se beneficia mucho del tipado.
Si vas a integrar con Claude Fable 5 recuerda que el modelo requiere data retention de 30 días como mínimo en tu organización Anthropic. Para uso local sin límites de API pásate por el tutorial de Colibri con GLM 5.2 antes de continuar.
Paso 1: Crear entorno Python e instalar LangGraph
Empezamos con la instalación limpia en un entorno virtual. Abre la terminal:
mkdir agente-customer-support && cd agente-customer-support
python -m venv .venv
source .venv/bin/activate # en Windows: .venv\Scripts\activate
pip install --upgrade pip
pip install langgraph langchain langchain-anthropic langchain-openai
pip install langgraph-checkpoint-sqlite # para persistencia con SQLite
Verifica la instalación con un import rápido:
python -c "from langgraph.graph import StateGraph, END; print('LangGraph listo')"
Si vas a usar Claude Fable 5 exporta la clave de Anthropic; si vas a usar GPT-5.6 haz lo mismo con la de OpenAI. También puedes ponerlas en un archivo .env y cargarlas con python-dotenv:
export ANTHROPIC_API_KEY=sk-ant-...
export OPENAI_API_KEY=sk-proj-...
Paso 2: Definir el State con TypedDict
El corazón de cualquier grafo LangGraph es su State. Es el objeto que fluye entre nodos y que cada uno actualiza parcialmente. Crea agente.py y añade la definición:
from typing import TypedDict, Literal, Optional
from langgraph.graph import StateGraph, END
class EstadoTicket(TypedDict):
ticket_id: str
mensaje_cliente: str
categoria: Optional[Literal["facturacion", "tecnico", "comercial", "otro"]]
prioridad: Optional[Literal["baja", "media", "alta", "critica"]]
respuesta_automatica: Optional[str]
escalar_a_humano: bool
resuelto: bool
Las tres claves de diseño de un buen State: úsalo tipado (TypedDict o Pydantic BaseModel), marca opcionales los campos que se rellenan progresivamente y evita objetos gigantes: el State se serializa en cada checkpoint y viaja entero por cada nodo, así que un blob de 10 MB dentro te va a matar el rendimiento. Guarda referencias (IDs, rutas) y consulta los datos completos dentro del nodo si hace falta.
LangGraph también soporta Annotated types para definir cómo se fusionan valores cuando dos nodos escriben en el mismo campo (por ejemplo, listas que se concatenan en vez de reemplazarse). En agentes multi-agente esto es imprescindible; para nuestro ejemplo simple no lo necesitamos.
Paso 3: Crear el primer nodo
Un nodo es una función Python que recibe el state actual y devuelve un dict con las claves que quiere actualizar. LangGraph fusiona ese dict con el state completo automáticamente. Añade el primer nodo, un clasificador de tickets:
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import SystemMessage, HumanMessage
llm = ChatAnthropic(model="claude-fable-5", max_tokens=1024)
def nodo_clasificar(state: EstadoTicket) -> dict:
prompt = f"""Clasifica este ticket de soporte en una categoria y prioridad.
Mensaje del cliente: {state['mensaje_cliente']}
Responde SOLO con este JSON: {{"categoria": "...", "prioridad": "..."}}
Categorias validas: facturacion, tecnico, comercial, otro
Prioridades validas: baja, media, alta, critica"""
respuesta = llm.invoke([
SystemMessage(content="Eres un clasificador de tickets de soporte."),
HumanMessage(content=prompt),
])
import json
datos = json.loads(respuesta.content)
return {"categoria": datos["categoria"], "prioridad": datos["prioridad"]}
Fíjate en tres detalles importantes. Primero, el nodo no muta el state, devuelve un dict nuevo con las claves que quiere actualizar; LangGraph hace la fusión. Segundo, el nodo solo devuelve las claves que cambia, no el state completo. Tercero, cualquier operación es válida dentro del nodo: llamar a un LLM, hacer HTTP, leer de base de datos, ejecutar código local. LangGraph no impone restricciones sobre qué haces, solo sobre cómo declaras la entrada y la salida.
Paso 4: Construir el grafo con StateGraph y compilar
Con el State definido y un nodo listo, ya podemos ensamblar el grafo. Añadimos dos nodos más (resolver automáticamente, escalar) y los conectamos:
def nodo_resolver_auto(state: EstadoTicket) -> dict:
prompt = f"""Redacta una respuesta breve y profesional para este ticket.
Categoria: {state['categoria']} | Prioridad: {state['prioridad']}
Mensaje: {state['mensaje_cliente']}"""
respuesta = llm.invoke([HumanMessage(content=prompt)])
return {"respuesta_automatica": respuesta.content, "resuelto": True}
def nodo_escalar_humano(state: EstadoTicket) -> dict:
print(f"[ESCALADO] Ticket {state['ticket_id']} enviado a cola humana")
return {"escalar_a_humano": True, "resuelto": False}
grafo = StateGraph(EstadoTicket)
grafo.add_node("clasificar", nodo_clasificar)
grafo.add_node("resolver_auto", nodo_resolver_auto)
grafo.add_node("escalar", nodo_escalar_humano)
grafo.set_entry_point("clasificar")
grafo.add_edge("resolver_auto", END)
grafo.add_edge("escalar", END)
app = grafo.compile()
Aún falta decidir qué arista sale de clasificar hacia resolver_auto o hacia escalar. Eso es una arista condicional y la vemos en el siguiente paso. Cuando llamas a compile(), LangGraph valida el grafo, comprueba que no haya nodos huérfanos ni ciclos infinitos y devuelve un objeto invocable.
Paso 5: Añadir edges condicionales
Las aristas condicionales son el motor del comportamiento dinámico. En vez de una arista fija, defines una función que recibe el state y devuelve el nombre del siguiente nodo. La regla de negocio: si la prioridad es critica o la categoría es comercial, escalar; en cualquier otro caso, resolver automáticamente:
def decidir_ruta(state: EstadoTicket) -> Literal["resolver_auto", "escalar"]:
if state["prioridad"] == "critica" or state["categoria"] == "comercial":
return "escalar"
return "resolver_auto"
grafo.add_conditional_edges(
"clasificar",
decidir_ruta,
{"resolver_auto": "resolver_auto", "escalar": "escalar"},
)
El tercer argumento es un diccionario que mapea el valor devuelto por decidir_ruta al nombre del nodo destino. Puedes tener múltiples destinos condicionales y hasta un destino especial END para terminar la ejecución en función del state.
Las aristas condicionales admiten funciones síncronas y asíncronas, y pueden inspeccionar cualquier campo del state. Es habitual meter aquí lógica de negocio dura (umbrales, políticas de escalado) y dejar los LLMs solo dentro de los nodos.
Paso 6: Integrar con Claude Fable 5 usando ChatAnthropic
Ya hemos estado usando ChatAnthropic en los pasos anteriores. Vamos a afinar la integración con Claude Fable 5, el modelo más capaz de Anthropic en 2026. Tres detalles críticos:
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(
model="claude-fable-5",
max_tokens=2048,
# Fable 5 tiene thinking siempre activo; no configures budget_tokens
# Para modelos anteriores como Opus 4.8 puedes usar adaptive thinking
)
# Alternativa con GPT-5.6 para comparar
from langchain_openai import ChatOpenAI
llm_openai = ChatOpenAI(model="gpt-5.6", max_tokens=2048)
# Alternativa local con Ollama (sin coste variable)
from langchain_community.chat_models import ChatOllama
llm_local = ChatOllama(model="glm-5.2", temperature=0.3)
Con Fable 5 recuerda tres cosas: el thinking está siempre activo (no pases thinking={"type": "disabled"}, devuelve 400); tu organización debe tener retención de datos de al menos 30 días; y el modelo puede devolver stop_reason: "refusal" si los clasificadores de seguridad rechazan la petición, así que envuelve la llamada en try/except o configura fallbacks a Opus 4.8.
Puedes tener múltiples LLMs en el mismo grafo. Por ejemplo: usar Fable 5 (caro pero potente) para el clasificador crítico, GPT-5.6 para redacciones largas y Colibri local para tareas triviales. LangGraph no restringe qué LLM usa cada nodo, cada uno decide.
Paso 7: Checkpointing con SqliteSaver para conversaciones persistentes
Hasta ahora el grafo es stateless entre invocaciones: cada llamada a app.invoke(state) empieza de cero. Para agentes reales necesitas checkpointing: guardar el state después de cada nodo para poder pausar, reanudar y auditar la ejecución. LangGraph soporta SQLite, Redis, Postgres y memoria out of the box:
from langgraph.checkpoint.sqlite import SqliteSaver
checkpointer = SqliteSaver.from_conn_string("checkpoints.db")
app = grafo.compile(checkpointer=checkpointer)
# Invocar con thread_id para que LangGraph agrupe checkpoints por conversacion
config = {"configurable": {"thread_id": "ticket-12345"}}
resultado = app.invoke({
"ticket_id": "12345",
"mensaje_cliente": "No puedo iniciar sesion desde ayer",
"categoria": None,
"prioridad": None,
"respuesta_automatica": None,
"escalar_a_humano": False,
"resuelto": False,
}, config=config)
El thread_id es la clave de agrupación. Todos los checkpoints con el mismo thread_id forman una conversación coherente que puedes retomar más tarde con app.invoke({}, config) pasando input vacío. Para producción usa Redis (langgraph-checkpoint-redis) o Postgres (langgraph-checkpoint-postgres); SQLite está bien para desarrollo y pruebas.
El checkpointing habilita también time travel: puedes listar todos los checkpoints de un thread con app.get_state_history(config), seleccionar uno intermedio y reanudar desde ahí. Imprescindible para debug de agentes largos.
Paso 8: Streaming de tokens con astream_events
Para experiencias de usuario responsivas necesitas streaming: mostrar tokens según los va generando el LLM en vez de esperar a la respuesta completa. LangGraph expone astream_events, que emite eventos granulares por cada delta de token, transición de nodo y actualización de state:
import asyncio
async def ejecutar_streaming(input_data, config):
async for evento in app.astream_events(input_data, config=config, version="v2"):
tipo = evento["event"]
if tipo == "on_chat_model_stream":
chunk = evento["data"]["chunk"]
print(chunk.content, end="", flush=True)
elif tipo == "on_chain_end" and evento["name"] == "LangGraph":
print("\n[Grafo terminado]")
asyncio.run(ejecutar_streaming(input_data, config))
Los eventos incluyen on_chain_start, on_chain_end, on_chat_model_start, on_chat_model_stream, on_chat_model_end, on_tool_start, on_tool_end y muchos más. Filtras por tipo y por nombre de nodo para renderizar solo lo que necesitas en tu UI.
Para agentes desplegados con FastAPI puedes envolver astream_events en un endpoint Server-Sent Events (SSE) y consumirlo desde el frontend. Es el patrón que usan Perplexity, Claude.ai y la mayoría de UIs conversacionales serias.
Paso 9: Testing y debugging con LangSmith
El último paso es observabilidad. LangSmith (el producto SaaS del equipo LangChain) traza automáticamente cada invocación del grafo, cada llamada a LLM, cada input y output. Actívalo con dos variables de entorno:
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=lsv2_pt_...
export LANGSMITH_PROJECT=agente-customer-support
Con eso, cada ejecución del grafo aparece en el dashboard de LangSmith con el árbol completo de llamadas, tiempos, tokens consumidos y coste. Puedes marcar ejemplos como datasets, crear evaluaciones automáticas con LLM-as-a-judge y hacer regresiones cuando cambias el prompt de un nodo.
Para testing local sin depender de LangSmith, LangGraph incluye get_state_history() que te da la traza completa de un thread. Combínalo con pytest y mocks del LLM (usando langchain_core.language_models.fake.FakeListChatModel) para tests unitarios rápidos sin gasto en APIs.
Ejemplo completo: agente customer support en 40 líneas
Consolidando todo lo anterior, este es el agente customer support completo. Cópialo, adapta las claves API y ejecútalo:
from typing import TypedDict, Literal, Optional
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.sqlite import SqliteSaver
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage, SystemMessage
import json
class EstadoTicket(TypedDict):
ticket_id: str
mensaje_cliente: str
categoria: Optional[str]
prioridad: Optional[str]
respuesta_automatica: Optional[str]
escalar_a_humano: bool
resuelto: bool
llm = ChatAnthropic(model="claude-fable-5", max_tokens=1024)
def clasificar(state):
p = f"Clasifica el ticket. Mensaje: {state['mensaje_cliente']}. Responde JSON con categoria (facturacion/tecnico/comercial/otro) y prioridad (baja/media/alta/critica)."
r = llm.invoke([HumanMessage(content=p)])
d = json.loads(r.content)
return {"categoria": d["categoria"], "prioridad": d["prioridad"]}
def resolver_auto(state):
p = f"Responde profesionalmente al ticket: {state['mensaje_cliente']}"
r = llm.invoke([HumanMessage(content=p)])
return {"respuesta_automatica": r.content, "resuelto": True}
def escalar(state):
return {"escalar_a_humano": True, "resuelto": False}
def guardar_crm(state):
print(f"[CRM] Ticket {state['ticket_id']} guardado: resuelto={state['resuelto']}")
return {}
def decidir(state):
if state["prioridad"] == "critica" or state["categoria"] == "comercial":
return "escalar"
return "resolver_auto"
g = StateGraph(EstadoTicket)
g.add_node("clasificar", clasificar)
g.add_node("resolver_auto", resolver_auto)
g.add_node("escalar", escalar)
g.add_node("guardar_crm", guardar_crm)
g.set_entry_point("clasificar")
g.add_conditional_edges("clasificar", decidir, {"resolver_auto": "resolver_auto", "escalar": "escalar"})
g.add_edge("resolver_auto", "guardar_crm")
g.add_edge("escalar", "guardar_crm")
g.add_edge("guardar_crm", END)
app = g.compile(checkpointer=SqliteSaver.from_conn_string("tickets.db"))
Cuarenta líneas, un agente productivo. Pruébalo:
config = {"configurable": {"thread_id": "t-001"}}
resultado = app.invoke({
"ticket_id": "t-001",
"mensaje_cliente": "Quiero cancelar mi suscripcion Enterprise",
"categoria": None, "prioridad": None,
"respuesta_automatica": None, "escalar_a_humano": False, "resuelto": False,
}, config=config)
print(resultado)
El ticket se clasifica como comercial, se escala a humano, se guarda en CRM y termina. Cambia el mensaje por uno técnico simple y verás cómo pasa por el flujo de resolución automática.
Patrones avanzados: human-in-the-loop, subgrafos, supervisor multi-agente
Cuando el agente básico ya funciona hay tres patrones avanzados que resuelven la mayoría de necesidades reales.
Human-in-the-loop: para operaciones que requieren aprobación humana (borrar datos, enviar comunicaciones críticas, cerrar contratos) usa interrupt_before al compilar el grafo. LangGraph pausa la ejecución antes del nodo indicado, guarda el checkpoint y espera a que llames a app.invoke(None, config) tras la aprobación humana:
app = g.compile(checkpointer=checkpointer, interrupt_before=["escalar"])
Subgrafos: permiten reutilizar grafos como si fueran nodos dentro de otros grafos. Útil para modularizar workflows complejos. Un subgrafo puede tener su propio State y traducir entre state padre e hijo con funciones de mapeo.
Supervisor multi-agente: patrón donde un nodo supervisor (que suele ser un LLM) decide qué agente especialista invocar. Un supervisor de customer support podría enrutar a un agente de facturación, uno técnico o uno comercial según el mensaje. Cada especialista es a su vez un subgrafo con sus propias herramientas.
def supervisor(state):
prompt = f"Cual agente debe manejar este mensaje: {state['mensaje_cliente']}. Responde SOLO: facturacion, tecnico o comercial."
r = llm.invoke([HumanMessage(content=prompt)])
return {"next_agent": r.content.strip().lower()}
Este patrón se parece a Managed Agents de Anthropic pero implementado localmente. Si prefieres delegar orquestación al proveedor mira el tutorial de agentes con Claude API y MCP.
Errores comunes y troubleshooting
Estos son los tropiezos habituales al empezar con LangGraph:
- State no se actualiza: casi siempre es porque devuelves el state completo modificado en vez de un dict parcial con solo las claves nuevas. Fíjate:
return {"categoria": "tecnico"}, noreturn state. - Recursion limit exceeded: LangGraph limita ciclos a 25 iteraciones por defecto. Si tu agente necesita más, pasa
{"recursion_limit": 50}enconfig, pero primero pregúntate si realmente necesitas tantos ciclos o si hay un bug en las aristas condicionales. - Checkpoint no se guarda: olvidaste pasar
checkpointeral compilar, o elthread_idesNone. Los checkpoints requieren ambos. - Types no cuadran entre nodos: revisa que el TypedDict sea el mismo objeto en toda la app y que los
Optionalestén bien marcados; un campo no opcional que devuelvas comoNonehará que pyright/Pylance se queje sin pistas claras. - Streaming no emite tokens: usa
astream_events(..., version="v2")(no el v1 antiguo) y asegúrate de que el LLM soporte streaming (ChatAnthropicyChatOpenAIlo hacen por defecto). - Explosión de coste con LLM en cada nodo: los nodos son cheap pero cada llamada LLM cuesta. Cachea con
langchain_core.caches.InMemoryCacheo mueve nodos triviales a Ollama local.
Alternativas y cuándo NO usar LangGraph
LangGraph es potente pero no es la respuesta universal. NO lo uses cuando:
- Tu workflow es lineal simple (prompt → LLM → parse → guardar). LangChain o incluso llamadas directas al SDK del proveedor son más ligeras.
- Necesitas conversación libre entre agentes iguales sin flujo predefinido. AutoGen encaja mejor.
- Quieres prototipar rápido con roles humanos (investigador, redactor, revisor). CrewAI tiene abstracciones más altas.
- Prefieres que Anthropic hospede el bucle agentic. Managed Agents de Claude API te da lo mismo sin orquestar código local.
- El caso es no-code y lo llevará gente de negocio. Zapier Central, n8n o Make son mejores.
LangGraph brilla cuando necesitas control fino sobre estado, ciclos, ramas condicionales y checkpointing, tienes equipo Python competente y el workflow es lo suficientemente complejo para justificar la infraestructura.
Material recomendado para desarrollar agentes IA con LangGraph
Estos productos elevan el flujo de trabajo alrededor de LangGraph, Python y agentes IA. Todos con enlaces afiliados Amazon (tag webmasteroson-21):
- Monitor BenQ RD280U: 4K con modo Coding y proporción 3:2 pensada para leer código Python largo y diagramas de grafos sin scroll horizontal. Ver precio actual en Amazon.
- Monitor LG 29WP60G-B ultrawide: 29 pulgadas ultrapanorámico ideal para tener editor, terminal con logs de LangSmith y navegador con documentación en paralelo. Ver precio actual en Amazon.
- Teclado Logitech MX Keys: teclas silenciosas retroiluminadas, imprescindible en sesiones largas iterando prompts y refactorizando nodos. Ver precio actual en Amazon.
- Ratón Logitech MX Master 3S: scroll ultrarrápido para revisar trazas largas de LangSmith y navegar por checkpoints. Ver precio actual en Amazon.
- Mac Mini M4: máquina de desarrollo silenciosa y potente para correr Ollama con modelos locales grandes junto al servidor LangGraph. Ver precio actual en Amazon.
- Silla Secretlab Titan Evo: soporte lumbar magnético y densidad de espuma pensada para jornadas depurando agentes IA sin castigar la espalda. Ver precio actual en Amazon.
Conclusión
LangGraph es la herramienta de referencia en 2026 para construir agentes IA con estado, ciclos y control fino en Python. Con lo aprendido puedes: modelar workflows complejos como grafos dirigidos, integrar Claude Fable 5, GPT-5.6 y modelos locales en el mismo agente, persistir estado con checkpointing en SQLite/Redis, hacer streaming responsive a la UI y auditar cada ejecución con LangSmith. El patrón replicable es siempre el mismo: define un State tipado, escribe nodos que devuelvan updates parciales, conéctalos con aristas (algunas condicionales) y compila con un checkpointer.
Próximos pasos naturales: convierte tu proceso más doloroso (soporte, moderación, triaje de leads) en un grafo LangGraph, despliégalo detrás de FastAPI con streaming SSE, mide tiempo y coste con LangSmith y itera. Si quieres seguir profundizando en el ecosistema de agentes IA revisa la guía completa de agentes IA 2026 y el tutorial del OpenAI Agents SDK para comparar enfoques.
Preguntas frecuentes
¿Cuál es la diferencia real entre LangGraph y LangChain?
LangChain trata las aplicaciones LLM como cadenas lineales (DAG rígido: A llama a B, B llama a C, fin), ideal para workflows deterministas como resumen o Q&A. LangGraph las trata como máquinas de estados con nodos, aristas y estado tipado que fluye entre ellos, permitiendo ciclos, ramas condicionales y checkpointing. Regla: si necesitas volver atrás, esperar input humano o repetir pasos hasta un criterio, LangGraph; si no, LangChain.
¿Puedo usar LangGraph sin depender de LangChain?
Sí en cierta medida. LangGraph solo requiere langgraph y langchain-core (la capa de tipos y mensajes base). Los adaptadores concretos de LLM (langchain-anthropic, langchain-openai) son opcionales: puedes usarlos o llamar directamente a los SDKs oficiales de Anthropic u OpenAI dentro de los nodos. Muchos equipos escapan del ecosistema LangChain pero mantienen LangGraph solo por su motor de grafos.
¿Cómo escala LangGraph en producción con muchos usuarios concurrentes?
LangGraph es una librería Python normal, escala como cualquier aplicación asyncio: FastAPI + uvicorn + workers gunicorn. Los checkpoints van a Redis o Postgres (evita SQLite en producción concurrente), y cada request usa un thread_id único. El cuello de botella real suele ser la latencia del LLM, no el motor de grafos. Para cargas masivas considera LangGraph Cloud (SaaS de LangChain) que gestiona autoescalado y colas.
¿Merece la pena LangGraph para un agente simple de tres pasos?
Casi nunca. Si tu workflow es clasificar → responder → guardar sin ciclos ni condicionales complejas, tres funciones Python encadenadas o incluso una sola llamada al SDK del proveedor con un prompt bien diseñado bastan. LangGraph justifica su curva de aprendizaje a partir de cuatro nodos con al menos una arista condicional o un ciclo de reflexión.
¿Puedo mezclar Claude Fable 5, GPT-5.6 y modelos locales en el mismo grafo?
Sí. Cada nodo elige qué LLM invoca; nada te obliga a usar uno solo. Un patrón habitual: modelos potentes (Fable 5, GPT-5.6) para clasificación crítica y redacción cara al cliente; modelos locales (Colibri, Ollama con GLM 5.2) para tareas triviales como parseo o normalización de datos. Esto optimiza coste sin sacrificar calidad donde importa.
¿LangGraph funciona bien con async y streaming a UIs web?
Sí, es su punto fuerte. Todos los métodos tienen equivalente async (ainvoke, astream, astream_events). Para UIs web el patrón canónico es exponer un endpoint FastAPI con Server-Sent Events que reenvíe los eventos de astream_events al frontend. Perplexity, Claude.ai y prácticamente cualquier UI conversacional moderna usan esta arquitectura.
¿Cómo hago testing de un grafo LangGraph sin gastar en llamadas a APIs?
Dos vías. Mock del LLM con langchain_core.language_models.fake.FakeListChatModel que devuelve respuestas predefinidas en orden, útil para tests unitarios rápidos. Para tests de integración, apunta a un modelo local en Ollama que no tiene coste variable. Complementa con get_state_history() para assert sobre el flujo real que tomó el grafo y no solo sobre la salida final.
¿Es seguro exponer un agente LangGraph a usuarios finales sin filtros?
No. Cualquier agente con acceso a herramientas (bases de datos, APIs externas, envío de emails) necesita validación de entrada, permisos granulares, límites de tasa por usuario y auditoría. LangGraph facilita meter un nodo de guardrails antes de acciones sensibles y usar interrupt_before para aprobación humana en operaciones críticas. Trata cada tool como código nuevo entrando a tu sistema con permisos que solo tú controlas.
Este artículo contiene enlaces afiliados a Amazon con el tag webmasteroson-21. Si compras a través de estos enlaces, Arkaia puede recibir una comisión sin coste adicional para ti. Nuestra valoración editorial es independiente y no varía según los ingresos por afiliación.
Comentarios
Inicia sesion para dejar un comentario
Acceder