API de Anthropic en Next.js: streaming, caché y control de costes
Cómo conectar Claude a una app Next.js: route handler en el servidor, streaming SSE, prefijo cacheado al 10% de entrada y reintentos que aguantan un 429.
Al final de esta guía tienes un route handler de Next.js que envía la respuesta de Claude al navegador según se genera, un system prompt en caché que en las llamadas siguientes cuesta una décima parte de la tarifa de entrada, reintentos que aguantan un límite de peticiones y un coste por llamada que puedes meter en una hoja de cálculo antes de publicar.
Es el patrón que usamos cuando un cliente pide IA dentro del producto. Un resumidor de tickets. Un generador de borradores. Un clasificador que lee los datos del propio cliente. Superficie pequeña, mucho tráfico, dinero real en cada llamada. Los frameworks de agentes son otro artículo. Aquí hablamos de la fontanería que hay debajo.
Qué necesitas antes de escribir código
Tres cosas. La tercera es la que casi todos se saltan.
- Una clave de API de la Consola de Anthropic, guardada en el servidor.
- Una decisión sobre en qué runtime corre el handler.
- Tres números: llamadas al día, tokens de entrada medios, tokens de salida medios.
Sin el tercero, el coste es una sorpresa que llega a final de mes. Una función con 2.000 llamadas diarias y un system prompt de 4.000 tokens se comporta de forma muy distinta a la misma función con 200 llamadas y un prompt de 400 tokens, y la solución cambia en cada caso. Los órdenes de magnitud por tipo de función están en nuestro análisis del coste de integrar IA en un SaaS.
¿SDK de Anthropic o AI SDK de Vercel?
Las dos respuestas se sostienen. La decisión va de cuánto quieres atarte a un proveedor.
@anthropic-ai/sdk es el cliente oficial. Tienes cada parámetro específico de Claude el mismo día que sale: los puntos de corte de caché, el razonamiento extendido, la forma completa de los eventos de streaming. Lo usamos cuando la función de IA es el producto.
El AI SDK de Vercel pone una sola interfaz sobre muchos proveedores, cada uno en su paquete (@ai-sdk/anthropic, @ai-sdk/openai). Cambiar de modelo pasa a ser un cambio de dos líneas, y useChat en el cliente ahorra un día de parseo del stream. El precio es el retraso: una abstracción sobre una docena de proveedores siempre llega tarde a la novedad de cada uno. Lo usamos cuando la libertad de cambiar de proveedor está escrita en el contrato.
Paso 1: la clave se queda en el servidor
La clave vive en ANTHROPIC_API_KEY, nunca en una variable NEXT_PUBLIC_, y la llamada ocurre dentro de un Route Handler. Lo dice cualquier guía de inicio. Aun así aparece en producción donde no debe. Una clave dentro del bundle del navegador es una clave en la factura de otro.
import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic()
export async function POST(req: Request) {
const { question } = await req.json()
const stream = client.messages.stream({
model: 'claude-sonnet-5',
max_tokens: 1024,
system: SYSTEM_PROMPT,
messages: [{ role: 'user', content: question }],
})
return new Response(stream.toReadableStream())
}Las Server Actions también valdrían, pero aquí la forma correcta es el Route Handler: estás devolviendo un stream, no cambiando un estado. Esa línea la trazamos en RPC con tipos usando Server Actions.
Paso 2: streaming, porque la espera parece una avería
Una respuesta de 1.000 tokens tarda varios segundos en generarse. Pintada de golpe es un spinner y un usuario que recarga la página. En streaming las primeras palabras llegan en menos de un segundo y el mismo tiempo de reloj se percibe corto.
La Messages API transmite por server-sent events. En el SDK de TypeScript, .stream() mantiene la conexión abierta y emite eventos tipados, y .finalMessage() los acumula en el mensaje completo, útil cuando también necesitas la respuesta entera en el servidor para registrarla o guardarla en base de datos.
Hay dos detalles que conviene clavar. Registra el mensaje final en el servidor y no en el navegador, o las métricas pierden en silencio cada petición abandonada. Y decide qué significa una respuesta a medias en tu modelo de datos. Nosotros escribimos la fila en message_stop y marcamos como fallido todo lo que se corta antes, así las generaciones truncadas no acaban en el histórico del producto.
Paso 3: cachea el prefijo estático
Casi todas las funciones de IA de producto mandan los mismos 2.000-8.000 tokens en cada llamada: system prompt, definición de herramientas, esquema de los datos del cliente, unos cuantos ejemplos. Pagarlos a precio completo de entrada cada vez es el desperdicio más habitual que encontramos en funciones de IA publicadas sin revisión.
El prompt caching lo quita. Marca el final de la parte estática con un punto de corte de caché. Escribir la caché cuesta 1,25 veces la tarifa base de entrada con un TTL de cinco minutos, y cada lectura posterior de ese prefijo cuesta el 10%, según la página de precios de Anthropic. El punto de equilibrio llega en la segunda llamada.
Una sola regla lo sostiene: ordena la petición empezando por lo estático. El prefijo cacheado tiene que coincidir exactamente, así que todo lo que cambia en cada petición (la pregunta, una marca de tiempo, el nombre del tenant) va después del punto de corte. Basta un valor dinámico en mitad del system prompt para que la tasa de acierto caiga a cero, y ningún error te avisa. Mira cache_read_input_tokens en el bloque usage de la respuesta: si en la segunda llamada idéntica marca 0, el prefijo se ha movido.
Paso 4: 429 y 529 son tráfico normal
Van a llegar los dos. Un 429 significa que has superado un límite de peticiones y trae la cabecera retry-after con el tiempo de espera. Un 529 significa que la API está sobrecargada de forma temporal: va de capacidad del servicio, no de tu cuenta.
Los SDK oficiales ya reintentan dos veces por defecto ante fallos transitorios, con backoff exponencial y respetando retry-after. Eso cubre los casos aburridos. No cubre el interesante: un fallo cuando los primeros bytes ya han llegado al navegador. Reintentar en el servidor en ese momento manda una respuesta duplicada. Nosotros retenemos la respuesta hasta que el stream está establecido y luego mostramos cualquier corte posterior como un error visible con un botón para reintentar, en lugar de coser dos generaciones y confiar en que nadie lea con atención.
Pon un timeout propio por debajo del de la plataforma, para que el usuario lea tu mensaje de error y no una página 504.
Paso 5: saca del camino de la petición lo que no es interactivo
Resúmenes nocturnos, clasificación masiva, reetiquetar 40.000 filas antiguas: nada de eso necesita una conexión abierta. La Message Batches API admite hasta 10.000 peticiones por lote, responde en menos de 24 horas y cuesta un 50% menos que las mismas llamadas hechas en síncrono. El descuento se suma al prompt caching.
Nuestra regla: si no hay una persona esperando la respuesta, va en lote. En un producto maduro, buena parte de la factura de IA está en trabajos que acabaron en el camino interactivo por costumbre, no por necesidad.
Paso 6: elige runtime y presupuesto de duración
Un handler de IA en streaming es una petición larga, y eso convierte la elección de runtime en una decisión real y no en un valor por defecto. En Vercel, una función que se pasa de presupuesto devuelve un 504 FUNCTION_INVOCATION_TIMEOUT a mitad del stream y el usuario se queda con una respuesta cortada.
El runtime Edge transmite hasta 300 segundos pero tiene que empezar a responder en 25 segundos. Va sobrado para un chat y va mal cuando el primer token espera una consulta lenta. Las funciones Node en los planes Pro y Enterprise llegan ya a 30 minutos, lo que cubre generaciones largas y orquestación de lotes. Nuestro valor por defecto es Node siempre que el handler toque la base de datos antes de llamar a Claude, y Edge para prompts sin estado donde lo único que importa es la latencia percibida. La comparación completa está en Edge runtime frente a Node runtime.
Qué no te da este patrón
La distancia entre una demo que funciona y una función por la que puedes cobrar está casi toda aquí.
- Ninguna evaluación. Nada de lo anterior te dice si las respuestas son buenas. Un conjunto de 30 a 50 ejemplos corregidos a mano, reejecutado en cada cambio de prompt, es el control de calidad más barato que hay en el trabajo con IA y lo primero que se aplaza.
- Ningún presupuesto por usuario. Los límites de Anthropic aplican a tu organización, no a tus clientes. Un solo usuario en bucle deja sin cuota al resto de tenants.
- Ninguna defensa ante prompt injection. Cualquier texto de usuario que llegue al modelo puede intentar reescribir sus instrucciones. Trata la salida del modelo como entrada no fiable para el resto del sistema, sobre todo si las herramientas pueden escribir.
- Ningún contrato de salida. El texto libre sirve para un resumen y no sirve para un campo de base de datos. Fija la forma con herramientas o structured outputs antes de parsear la respuesta.
El orden importa más que cualquier punto suelto de la lista. Clave en el servidor, luego streaming, luego caché, luego reintentos, luego lotes, luego runtime. Quien empieza por la caché sin tener los números de tráfico optimiza el prefijo equivocado. Quien empieza por el runtime reescribe el handler dos veces.
Preguntas frecuentes
¿Cómo calculo el coste mensual de una función de IA antes de construirla?
Parte de tres números: llamadas al día, tokens de entrada medios y tokens de salida medios. Multiplica por las tarifas por token del modelo elegido y por 30. Luego aplica dos correcciones. Los tokens del prefijo cacheado se facturan al 10% de la tarifa de entrada tras la primera escritura, y todo lo que muevas a la Message Batches API se factura al 50%. Añade un 30% de margen para los reintentos y para respuestas más largas que tus prompts de prueba. Antes de fiarte, manda 20 prompts reales a la API y compara los tokens medidos con tu estimación.
¿Qué pasa con mi producto cuando la API de Anthropic se cae?
Recibes errores 529 de sobrecarga, y la decisión es de producto más que de ingeniería. Tres caminos: encolar la petición y entregar la respuesta luego por email o notificación, tirar de un segundo proveedor detrás de la misma interfaz, o fallar de forma visible y dejar que el usuario reintente. La cola funciona para todo lo asíncrono. El segundo proveedor cuesta un segundo prompt que mantener, porque en la práctica los prompts no son portables. Fallar de forma visible es lo honesto en funciones interactivas y exige un estado de error real en la interfaz, diseñado antes del lanzamiento y no después de la primera caída.
¿Anthropic entrena sus modelos con los datos enviados por la API?
No. En los términos comerciales, las entradas y salidas de la API no se usan para entrenar modelos salvo que el cliente lo autorice de forma explícita, por ejemplo en un programa de partners. Cubre la API, Claude for Work y los modelos servidos vía Amazon Bedrock y Google Cloud Vertex AI. Aun así no responde a todo lo que preguntará una revisión de cumplimiento: plazos de conservación, subencargados, residencia de los datos y un DPA firmado son cuestiones aparte, y en un producto sanitario o financiero van en el contrato antes de la primera petición.
¿Necesito mi propio control de peticiones además del de Anthropic?
Sí, en cualquier producto multi-tenant. Los límites de Anthropic aplican a la organización entera, así que un único cliente atrapado en un bucle de reintentos se come la cuota del resto y los 429 los ve todo el mundo. Un contador en Redis con clave por usuario o por tenant, comprobado antes de la llamada, se resuelve en una tarde. El techo por usuario se fija desde tu tarifa, no desde el límite de la API: si un plan incluye 200 generaciones al mes, ese número va en el código, y pasarse debe leerse como límite de plan y no como error de servidor.
Artículos relacionados
Studio
Empieza un proyecto.
Un partner único para el producto digital que necesitas construir. Producción más rápida, tecnología moderna, costes reducidos. Un equipo, una factura.