El modelo mental del SDK de TypeScript de Anthropic
El paquete @anthropic-ai/sdk es el cliente oficial de TypeScript y JavaScript para la API de Claude.
La mayoría de los desarrolladores lo conocen al instalarlo con npm install @anthropic-ai/sdk seguido de una única llamada a messages.create, y esa llamada funciona bien como primera impresión.
Pero la forma real del SDK solo se aclara una vez que comprendes las pocas decisiones de diseño que hay debajo: está construido sobre fetch en lugar de un cliente HTTP específico para Node, modela una respuesta de transmisión como un iterable asíncrono en lugar de un flujo de callbacks, y se apoya en las uniones discriminadas de TypeScript para que el compilador, y no tu memoria, rastree qué forma de datos tienes en cada momento.
Esta página construye ese modelo mental antes de que escribas cualquier código de producción contra el SDK.
Resumen
- Idea Central:
@anthropic-ai/sdkes un cliente delgado basado enfetchque convierte las llamadas HTTP a la API de Claude en objetos tipificados e iterables asíncronos. - Por qué Importa: Debido a que solo depende de
fetch, el mismo código de cliente se ejecuta en Node.js, Vercel Edge Functions, Cloudflare Workers y Deno Deploy sin una compilación específica del entorno de ejecución. - Conceptos Clave: instanciación del cliente, la API de Mensajes, transmisión a través de iteradores asíncronos, bloques de contenido de unión discriminada, configuración de reintentos y cancelación, clases de error tipificadas.
- Cuándo Usar: Utiliza este SDK siempre que llames a Claude desde TypeScript o JavaScript, ya sea un backend de Node, una función serverless o middleware edge.
- Limitaciones / Compensaciones: El SDK es una capa de transporte y tipificación, no un framework de agente. No gestiona el estado de la conversación, los bucles de ejecución de herramientas o la memoria por ti.
- Temas Relacionados: la forma de solicitud/respuesta de la API de Mensajes, definiciones de herramientas con Zod, configuración de reintentos y tiempos de espera, extremos de chat de transmisión en Next.js.
Fundamentos
En esencia, el SDK es un envoltorio alrededor de las solicitudes HTTP a la API de Claude.
Construyes un cliente Anthropic, generalmente una vez por proceso o por solicitud, y cada llamada posterior es un método en ese cliente.
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});El objeto cliente es deliberadamente poco llamativo.
Almacena tu clave API, tu URL base y tus opciones de solicitud predeterminadas (tiempos de espera, reintentos, encabezados), y expone espacios de nombres de recursos como client.messages que agrupan métodos relacionados.
Llamar a client.messages.create(...) envía una única solicitud HTTP y se resuelve con un objeto JavaScript plano una vez que llega la respuesta.
Ese objeto no es una instancia de clase especial con comportamiento oculto. Es JSON, tipificado.
Una analogía útil es que el SDK está más cerca de un envoltorio fetch bien tipificado que de un framework con estado.
No abre una conexión persistente, no recuerda giros anteriores de una conversación por ti, y no decide cuándo llamar a una herramienta.
Cada una de esas responsabilidades permanece en el código de tu aplicación. El trabajo del SDK es más estrecho: convertir un objeto de solicitud en una llamada HTTP validada y convertir la respuesta de nuevo en datos tipificados de TypeScript.
Mecánicas e Interacciones
Por qué importa la arquitectura basada en fetch
La mayoría de los clientes HTTP en el ecosistema de Node se basan en los módulos http y https propios de Node, que solo existen en un proceso de Node.js.
El SDK de TypeScript de Anthropic, en cambio, construye su capa de solicitud sobre la API estándar fetch, utilizando una implementación de fetch compatible con Node cuando se ejecuta en Node y el fetch nativo del entorno de ejecución en cualquier otro lugar.
Esa única elección es lo que permite que la misma importación, la misma construcción de cliente y la misma llamada messages.create se ejecuten sin modificaciones en una Vercel Edge Function, un Cloudflare Worker o un Deno Deploy isolate, ninguno de los cuales expone el módulo http de Node en absoluto.
En la práctica, esto significa que no eliges una "compilación para navegador" frente a una "compilación para servidor" del SDK.
Eliges dónde ejecutar tu código, y el SDK se adapta porque su capa más baja solo asume la presencia de fetch, ReadableStream y AbortController, todos los cuales son estándar en los entornos de ejecución de JavaScript modernos.
Transmisión como iterable asíncrono, no eventos
Una llamada sin transmisión espera a que llegue el cuerpo completo de la respuesta antes de resolverse.
Una llamada de transmisión es diferente: el servidor envía la respuesta como una secuencia de eventos enviados por el servidor, uno por token o por cambio estructural, y el trabajo del SDK es convertir ese flujo de eventos sin procesar en algo que puedas consumir incrementalmente.
Muchas bibliotecas de clientes HTTP exponen la transmisión como un EventEmitter, donde registras callbacks on("data", ...) y on("end", ...) y gestionas el estado entre llamadas tú mismo.
El SDK de Anthropic, en cambio, devuelve un objeto de flujo que es en sí mismo un iterable asíncrono, por lo que lo consumes con un bucle for await estándar.
const stream = client.messages.stream({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Explica los iterables asíncronos." }],
});
for await (const event of stream) {
if (event.type === "content_block_delta") {
process.stdout.write(event.delta.text ?? "");
}
}El cambio de mentalidad aquí importa más que la sintaxis.
Un modelo de oyente de eventos te obliga a construir tu propio acumulador y tu propia noción de "terminado", generalmente con una variable mutable que vive fuera del callback.
Un modelo de iterable asíncrono permite que el flujo de control de tu propia función exprese esa lógica: el cuerpo del bucle se ejecuta una vez por evento, y el bucle simplemente termina cuando el flujo termina, sin un manejador on end separado que mantener sincronizado.
El objeto de flujo también expone métodos de conveniencia, como esperar el mensaje final ensamblado, por lo que no estás obligado a concatenar manualmente los deltas cuando solo te interesa el resultado final.
Las uniones discriminadas dan forma a tu código
Una respuesta de Claude no tiene una forma fija.
Un solo mensaje puede contener un bloque de texto, un bloque de uso de herramientas y (cuando se habilita el pensamiento extendido) un bloque de pensamiento, en cualquier combinación y orden.
El SDK modela esto con una unión discriminada: cada tipo de bloque de contenido comparte un campo type, y el valor literal de ese campo ("text", "tool_use", "thinking") es lo que TypeScript utiliza para acotar el tipo.
for (const block of message.content) {
switch (block.type) {
case "text":
console.log(block.text);
break;
case "tool_use":
console.log(block.name, block.input);
break;
}
}Una vez que te ramificas en block.type, el compilador ya sabe qué otros campos existen en block dentro de esa rama, text dentro del caso "text", name e input dentro del caso "tool_use", sin una aserción de tipo manual.
Por eso, leer respuestas de Claude en TypeScript tiende a parecer un flujo de control sobre una etiqueta, en lugar de encadenar opcionalmente a través de un blob de tipo flexible.
El mismo patrón de unión discriminada se extiende a los eventos de transmisión (content_block_start, content_block_delta, message_stop y otros), por lo que la forma del código que escribes para manejar un flujo refleja la forma del código que escribes para manejar un mensaje finalizado.
Consideraciones Avanzadas y Aplicaciones
La resiliencia es configuración, no código que escribes
Las llamadas de red fallan, expiran y ocasionalmente se limitan en velocidad, y el SDK trata las tres como configuración de primera clase en lugar de problemas que resuelves con tu propio bucle de reintentos.
Puedes establecer maxRetries y timeout globalmente en el cliente o por llamada, y el SDK aplica retroceso exponencial para fallos reintentables (errores del servidor, errores de conexión, límites de velocidad) automáticamente.
Para la cancelación, el SDK acepta una señal AbortController estándar en cualquier llamada, lo que te permite vincular la vida útil de una solicitud de Claude a algo externo, como un usuario que cierra un panel de chat, un manejador de solicitud HTTP que se cancela o un tiempo de espera que controlas tú mismo.
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
await client.messages.create(
{ model: "claude-sonnet-5", max_tokens: 256, messages: [...] },
{ signal: controller.signal },
);Dado que AbortController es un estándar web en lugar de una API de Node, este mecanismo de cancelación funciona de manera idéntica en un navegador, una función edge o un servidor Node, que es la misma historia de portabilidad que el transporte basado en fetch debajo de él.
Errores tipificados en lugar de análisis de códigos de estado
Cuando una solicitud falla, el SDK lanza una clase de error específica en lugar de un error HTTP genérico con un estado numérico adjunto.
BadRequestError, RateLimitError, AuthenticationError y APIConnectionError son cada una clases distintas, por lo que un bloque catch puede ramificarse con instanceof en lugar de inspeccionar un código de estado y esperar que la forma del cuerpo del error coincida con lo que esperas.
try {
await client.messages.create({ ... });
} catch (error) {
if (error instanceof Anthropic.RateLimitError) {
// retrocede y reintenta más tarde
} else if (error instanceof Anthropic.APIConnectionError) {
// fallo a nivel de red, no un rechazo de la API
}
}Esto es lo más importante en el código de producción que debe comportarse de manera diferente para diferentes clases de fallos: un límite de velocidad generalmente significa "esperar y reintentar", un error de autenticación generalmente significa "detener y alertar", y un error de conexión generalmente significa "el problema es la red, no Claude".
Dónde termina la responsabilidad del SDK
Un patrón de producción común es conectar client.messages.stream() a un manejador de ruta de Next.js para que el manejador reenvíe el flujo de tokens de Claude directamente al navegador como una respuesta de chat token por token.
El SDK hace que ese patrón sea natural porque su flujo ya es un iterable asíncrono y el transporte subyacente ya es compatible con fetch con entornos edge, pero el SDK en sí mismo no sabe nada sobre Next.js, la estructura de tu ruta o cómo presentas la salida parcial a un usuario.
Tampoco gestiona el historial de conversaciones de múltiples turnos (tú reenvías los mensajes anteriores tú mismo), y no ejecuta un bucle de llamadas a herramientas por ti (inspeccionas los bloques tool_use y decides si ejecutarlos y cómo).
Tratar el SDK como "transporte tipificado, no orquestación" te evita esperar un comportamiento de framework de agente de una biblioteca cliente.
| Enfoque | Fortaleza | Debilidad | Mejor Ajuste |
|---|---|---|---|
messages.create sin transmisión | Código más simple, una respuesta esperada | El usuario espera la finalización completa antes de ver nada | Trabajos por lotes, llamadas de backend a backend sin UI en vivo |
messages.stream con transmisión y for await | Los tokens aparecen a medida que se generan, flujo de control natural | Código ligeramente más complejo para ensamblar estado parcial si también necesitas el mensaje completo | Interfaces de chat, donde la latencia percibida importa |
| Transmisión con el ayudante de mensaje final incorporado | Obtén actualizaciones incrementales de la UI y el mensaje final de una sola llamada | Mantiene la respuesta completa en memoria hasta que finaliza el flujo | Interfaces de chat que también necesitan persistir el mensaje completado |
Conceptos erróneos comunes
- "La transmisión requiere un cliente diferente o un paquete diferente." No es así. El mismo cliente
Anthropicy el mismo espacio de nombresmessagesexponen tantocreate(sin transmisión) comostream(con transmisión); la transmisión es una elección de método, no una instalación separada. - "El SDK solo funciona en Node.js porque es un paquete npm." Ser distribuido en npm no está relacionado con el entorno de ejecución en el que puede ejecutarse. Debido a que su transporte se basa en
fetch, se ejecuta en cualquier entorno que implemente los estándaresfetch,ReadableStreamyAbortController, que incluyen la mayoría de los entornos edge modernos. - "Las uniones discriminadas son solo decoración de TypeScript; los datos reales son un objeto suelto." El campo
typesobre el que se acota la unión es el mismo campo que la API realmente devuelve, por lo que la tipificación no es aspiracional. Acotar enblock.typerefleja una diferencia estructural real en la respuesta, no una capa de conveniencia añadida. - "Necesitas analizar manualmente los eventos enviados por el servidor para crear una función de transmisión." El SDK ya analiza el formato de transmisión SSE por ti y expone el resultado como un iterable asíncrono de eventos tipificados; nunca tocas texto de evento sin procesar a menos que deliberadamente te sitúes por debajo de la abstracción del SDK.
- "Los reintentos duplicarán silenciosamente los efectos secundarios si una solicitud falla a mitad de camino." El SDK solo reintenta las solicitudes que considera seguras para reintentar (fallos del servidor, ciertos errores del servidor, límites de velocidad) antes de que se reciba una respuesta, no después de que tu código ya haya comenzado a consumir un flujo; no reintenta una vez que tu código ya ha comenzado a consumir un flujo.
Preguntas Frecuentes
¿Qué problema resuelve realmente @anthropic-ai/sdk?
- Convierte las llamadas HTTP sin procesar a la API de Claude en objetos TypeScript tipificados e iterables asíncronos.
- Maneja encabezados de autenticación, reintentos, tiempos de espera y clasificación de errores para que no tengas que implementarlos tú mismo.
- Te proporciona tipos comprobados por el compilador para solicitudes y respuestas en lugar de JSON de tipo flexible.
¿Por qué es importante que el SDK se base en fetch en lugar del módulo http de Node?
Debido a que fetch es un estándar web implementado por Node, navegadores y entornos edge por igual, el mismo código del SDK se ejecuta sin modificaciones en una Vercel Edge Function, un Cloudflare Worker o un Deno Deploy isolate, ninguno de los cuales tiene disponible el módulo http de Node.
¿Cómo preparo una instancia de cliente para hacer solicitudes?
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });Una instancia de cliente es suficiente para muchas solicitudes; solo contiene tu configuración.
¿En qué se diferencia la transmisión de una llamada normal a messages.create?
messages.createse resuelve una vez con la respuesta completa.messages.streamdevuelve un objeto sobre el que iteras, recibiendo eventos parciales a medida que Claude los genera.- Ambos residen en el mismo espacio de nombres
client.messages, por lo que cambiar entre ellos es una elección de método, no un cliente diferente.
¿Qué significa que el flujo sea un "iterable asíncrono"?
Significa que puedes consumirlo con un bucle for await (const event of stream) estándar, permitiendo que el cuerpo de tu propio bucle reaccione a cada evento a medida que llega, en lugar de registrar callbacks de oyente de eventos on("data") y on("end") por separado y rastrear el estado de finalización tú mismo.
¿Qué es una unión discriminada, en el contexto de este SDK?
Es un patrón de TypeScript donde cada bloque de contenido posible comparte un campo común type ("text", "tool_use", "thinking"), y verificar el valor de ese campo permite al compilador acotar qué otros campos están disponibles en ese bloque específico, sin una conversión de tipo manual.
¿Necesito escribir mi propia lógica de reintento para solicitudes inestables?
No. El SDK acepta una opción maxRetries (para todo el cliente o por llamada) y aplica automáticamente el retroceso para fallos reintentables como errores de conexión, ciertos errores del servidor y límites de velocidad.
¿Cómo cancelo una solicitud en curso?
Pasa la signal de un AbortController como una opción de solicitud y llama a controller.abort() cuando quieras cancelar; esto funciona de la misma manera en Node, navegadores y entornos edge porque AbortController es un estándar web, no una API específica de Node.
¿Cómo debo manejar los errores del SDK?
Captura la llamada y verifica instanceof contra las clases de error tipificadas del SDK (RateLimitError, BadRequestError, AuthenticationError, APIConnectionError y otras) para que tu lógica de manejo coincida con el tipo real de fallo en lugar de analizar un código de estado.
¿El SDK gestiona el historial de conversaciones por mí?
No. Eres responsable de construir el array messages en cada llamada, incluyendo los turnos anteriores que quieras que Claude vea. El SDK envía exactamente lo que le das y no persiste el estado entre llamadas.
¿El SDK ejecuta bucles de llamada a herramientas automáticamente?
No. Cuando Claude quiere usar una herramienta, la respuesta incluye un bloque de contenido tool_use; tu código es responsable de leerlo, ejecutar la lógica correspondiente y enviar el resultado en una llamada posterior.
¿Cuándo elegiría no transmitir en lugar de transmitir?
Elige no transmitir para llamadas de backend a backend, procesamiento por lotes o en cualquier lugar donde ningún humano esté viendo la salida llegar en vivo, ya que es un código más simple sin manejo de eventos parciales. Elige transmitir siempre que la latencia percibida en una interfaz de usuario importe.
¿Es la tipificación del SDK puramente para conveniencia del editor, o refleja la API real?
Refleja la API real. Los campos de unión discriminada (como type en un bloque de contenido) son los mismos campos que la API de Claude realmente devuelve en el cable, por lo que acotar en TypeScript corresponde a una distinción estructural real en la respuesta, no a una capa cosmética.
Relacionados
- Conceptos básicos del SDK de TypeScript/JavaScript - instalación del paquete y realización de tu primera llamada tipificada.
- Iterables asíncronos para transmisión en el SDK de TypeScript - un análisis más profundo del consumo de eventos transmitidos.
- Ejecución del SDK de Anthropic en entornos Edge - lo que significa la arquitectura basada en fetch en la práctica en Vercel Edge y Cloudflare Workers.
- Patrones de reintento, tiempo de espera y AbortController en el SDK de TypeScript - configuración de resiliencia en profundidad.
- Referencia de tipos del SDK de TypeScript para bloques de contenido - el catálogo completo de uniones discriminadas.
- Referencia de clases de error del SDK de TypeScript - cada clase de error tipificada y cuándo se lanza.
Versiones de la pila: 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 los modelos, las versiones del SDK y los precios cambian rápidamente; verifica los detalles actuales en platform.claude.com/docs antes de confiar en ellos.