Anthropic Chat — Configuración
Módulo de chat listo para integrar en Next.js App Router usando la API de Anthropic. Es independiente del módulo Text Generation: usalo cuando necesites conversaciones con historial, no generaciones de una sola respuesta.
Qué incluye
- Chat completion (sin streaming)
- Chat con streaming
- Historial de conversaciones y mensajes
- Historial de chat persistente (mediante un store intercambiable)
- Múltiples conversaciones
- Gestión de conversaciones (crear, renombrar, eliminar, listar)
- Gestión de contexto (recorte automático de mensajes antiguos usando el endpoint real de conteo de tokens)
No incluido a propósito: speech-to-text y text-to-speech, ya que la API de Anthropic no los ofrece de forma nativa. Si necesitás voz, integrá un proveedor aparte (por ejemplo Whisper o ElevenLabs) y pasale el texto resultante a sendMessage / streamMessage.
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 |
store.ts | servidor | Contrato de persistencia (ChatStore) + implementación en memoria por defecto |
service.ts | servidor | Llamadas internas al SDK de Anthropic, gestión de contexto y normalización de errores |
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/chat/stream/route.ts |
.env.local | — | Variables de entorno |
Configuración
- Copiá todos los archivos a tu proyecto (ubicación sugerida:
lib/ai/anthropic/chat/). - Copiá
stream/route.tsaapp/api/anthropic/chat/stream/route.ts, junto con una copia destream/handler.ts(o dejáhandler.tsen tu carpeta lib e importalo desde ahí, solo actualizá el import relativo enroute.ts). - Agregá tu clave en
.env.local:ANTHROPIC_API_KEY=sk-ant-... - Asegurate de que
@anthropic-ai/sdkesté en tus dependencias. - (Opcional) El módulo funciona de entrada con un store en memoria, que se pierde al reiniciar y no se comparte entre instancias del servidor. Para producción, implementá
ChatStore(definido enstore.ts) contra tu propia base de datos y registralo una sola vez al iniciar:import { setChatStore } from "@/lib/ai/anthropic/chat/store"; import { PostgresChatStore } from "./postgres-chat-store"; setChatStore(new PostgresChatStore(db));
Uso
Crear una conversación y enviar un mensaje (server component / server action)
import { createConversation, sendMessage } from "@/lib/ai/anthropic/chat/actions";
const conversation = await createConversation("Trip planning");
const result = await sendMessage(conversation.id, "Suggest a 5-day itinerary for Japan", {
systemPrompt: "You are a helpful travel assistant.",
});
if (result.error) {
// result.error.code, result.error.message
} else {
console.log(result.data.message.content);
}
Listar y gestionar conversaciones (server component / server action)
import {
listConversations,
getConversation,
renameConversation,
deleteConversation,
} from "@/lib/ai/anthropic/chat/actions";
const conversations = await listConversations();
const full = await getConversation(conversations[0].id); // includes messages
await renameConversation(conversations[0].id, "Japan trip");
await deleteConversation(conversations[0].id);
Chat con streaming (client component)
"use client";
import { useState } from "react";
import { streamMessage } from "@/lib/ai/anthropic/chat/client";
export function ChatWindow({ conversationId }: { conversationId: string }) {
const [reply, setReply] = useState("");
const [isStreaming, setIsStreaming] = useState(false);
const [error, setError] = useState<string | null>(null);
function handleSend(content: string) {
setReply("");
setError(null);
setIsStreaming(true);
streamMessage(conversationId, content, undefined, {
onChunk: (text) => setReply((prev) => prev + text),
onError: (err) => setError(err.message),
onDone: () => setIsStreaming(false),
});
}
return (
<div>
<p>{reply}</p>
{error && <p role="alert">{error}</p>}
</div>
);
}
Manejo de errores
Usa el mismo formato normalizado que el módulo Text Generation, más "not_found" para operaciones sobre una conversación que no existe:
type AIErrorCode =
| "invalid_request"
| "authentication_error"
| "rate_limited"
| "overloaded"
| "network_error"
| "not_found"
| "unknown_error";
interface AIError {
code: AIErrorCode;
message: string;
retryAfter?: number; // present when code === "rate_limited"
}
Gestión de contexto
Cada request verifica la cantidad de tokens de la conversación con anthropic.messages.countTokens() y recorta los mensajes más antiguos hasta que entre dentro de DEFAULT_MAX_CONTEXT_TOKENS (150.000, se puede sobrescribir en cada llamada con options.maxContextTokens). El recorte solo afecta lo que se envía al modelo: el historial completo se mantiene persistido en tu store.