← todos los posts
agentes·3 de septiembre de 2026·6 min

Cuándo usar LangGraph frente a Vercel AI SDK en tus agentes

Aprendé cuándo usar LangGraph o Vercel AI SDK según la persistencia y latencia de tu arquitectura, y cómo integrarlos sin duplicar esquemas.

Querés armar un flujo que apruebe reembolsos de clientes. Si el monto es chico, sale automático; si supera los 500 dólares, necesitás que una persona lo apruebe antes de pagar.

Acá aparece el dilema clásico: ¿metés todo en una función serverless con streaming o levantás un orquestador con base de datos?

En este post vas a ver cuándo conviene usar LangGraph, cuándo Vercel AI SDK y cómo integrarlos sin romperte la cabeza con dos lenguajes distintos.


Comparación arquitectónica de LangGraph frente a Vercel AI SDK

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 (stopWhen)"}
        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 adapta el modelo Pregel de Google para agentes. Modela el flujo como un grafo donde el estado pasa por funciones reductoras puras, en vez de usar scripts lineales. Si querés profundizar en esta diferencia, revisá esta nota sobre bucles vs. grafos para estructurar agentes de IA.

Su pieza clave es el checkpointer. Guarda una foto del estado en PostgreSQL, SQLite o Redis en cada paso de ejecución:

  • Suspensión determinista: Podés frenar el proceso con interrupt_before o interrupt_after y apagar el worker sin perder datos.
  • Viaje en el tiempo: Podés volver a un paso anterior de la ejecución y reintentar desde ahí si algo falló.

Siguiendo el caso del reembolso, así frenás el flujo hasta que un analista revise el caso:

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 guarda un grafo en backend. Su foco es resolver rápido el transporte HTTP mediante Server-Sent Events (SSE) y atar la respuesta a hooks de React como useChat.

Ejecuta un bucle de llamadas a herramientas controlado con stopWhen, tal como explica la documentación de tool calling en Vercel AI SDK. Como corre en entornos serverless, las pausas humanas largas no son nativas: tenés que derivar el trabajo a un sistema externo.

Mirá cómo resolverías la misma aprobación de reembolso con este enfoque:

import { streamText, tool, stepCountIs } 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,
    stopWhen: stepCountIs(5), // corta el loop de tool calling tras N pasos (v5)
    tools: {
      requestHumanApproval: tool({
        description: 'Escala la transacción si el monto supera los 500 USD.',
        inputSchema: 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.toUIMessageStreamResponse();
}

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: la serialización de estado en DB agrega overhead de infraestructura (del orden de cientos de ms) Mínima: streams directos desde runtime Edge (overhead de decenas de ms)
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 / TypedDict (Python) Zod / JSON Schema nativo

El costo de la persistencia frente al límite del Edge

LangGraph guarda todo el estado en cada paso. Si un worker muere durante un reembolso que tarda 20 minutos, el grafo levanta el snapshot y sigue sin problemas. Si querés evitar el impacto de una base relacional acá, leé sobre cómo guardar memoria para agentes LangGraph en DynamoDB.

En Vercel AI SDK la conexión queda abierta durante todo el proceso. Si tu agente encadena 4 llamadas de herramientas y el LLM demora 15 segundos por paso, superás el minuto de ejecución.

En planes estándar donde el timeout ronda los 30 o 60 segundos, la función se corta con un error 504 y el estado se pierde.


El problema del doble stack y la estandarización de herramientas

Tener LangGraph en Python y Vercel AI SDK en TypeScript te parte el sistema en dos. Terminás con esquemas duplicados (Zod y Pydantic), métricas partidas entre OpenTelemetry y LangSmith, y tests que divergen.

Para no duplicar lógica, lo mejor es definir tus herramientas con esquemas neutrales.

Contrato unificado: definición de esquema compartido

Definís el reembolso una sola vez usando JSON Schema puro:

// 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;

Ese mismo archivo lo usás en TypeScript con zod-to-json-schema y lo mapeás en tu agente de Python con 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: Procesos que tardan minutos u horas y tienen que sobrevivir a despliegues de código o aprobaciones humanas lentas.
  • Grafos cíclicos complejos: Flujos con etapas de reflexión, corrección automática de código o agentes que auditan los resultados de otros en bucle.
  • Requisitos estrictos de rollback: Tareas financieras donde necesitás auditar cada paso y poder volver el estado a un punto exacto del pasado.

Cuándo elegir Vercel AI SDK

  • Interfaces orientadas al usuario final (UI-Bound): Chats interactivos o copilotos dentro de tu SaaS donde el tiempo de respuesta inicial debe ser menor a 800 ms.
  • Generative UI: Respuestas donde el modelo devuelve componentes de React que se renderizan directo en la interfaz vía Server Actions.
  • Pipelines acotados: Operaciones directas de 1 o 2 llamadas a herramientas sin loops complejos.

Plan de acción

  1. Separar los casos de uso: Mandá a Vercel AI SDK lo que requiera respuesta inmediata en pantalla (Categoría A), y dejá en LangGraph los procesos pesados de fondo como auditorías o reembolsos manuales (Categoría B).
  2. Controlar los timeouts: Si una ruta con streamText pasa los 25 segundos por encadenar llamadas, pasá ese trabajo a un worker de LangGraph y avisale al frontend por WebSockets o polling.
  3. Unificar contratos en JSON Schema: Creá un paquete compartido para los esquemas de herramientas y consumilo tanto desde TypeScript como desde Python.
  4. Monitorear el TTFT real: Medí cuánto tarda en llegar el primer token al usuario; si persistir checkpoints en LangGraph te suma mucha latencia en la UI, desacoplá la capa visual del motor de estado.