Anthropic Text Generation — Configuración
Módulo de generación de texto listo para integrar en Next.js App Router usando la API de Anthropic.
Qué incluye
- Generación de texto (sin streaming)
- Texto con streaming
- Prompts de sistema
- Temperatura / máximo de tokens / modelo configurables
- Salida estructurada (JSON, mediante tool use forzado)
- Manejo de errores normalizado (incluyendo rate limiting), listo para la UI
No incluido a propósito: agentes, generación de imágenes, historial de chat/conversaciones, tool calling de uso general. Para eso están los módulos separados.
Dependencias
Este módulo usa:
No se instala automáticamente: agregalo al package.json de tu proyecto como lo hacés normalmente.
Mapa de archivos
| Archivo | Se ejecuta en | Para qué sirve |
|---|---|---|
types.ts | ambos | Tipos compartidos, valores por defecto y formatos de error |
service.ts | servidor | Llamadas internas al SDK de Anthropic + normalización de errores. No lo importes directamente. |
actions.ts | servidor | Server Actions: importalas en server components |
client.ts | cliente | Streaming del lado del cliente: importalo en client components |
stream/handler.ts | servidor | Handler interno de las requests de streaming |
stream/route.ts | servidor | Copialo a app/api/anthropic/stream/route.ts |
.env.local | — | Variables de entorno |
Configuración
- Copiá todos los archivos a tu proyecto (ubicación sugerida:
lib/ai/anthropic/text-generation/). - Copiá
stream/route.tsaapp/api/anthropic/stream/route.ts(importa./handler, que tenés que copiar al lado, por ejemplo aapp/api/anthropic/stream/handler.ts, actualizando la ruta del import enroute.tsen consecuencia; o dejáhandler.tsen tu carpeta lib e importalo desde ahí). - Agregá tu clave en
.env.local:ANTHROPIC_API_KEY=sk-ant-... - Asegurate de que
@anthropic-ai/sdkesté en tus dependencias.
Uso
Generar texto (server component / server action)
import { generateText } from "@/lib/ai/anthropic/text-generation/actions";
const result = await generateText("Explain quantum computing simply", {
systemPrompt: "You are a friendly physics teacher.",
temperature: 0.7,
});
if (result.error) {
// result.error.code, result.error.message (and result.error.retryAfter if rate_limited)
} else {
console.log(result.data.text);
}
Salida estructurada (server component / server action)
import { generateStructuredOutput } from "@/lib/ai/anthropic/text-generation/actions";
const result = await generateStructuredOutput("John is 30 years old", {
schemaName: "extract_person",
schema: {
type: "object",
properties: {
name: { type: "string" },
age: { type: "number" },
},
required: ["name", "age"],
},
});
if (!result.error) {
console.log(result.data.data); // { name: "John", age: 30 }
}
Texto con streaming (client component)
"use client";
import { useState } from "react";
import { streamText } from "@/lib/ai/anthropic/text-generation/client";
export function ChatDemo() {
const [output, setOutput] = useState("");
const [isStreaming, setIsStreaming] = useState(false);
const [error, setError] = useState<string | null>(null);
function handleGenerate() {
setOutput("");
setError(null);
setIsStreaming(true);
streamText("Write a haiku about the ocean", undefined, {
onChunk: (text) => setOutput((prev) => prev + text),
onError: (err) => setError(err.message),
onDone: () => setIsStreaming(false),
});
}
return (
<div>
<button onClick={handleGenerate} disabled={isStreaming}>
Generate
</button>
<p>{output}</p>
{error && <p role="alert">{error}</p>}
</div>
);
}
Manejo de errores
Todas las funciones (generateText, generateStructuredOutput, streamText) devuelven o entregan un error normalizado en lugar de lanzar excepciones crudas del SDK:
type AIErrorCode =
| "invalid_request"
| "authentication_error"
| "rate_limited"
| "overloaded"
| "network_error"
| "unknown_error";
interface AIError {
code: AIErrorCode;
message: string;
retryAfter?: number; // present when code === "rate_limited"
}
El rate limiting (code: "rate_limited") incluye retryAfter (en segundos) cuando la API lo provee, así podés deshabilitar el botón de envío de la UI o mostrar una cuenta regresiva hasta que sea seguro reintentar.