LangGraph vs Vercel AI SDK: Máquinas de estado o reactividad en el Edge
Comparación técnica y arquitectónica entre LangGraph y Vercel AI SDK: persistencia con máquinas de estado vs. streaming reactivo en el Edge.
El diseño de sistemas con LLMs superó la etapa de experimentación con scripts aislados. La discusión arquitectónica actual gira en torno a un balance concreto: orquestación determinista de backend basada en máquinas de estado vs. ejecución reactiva orientada a la interfaz en el Edge.
LangGraph (del ecosistema LangChain) y Vercel AI SDK representan dos aproximaciones técnicas divergentes. LangGraph traslada los principios del modelo Pregel de Google a grafos de agentes con sincronización cíclica y persistencia de estado. Vercel AI SDK aborda el problema desde el protocolo de transporte: flujos HTTP basados en Server-Sent Events (SSE), ejecución serverless efímera y sincronización directa con el Virtual DOM.
Elegir una u otra no es una cuestión de preferencia de lenguaje, sino de dónde reside el centro de gravedad del sistema: en la resiliencia del proceso de negocio o en la latencia del primer token percibida por el usuario.
Comparación Arquitectónica: Mecanismos de Ejecución
flowchart LR
subgraph LG ["LangGraph: Motor Pregel y Checkpointing"]
A["Input / Webhook"] --> B["State Graph Reducer"]
B --> C{"Router Node"}
C -->|"Tool Execution"| D["Python Worker"]
D --> B
C -->|"Pause (Human Gate)"| E["Checkpointer (PostgreSQL/Redis)"]
E -.->|"Resume Command"| B
end
subgraph VAI ["Vercel AI SDK: Edge Streaming Loop"]
F["User UI Action"] --> G["Edge Function (streamText)"]
G --> H{"Tool Calling Loop (maxSteps)"}
H -->|"Tool Call Stream"| I["React UI / Client State"]
H -->|"Async Side-effect"| J["Background Worker / Queue"]
H --> K["SSE Stream (Fast TTFT)"]
end
1. LangGraph: StateGraphs, Reducers y Suspensión a Disco
LangGraph modela agentes como grafos dirigidos (cíclicos o acíclicos). El estado es un esquema estructurado (usualmente un TypedDict o modelo Pydantic) que se transforma mediante funciones reductoras puras.
El núcleo de su arquitectura es el Checkpointer. Cada paso de ejecución (un “super-step” en la jerga de Pregel) genera un snapshot atómico en una base de datos (PostgreSQL, SQLite, Redis). Esto permite:
- Suspensión determinista: El proceso puede detenerse en seco mediante la directiva
interrupt_beforeointerrupt_after, liberando la memoria del runtime de Python. - Viaje en el tiempo (Time-travel): Capacidad de bifurcar el estado de un hilo hacia un paso previo para reintentar una rama de ejecución fallida.
from typing import TypedDict, Annotated
import operator
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver
class TicketState(TypedDict):
ticket_id: str
amount: float
requires_approval: bool
status: str
def analyze_refund(state: TicketState) -> dict:
if state["amount"] > 500:
return {"requires_approval": True}
return {"status": "auto_approved"}
def human_approval_gate(state: TicketState) -> dict:
# Este nodo no se ejecuta hasta que el proceso se reanuda manualmente
return {"status": "approved_by_human"}
workflow = StateGraph(TicketState)
workflow.add_node("analyze_refund", analyze_refund)
workflow.add_node("human_approval_gate", human_approval_gate)
workflow.set_entry_point("analyze_refund")
workflow.add_conditional_edges(
"analyze_refund",
lambda state: "human_approval_gate" if state["requires_approval"] else END
)
workflow.add_edge("human_approval_gate", END)
# El checkpointer persiste el snapshot en cada transición de nodo
checkpointer = MemorySaver()
app = workflow.compile(
checkpointer=checkpointer,
interrupt_before=["human_approval_gate"]
)
# Ejecución: se interrumpe automáticamente antes de 'human_approval_gate'
config = {"configurable": {"thread_id": "thread-001"}}
initial_input = {"ticket_id": "T-100", "amount": 750.0, "requires_approval": False, "status": "new"}
events = app.stream(initial_input, config)
for event in events:
print(event)
# La ejecución suspende el hilo. El worker se desasigna.
2. Vercel AI SDK: Tool Calling Reactivo y Streaming SSE
Vercel AI SDK no utiliza un grafo con estado persistido en backend. Modela la interacción como un bucle iterativo de inferencia y llamada a herramientas (maxSteps) sobre funciones serverless/Edge.
El estado del agente vive en el transporte HTTP y en el cliente (a través de hooks como useChat o streams de streamText).
import { streamText, tool } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-5'), // Tier de frontera
system: 'Agente de procesamiento transaccional.',
messages,
maxSteps: 5, // Ejecuta loops automáticos de tool calling
tools: {
requestHumanApproval: tool({
description: 'Escala la transacción si el monto supera los 500 USD.',
parameters: z.object({
amount: z.number(),
reason: z.string(),
}),
execute: async ({ amount, reason }) => {
// Despacho no bloqueante a una cola externa (ej. SQS/Inngest)
await fetch('https://api.internal/queues/approvals', {
method: 'POST',
body: JSON.stringify({ amount, reason }),
});
return { status: 'escalated_to_queue', estimatedReviewTime: '2h' };
},
}),
},
});
return result.toDataStreamResponse();
}
Análisis de Tradeoffs Técnicos
| Dimensión | LangGraph | Vercel AI SDK |
|---|---|---|
| Primitiva Central | Máquinas de estado y grafos (Pregel) | Streams HTTP y bucles de herramientas |
| Persistencia de Estado | Nativa y atómica por nodo (Checkpoints en DB) | Efímera en memoria / Delegada a base de datos externa |
| Pausa / Suspensión | Nativa (interrupt_before detiene el runtime) |
Requiere desacople externo (ej. Queues, Webhooks) |
| Latencia (TTFT) | Mayor: serialización de estado en DB relacional (~150-400 ms de overhead de infraestructura) | Mínima: streams directos desde runtime Edge (~20-50 ms de overhead) |
| Riesgo Operativo | Mayor complejidad de infraestructura (workers dedicados, gestión de pooling a DB) | Riesgo de HTTP 504 (Timeout) si el loop multi-step excede los límites de la función serverless |
| Tipado y Contratos | Pydantic / TypeScript TypedDict | Zod / JSON Schema nativo |
El costo de la persistencia frente al límite del Edge
En LangGraph, cada transición de nodo involucra serializar el estado completo a un almacén de datos. Esto garantiza tolerancia a fallos: si un worker se cae a mitad de una ejecución de 20 minutos, el grafo se reanuda desde el último snapshot válido.
En Vercel AI SDK, si un proceso encadena 4 llamadas de herramientas y el LLM tarda 15 segundos por paso, la conexión HTTP serverless permanece abierta durante más de 60 segundos. Si el proveedor de infraestructura corta la conexión por timeout (ej. 30 o 60 segundos en tiers estándar), el estado en tránsito se pierde por completo a menos que se implemente un mecanismo manual de checkpoints.
El Problema del Doble Stack y la Estandarización de Herramientas
Adoptar una arquitectura híbrida (LangGraph en backend y Vercel AI SDK en el frontend) introduce fricción operativa: duplicación de esquemas (Zod en TS vs. Pydantic en Python), doble instrumentación de observabilidad (OpenTelemetry + LangSmith) y divergencia en las suites de pruebas.
Para mitigar la divergencia de contratos, las herramientas deben desacoplarse de los frameworks mediante definiciones de esquemas agnósticos.
Contrato unificado: Definición de Esquema Compartido
// schemas/refundTool.ts
export const refundSchema = {
name: "processRefund",
description: "Procesa un reembolso comercial validando límites operativos.",
parameters: {
type: "object",
properties: {
ticketId: { type: "string" },
amount: { type: "number", minimum: 0 },
reason: { type: "string" }
},
required: ["ticketId", "amount", "reason"],
additionalProperties: false
}
} as const;
Este esquema JSON Schema puro se consume de forma directa en TypeScript vía zod-to-json-schema (o Zod puro) y se importa en Python vía Pydantic:
# python_agent/tools.py
from pydantic import BaseModel, Field
class RefundInput(BaseModel):
ticketId: str = Field(description="Identificador único del ticket")
amount: float = Field(gt=0, description="Monto a reembolsar")
reason: str = Field(description="Motivo de la solicitud")
Criterios de Selección Arquitectónica
Cuándo elegir LangGraph
- Workflows asíncronos de larga duración: Tareas que tardan minutos u horas, donde el estado debe persistir a través de reinicios de servidores o pausas humanas prolongadas.
- Grafos cíclicos complejos: Flujos con etapas de reflexión, corrección de código o multi-agentes que compiten y auditan salidas de forma recursiva.
- Requisitos estrictos de rollback: Procesos financieros donde sea indispensable auditar y revertir la ejecución a un nodo temporal previo.
Cuándo elegir Vercel AI SDK
- Interfaces orientadas al usuario final (UI-Bound): Chats interactivos, copilotos integrados en aplicaciones SaaS y autocompletados donde la métrica principal es un TTFT < 800 ms.
- Generative UI: Casos donde el LLM devuelve componentes interactivos que se montan en el cliente React en tiempo real vía Server Actions.
- Pipelines acotados: Tareas que se resuelven en 1 o 2 pasos deterministas de llamado a herramientas sin dependencias cíclicas.
Plan de Acción
- Clasificar los casos de uso del backlog:
- Categoría A (Interacción sincrónica): Asistentes conversacionales y autocompletados. Usar Vercel AI SDK con streaming SSE directo.
- Categoría B (Orquestación asincrónica): Procesamiento de documentos por lotes, agentes de auditoría y reconciliaciones. Usar LangGraph con checkpointers en base de datos.
- Definir límites de tiempo de ejecución (Timeouts): Si una ruta serverless que utiliza
streamTextsupera regularmente los 25 segundos debido a llamadas múltiples de herramientas, extraer el bucle hacia un worker de LangGraph y comunicar el estado a la UI mediante WebSockets o sondeo (polling). - Centralizar la definición de contratos: Unificar las definiciones de herramientas en un repositorio compartido o paquete interno utilizando JSON Schema para evitar divergencias entre TypeScript y Python.
- Medir el TTFT real: Instrumentar métricas de red para evaluar el overhead de serialización. Si la persistencia de checkpoints en LangGraph penaliza la experiencia interactiva del usuario, desacoplar la capa de presentación de la capa de orquestación central.
En el fondo no es LangGraph contra Vercel AI SDK: es orquestación con estado y reactividad en el edge, cada una en su lugar. La decisión no es de framework, es de la forma de tu carga de trabajo —y ahora tenés los criterios para no terminar peleándote con la herramienta equivocada.