Ejecución del SDK de Anthropic en Entornos de Ejecución Edge
El paquete oficial @anthropic-ai/sdk está construido sobre fetch, por lo que se ejecuta sin modificaciones en entornos de ejecución edge como Vercel Edge Functions, Cloudflare Workers y Deno Deploy, no solo en Node.js. Esta página cubre cómo configurar el cliente y transmitir respuestas correctamente en cada plataforma.
Resumen
Los entornos de ejecución edge son entornos JavaScript ligeros que se ejecutan cerca de la solicitud, a menudo sin la superficie completa de la API de Node.js. No tienen fs, net ni muchas otras utilidades integradas de Node disponibles.
@anthropic-ai/sdk evita ese problema porque su ruta de solicitud está construida sobre la API estándar fetch, ReadableStream y AbortController, todas las cuales están disponibles en todos los entornos de ejecución edge modernos.
Las principales diferencias entre las implementaciones edge y Node.js son cómo lees la clave API (el acceso a las variables de entorno difiere según la plataforma) y cómo devuelves una respuesta transmitida (los manejadores edge normalmente devuelven un objeto Response directamente en lugar de escribir en una http.ServerResponse de Node.js).
Esta página recorre una Vercel Edge Function (a través de un manejador de ruta de Next.js), una Cloudflare Worker y notas sobre Deno Deploy, cada una configurando el cliente y transmitiendo una respuesta al llamador.
Los tiempos de espera y la cancelación funcionan de la misma manera en edge que en Node.js: pasa un AbortSignal a la solicitud, o confía en la configuración de tiempo de espera propia del SDK, pero recuerda que la plataforma también impone su propio límite de tiempo de ejecución además de cualquier cosa que configures.
Receta
Tarjeta de receta de referencia rápida, lista para copiar y pegar.
// Funciona idénticamente en Node.js, Vercel Edge, Cloudflare Workers y Deno Deploy
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
const message = await anthropic.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Explica los entornos de ejecución edge en un párrafo." }],
});
console.log(message.content);Cuándo recurrir a esto:
- Servir respuestas de Claude de baja latencia desde una ubicación cercana al usuario (Vercel Edge, Cloudflare Workers se ejecutan en el borde de la red).
- Implementar en una plataforma que no admita el tiempo de ejecución completo de Node.js (Cloudflare Workers, Deno Deploy).
- Transmitir una respuesta de chat directamente al navegador sin almacenar en búfer la respuesta completa primero.
- Mantener bajo el tiempo de arranque en frío de una función sin servidor; los entornos de ejecución edge generalmente arrancan más rápido que las funciones de Node.js.
Ejemplo de trabajo
Vercel Edge Function (manejador de ruta de Next.js)
// app/api/chat/route.ts
import Anthropic from "@anthropic-ai/sdk";
export const runtime = "edge";
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
export async function POST(req: Request) {
const { prompt } = await req.json();
const stream = await anthropic.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [{ role: "user", content: prompt }],
stream: true,
});
const encoder = new TextEncoder();
const body = new ReadableStream({
async start(controller) {
for await (const event of stream) {
if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
controller.enqueue(encoder.encode(event.delta.text));
}
}
controller.close();
},
});
return new Response(body, {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
}Lo que esto demuestra:
- Establecer
export const runtime = "edge"opta el manejador de ruta de Next.js en el entorno de ejecución Vercel Edge. - La clave API se lee de
process.env.ANTHROPIC_API_KEY, que Vercel inyecta en las funciones edge de la misma manera que lo hace para las funciones Node.js, siempre que la variable de entorno esté configurada en la configuración del proyecto. - El iterador asíncrono del SDK (
for await (const event of stream)) se envuelve en unReadableStreampara que el manejador pueda devolver unaResponsetransmitida en lugar de esperar el mensaje completo. - Solo se reenvían al cliente los deltas de eventos de bloque de contenido de tipo
text_delta; otros tipos de eventos (inicio de mensaje, inicio/fin de bloque de contenido, fin de mensaje) se ignoran para este caso simple de transmisión de texto.
Cloudflare Worker
// src/worker.ts
import Anthropic from "@anthropic-ai/sdk";
export interface Env {
ANTHROPIC_API_KEY: string;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== "POST") {
return new Response("Use POST", { status: 405 });
}
const anthropic = new Anthropic({
apiKey: env.ANTHROPIC_API_KEY,
});
const { prompt } = await request.json<{ prompt: string }>();
const stream = await anthropic.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [{ role: "user", content: prompt }],
stream: true,
});
const encoder = new TextEncoder();
const body = new ReadableStream({
async start(controller) {
for await (const event of stream) {
if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
controller.enqueue(encoder.encode(event.delta.text));
}
}
controller.close();
},
});
return new Response(body, {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
},
};Lo que esto demuestra:
- Cloudflare Workers pasa la configuración y los secretos a través de un objeto
envtipado pasado como argumento afetch, no a través deprocess.env.ANTHROPIC_API_KEYse declara en una interfazEnvy se lee comoenv.ANTHROPIC_API_KEY. - El secreto en sí se establece fuera del código, con
wrangler secret put ANTHROPIC_API_KEY, por lo que nunca vive en el repositorio ni en el archivowrangler.toml. - El cliente se instancia dentro del manejador
fetch(no en el ámbito del módulo) para que siempre capte los enlacesenvpara la solicitud actual. - El patrón de transmisión es idéntico al ejemplo de Vercel Edge porque ambas plataformas implementan los mismos estándares web
ReadableStreamyResponse.
Cancelación de la Llamada Upstream ante la Desconexión del Cliente
Ambos ejemplos anteriores pueden reenviar el AbortSignal de la solicitud entrante a la llamada del SDK, de modo que la desconexión del cliente cancele la solicitud upstream a Claude en lugar de dejar que se complete:
const message = await anthropic.messages.create(
{
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [{ role: "user", content: prompt }],
},
{ signal: request.signal },
);- Conectar
AbortControllera la señal de la solicitud entrante significa que cancelar el cliente (cerrar la pestaña del navegador, navegar a otra página) también cancela la llamada upstream a Claude, en lugar de dejar que se complete y consuma tokens para una respuesta que nadie leerá. request.signalestá disponible en el objetoRequesttanto en Vercel Edge Functions como en Cloudflare Workers porque ambas implementan la API estándar de Fetch.
Análisis Profundo
Cómo funciona
@anthropic-ai/sdkenvía solicitudes con la funciónfetchglobal en lugar de un cliente HTTP específico de Node, por lo que no tiene dependencia de las utilidades integradas de Node comohttp,httpsonetpara su ruta de solicitud principal.- Las respuestas transmitidas de la API de Mensajes llegan como eventos enviados por el servidor (server-sent events), que el SDK analiza y expone como un iterable asíncrono de eventos de mensajes tipados (
for await (const event of stream)). - Los entornos de ejecución edge ejecutan tu manejador en un sandbox ligero, a menudo basado en aislados de V8, no en un proceso completo de Node.js, por lo que las API exclusivas de Node (
fs,child_process, módulos nativos) no están disponibles y un SDK basado en fetch es el factor decisivo para la compatibilidad. - Dado que el ciclo de solicitud/respuesta en un manejador edge se basa en los mismos primitivos
Request/Response/ReadableStreamque el SDK utiliza internamente, puedes canalizar la transmisión del SDK directamente al valor de retorno de la función sin una capa adaptadora.
Manejo de Claves API por Plataforma
| Plataforma | Dónde vive la clave | Cómo la lees |
|---|---|---|
| Vercel Edge Function | Variables de entorno del proyecto (panel de Vercel o .env.local para desarrollo local) | process.env.ANTHROPIC_API_KEY |
| Cloudflare Worker | Secreto establecido a través de wrangler secret put ANTHROPIC_API_KEY | env.ANTHROPIC_API_KEY (pasado como argumento a fetch) |
| Deno Deploy | Variable de entorno del proyecto configurada en el panel de Deno Deploy (o .env para desarrollo local con deno run --env) | Deno.env.get("ANTHROPIC_API_KEY") |
Notas sobre Deno Deploy
// main.ts (Deno Deploy)
import Anthropic from "npm:@anthropic-ai/sdk";
const anthropic = new Anthropic({
apiKey: Deno.env.get("ANTHROPIC_API_KEY"),
});
Deno.serve(async (request: Request) => {
const { prompt } = await request.json();
const message = await anthropic.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [{ role: "user", content: prompt }],
});
return Response.json(message);
});- Deno Deploy importa paquetes npm con el especificador
npm:, por lo queimport Anthropic from "npm:@anthropic-ai/sdk"funciona sin unpackage.jsono un paso de compilación. - Los secretos se leen con
Deno.env.get(...), no conprocess.env; Deno expone un shimprocesspara compatibilidad, peroDeno.enves la ruta nativa y recomendada. Deno.servees el punto de entrada HTTP integrado en Deno Deploy y, al igual que las otras dos plataformas, toma y devuelve objetosRequest/Responseestándar.
Notas sobre TypeScript
// Estrecha la unión de eventos de transmisión antes de leer delta.text
for await (const event of stream) {
if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
// event.delta.text está tipado de forma segura como string aquí
process.stdout.write(event.delta.text);
}
}- El SDK envía sus propios tipos de TypeScript, por lo que
message.content, los eventos de transmisión y las clases de error están tipados sin paquetes@typesadicionales. - Los eventos de transmisión son una unión discriminada en
event.type; estrechar con una verificaciónif(como se muestra arriba) es lo que le indica a TypeScript queevent.delta.textexiste, en lugar de recurrir a una aserción de tipo. - Evita las aserciones
as anyen la opciónapiKeydel cliente. Siprocess.env.ANTHROPIC_API_KEY(oenv.ANTHROPIC_API_KEY) esundefineden tiempo de ejecución porque la variable no se estableció, deja que el SDK genere su error de autenticación normal en lugar de silenciar el verificador de tipos.
Parámetros y Valores de Retorno
| Parámetro | Tipo | Descripción |
|---|---|---|
apiKey | string | Clave API de Anthropic. Requerida a menos que se establezca a través de ANTHROPIC_API_KEY en un entorno que el SDK lea automáticamente (solo Node.js; los entornos edge deben pasarla explícitamente). |
timeout | number | Milisegundos antes de que el SDK cancele la solicitud del lado del cliente. Independiente del límite de ejecución propio de la plataforma edge. |
maxRetries | number | Número de reintentos automáticos en errores transitorios (límites de tasa, fallos de red, respuestas 5xx). Predeterminado a 2. |
signal | AbortSignal | Pasado por solicitud para cancelar una llamada en curso, por ejemplo anthropic.messages.create(params, { signal }). |
Trampas
- Lectura de
process.enven Cloudflare Workers. Cloudflare Workers no rellenaprocess.envcon secretos por defecto; pasan la configuración a través del argumentoenven el manejadorfetch. Solución: leeenv.ANTHROPIC_API_KEYdentro del manejador, noprocess.env.ANTHROPIC_API_KEYen el ámbito del módulo. - Instanciación del cliente en el ámbito del módulo en Cloudflare Workers. Si construyes el cliente
Anthropicfuera del manejadorfetch,envno está disponible todavía cuando se carga el módulo. Solución: construye el cliente dentro de la función manejadora dondeenvse pasa como argumento. - Asumir que los entornos edge no tienen tiempo de espera. Vercel Edge Functions, Cloudflare Workers y Deno Deploy imponen su propio tiempo máximo de ejecución o tiempo de CPU por solicitud, además de cualquier cosa que configures en el cliente del SDK. Solución: consulta los límites actuales para tu plan en cada plataforma y diseña generaciones de larga duración en torno a la transmisión (devuelve la salida parcial a medida que llega) en lugar de esperar una única respuesta grande no transmitida.
- Olvidar establecer
stream: truey luego intentar iterar el resultado. Llamar aanthropic.messages.create()sinstream: truedevuelve un único objetoMessageresuelto, no un iterable asíncrono; intentar un buclefor awaitsobre él falla. Solución: pasastream: trueen los parámetros de la solicitud siempre que pretendas consumir la respuesta como una transmisión. - No estrechar la unión de eventos de transmisión antes de leer
delta.text. Los eventos de transmisión incluyen varios tipos (message_start,content_block_start,content_block_delta,content_block_stop,message_stop, y más), y solo los eventoscontent_block_deltacondelta.type === "text_delta"contienen.text. Solución: verifica tantoevent.typecomoevent.delta.typeantes de leerevent.delta.text. - Dejar la clave API en el código del lado del cliente. Dado que las funciones edge se ejecutan en el lado del servidor, es tentador pensar que cualquier código en el mismo repositorio es seguro, pero una clave codificada directamente en un manejador de ruta que también envía un paquete cliente (o copiada y pegada en una Cloudflare Worker comprometida en el control de código fuente) puede filtrarse. Solución: carga siempre la clave desde una variable de entorno o una tienda de secretos, nunca la codifiques, y añade archivos
.env*a.gitignore. - Asumir que
AbortControllernecesita una importación específica de Node.AbortControlleryAbortSignalson globales en Node.js 18+, todos los navegadores principales y todos los entornos edge cubiertos aquí, por lo que no se necesita ninguna importación o polyfill. Solución: simplemente usa elAbortControllerglobal, o reenvíarequest.signalde unaRequestentrante cuando quieras que las desconexiones del cliente cancelen la llamada upstream a Claude.
Alternativas
| Alternativa | Usar cuando | No usar cuando |
|---|---|---|
| Función sin servidor Node.js (entorno Node de Vercel, AWS Lambda) | Necesitas APIs completas de Node.js (acceso al sistema de archivos, ciertos paquetes npm nativos) junto con la llamada al SDK. | La latencia a la ubicación edge más cercana importa más que la compatibilidad con Node, o la plataforma factura las funciones edge y Node de manera diferente y las edge son más baratas para tu tráfico. |
| Un servidor backend dedicado (Express, Fastify) que llama al SDK | Ya ejecutas un proceso de servidor de larga duración y deseas registro centralizado, agrupación de conexiones o integraciones no HTTP. | Quieres escalado por solicitud a cero y baja latencia de arranque en frío, que los entornos edge y las funciones sin servidor proporcionan de forma más natural que un servidor siempre activo. |
Llamar a la API de Mensajes con fetch en bruto en lugar del SDK | Necesitas un paquete mínimo sin dependencias, o estás en un entorno en el que el SDK no ha sido verificado. | Quieres formas de solicitud/respuesta tipadas, manejo de reintentos y tiempos de espera integrados, y análisis de eventos de transmisión, que el SDK proporciona de inmediato. |
Preguntas Frecuentes
¿El SDK de TypeScript de Anthropic necesita alguna compilación o paquete especial para entornos edge?
No. Instala el mismo paquete @anthropic-ai/sdk que usarías en Node.js. Funciona en entornos de ejecución edge porque su ruta de solicitud está construida sobre fetch, ReadableStream y AbortController, todas las cuales son API web estándar disponibles en entornos edge.
¿Por qué `process.env.ANTHROPIC_API_KEY` no funciona en mi Cloudflare Worker?
- Cloudflare Workers no rellena automáticamente
process.envcon secretos como lo hace Node.js. - Los secretos y variables se pasan como el argumento
enval manejadorfetchen su lugar. - Lee la clave como
env.ANTHROPIC_API_KEYdentro del manejador, y configúrala conwrangler secret put ANTHROPIC_API_KEY.
¿Puedo transmitir una respuesta de Claude directamente al navegador desde una función edge?
Sí. Envuelve el iterador asíncrono del SDK en un ReadableStream, encola cada delta de texto a medida que llega y devuelve esa transmisión como el cuerpo de un objeto Response estándar. Tanto Vercel Edge Functions como Cloudflare Workers aceptan un ReadableStream como cuerpo de Response de forma nativa.
¿Cómo configuro la clave API para un proyecto Deno Deploy?
Establécela como una variable de entorno en el panel del proyecto Deno Deploy (o en un archivo .env local para desarrollo), luego léela con Deno.env.get("ANTHROPIC_API_KEY") en lugar de process.env.
¿Necesito instalar algo diferente para importar el SDK en Deno?
No se requiere ningún paso de instalación separado. Usa el especificador npm: para importar directamente, por ejemplo import Anthropic from "npm:@anthropic-ai/sdk", y Deno resuelve el paquete npm en tiempo de ejecución.
¿Funcionarán `maxRetries` y `timeout` todavía en entornos edge?
Sí, ambas opciones funcionan de la misma manera que en Node.js, ya que se implementan sobre fetch y temporizadores estándar. Ten en cuenta que la plataforma edge también aplica su propio tiempo máximo de ejecución de forma independiente, por lo que un tiempo de espera generoso del SDK no anula el límite de la plataforma.
¿Qué sucede si olvido establecer `stream: true`?
anthropic.messages.create() devuelve un único objeto Message resuelto en lugar de un iterable asíncrono. Intentar ejecutar un bucle for await sobre un resultado no transmitido fallará, así que asegúrate de que stream: true esté configurado siempre que pretendas consumir la respuesta incrementalmente.
¿Cómo cancelo una solicitud de Claude en curso si el usuario navega a otra página?
Reenvía el AbortSignal de la solicitud entrante a la llamada del SDK, por ejemplo anthropic.messages.create(params, { signal: request.signal }). Cuando el cliente se desconecta, la plataforma aborta la señal y el SDK cancela la solicitud upstream a Claude.
¿Qué tipo de evento de transmisión contiene realmente el texto que quiero mostrar?
Los eventos content_block_delta donde event.delta.type === "text_delta" contienen el texto incremental en event.delta.text. Otros tipos de eventos como message_start, content_block_start y message_stop marcan límites estructurales en la transmisión y no contienen contenido de texto.
¿Es seguro codificar mi clave API directamente en el archivo fuente de una Cloudflare Worker para una prueba rápida?
No. Incluso para pruebas, carga la clave desde una variable de entorno o un secreto de Cloudflare. Una clave confirmada en el control de código fuente (incluso temporalmente) puede terminar en el historial de versiones o en un repositorio público, y los secretos de Workers configurados con wrangler secret put son la forma admitida de mantenerla completamente fuera del código base.
¿Se ejecuta el mismo código sin cambios en Vercel Edge, Cloudflare Workers y Deno Deploy?
El uso del SDK (construcción del cliente, messages.create, transmisión) es el mismo en los tres. Lo que difiere es cómo cada plataforma expone las variables de entorno/secretos (process.env en Vercel, un argumento env en Cloudflare, Deno.env.get en Deno) y, para Cloudflare, cómo se da forma a la firma del manejador fetch.
¿Necesito un polyfill para `AbortController` en alguna de estas plataformas?
No. AbortController y AbortSignal están disponibles globalmente en Node.js 18+, y en Vercel Edge Functions, Cloudflare Workers y Deno Deploy, ya que todas implementan la superficie estándar de la API Fetch.
Relacionado
- Conceptos básicos del SDK de TypeScript/JavaScript - instalación del SDK y envío de tu primera llamada tipada a la API de Mensajes.
- Iteradores asíncronos para transmisión en el SDK de TypeScript - una mirada más cercana al consumo de deltas de mensajes transmitidos.
- Patrones de reintento, tiempo de espera y AbortController en el SDK de TypeScript - ajuste de retroceso y cancelación con más detalle.
- Creación de un punto final de chat de transmisión con Next.js y el SDK de TypeScript - un punto final de chat completo construido sobre el patrón de transmisión que se muestra aquí.
- El modelo mental del SDK de TypeScript de Anthropic - cómo encajan el modelo de solicitud/respuesta y transmisión del SDK.
Versiones de Stack: Escrito contra la línea de modelos de Claude actual a partir de ~junio de 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (el predeterminado), y Claude Haiku 4.5 - y el SDK oficial de TypeScript
@anthropic-ai/sdk(última versión). Los nombres de modelos, versiones de SDK y precios cambian rápidamente; verifica los detalles actuales en platform.claude.com/docs antes de confiar en ellos.