Use Cases

Claude Code × Amazon Bedrock Guía Completa | Ejecutar Claude en Producción con AWS

Guía completa para usar Amazon Bedrock con Claude Code. Desde autenticación IAM, streaming, integración con Lambda, implementación RAG hasta optimización de costos, basada en la experiencia real de producción de Masa.

«Quiero usar la API de Claude en producción, pero me preocupa la gestión de claves API» o «Nuestra política de seguridad interna no permite que los datos salgan de AWS» — para estos problemas, Amazon Bedrock es la respuesta perfecta.

Cuando integraba IA en un servidor API sobre ECS para un proyecto laboral, inicialmente utilizaba la API de Anthropic directamente. Sin embargo, una auditoría de seguridad señaló la «gestión de claves API para servicios externos» como un problema. Después de migrar a Bedrock, la autenticación se gestiona completamente con roles IAM y me liberé de la gestión de claves API. Este artículo explica todo, desde la implementación de Bedrock con Claude Code hasta la operación en producción.


¿Qué es Amazon Bedrock?

Amazon Bedrock es un servicio de modelos de IA gestionado de AWS. Permite llamar a múltiples modelos —Claude (Anthropic), Llama (Meta), Titan (Amazon)— a través de una API unificada.

¿Por qué usar Bedrock?

AspectoAPI de AnthropicAmazon Bedrock
AutenticaciónClave APIRol IAM de AWS
FacturaciónDirectamente a AnthropicIntegrada en la facturación de AWS
Soporte VPCNo disponibleTotalmente privado con PrivateLink
Retención de datosPolítica de AnthropicPolítica de AWS
Cumplimiento normativoSOC2, etc.SOC2 / ISO27001 / HIPAA, etc.

La API de Anthropic es conveniente para proyectos personales, pero para casos de uso empresariales, financieros y sanitarios, Bedrock se está convirtiendo cada vez más en la única opción.


Paso 1: Configuración inicial

Solicitar acceso al modelo

Primero, solicite acceso a los modelos de Claude en la consola de AWS.

# Obtener la lista de modelos disponibles
aws bedrock list-foundation-models \
  --by-provider anthropic \
  --region us-east-1 \
  --query 'modelSummaries[].{id:modelId, name:modelName}'

# Ejemplo de salida
[
  {"id": "anthropic.claude-opus-4-5",     "name": "Claude Opus 4.5"},
  {"id": "anthropic.claude-sonnet-4-6",   "name": "Claude Sonnet 4.6"},
  {"id": "anthropic.claude-haiku-4-5-20251001", "name": "Claude Haiku 4.5"}
]

Importante: Las regiones principales disponibles son us-east-1 (Virginia) y us-west-2 (Oregón). La región de Tokio puede usarse a través de Cross-region inference.

Instalación del SDK

npm install @anthropic-ai/sdk @aws-sdk/client-bedrock-runtime

Paso 2: Implementación básica

Usar el soporte Bedrock integrado del SDK de Anthropic (Recomendado)

El SDK oficial de Anthropic tiene soporte para Bedrock incorporado. Como la sintaxis es casi idéntica a la API regular de Anthropic, el costo de migración desde código existente es mínimo.

// src/lib/bedrock-client.ts
import Anthropic from "@anthropic-ai/sdk";

// No se necesitan credenciales cuando se usa el rol IAM (ej. Lambda/ECS)
const bedrock = new Anthropic.AnthropicBedrock({
  awsRegion: process.env.AWS_REGION ?? "us-east-1",
  // Durante el desarrollo local, se usa automáticamente el perfil de AWS CLI
});

export async function generateText(
  prompt: string,
  options: { model?: string; maxTokens?: number } = {}
): Promise<string> {
  const { model = "anthropic.claude-sonnet-4-6", maxTokens = 1024 } = options;

  const response = await bedrock.messages.create({
    model,
    max_tokens: maxTokens,
    messages: [{ role: "user", content: prompt }],
  });

  return response.content[0].type === "text" ? response.content[0].text : "";
}

Los IDs de modelo de Bedrock difieren de la API de Anthropic:

API de Anthropic: claude-sonnet-4-6
Bedrock:          anthropic.claude-sonnet-4-6  (se agrega prefijo)

Soporte de streaming

El streaming es esencial para respuestas largas.

// src/lib/bedrock-stream.ts
export async function* streamText(
  prompt: string,
  model = "anthropic.claude-sonnet-4-6"
): AsyncGenerator<string> {
  const stream = await bedrock.messages.stream({
    model,
    max_tokens: 4096,
    messages: [{ role: "user", content: prompt }],
  });

  for await (const chunk of stream) {
    if (
      chunk.type === "content_block_delta" &&
      chunk.delta.type === "text_delta"
    ) {
      yield chunk.delta.text;
    }
  }
}

// Ejemplo de uso (Next.js App Router)
export async function POST(req: Request) {
  const { prompt } = await req.json();
  const encoder = new TextEncoder();

  const stream = new ReadableStream({
    async start(controller) {
      for await (const text of streamText(prompt)) {
        controller.enqueue(encoder.encode(text));
      }
      controller.close();
    },
  });

  return new Response(stream, {
    headers: { "Content-Type": "text/event-stream" },
  });
}

Paso 3: Patrón Lambda + Bedrock

La arquitectura más común para proporcionar funciones de IA sin servidor.

claude -p "
Implementa la siguiente función Lambda en src/lambda/ai-handler.ts:
- Recibir prompt y maxTokens del evento
- Llamar a Bedrock (claude-sonnet-4-6) y devolver el resultado
- Manejar errores: ThrottlingException (reintentar) y ValidationException (400)
- Registrar el tiempo de ejecución
- Inicializar el cliente fuera del handler (optimización de cold start)
"
// src/lambda/ai-handler.ts
import { Handler, APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
import Anthropic from "@anthropic-ai/sdk";

// Inicialización en el ámbito del módulo (se cachea cuando el contenedor se reutiliza)
const bedrock = new Anthropic.AnthropicBedrock({
  awsRegion: process.env.AWS_REGION,
});

export const handler: Handler<APIGatewayProxyEvent, APIGatewayProxyResult> = async (event) => {
  const startTime = Date.now();

  try {
    const { prompt, maxTokens = 512 } = JSON.parse(event.body ?? "{}");

    if (!prompt) {
      return { statusCode: 400, body: JSON.stringify({ error: "prompt is required" }) };
    }

    const response = await bedrock.messages.create({
      model: "anthropic.claude-sonnet-4-6",
      max_tokens: maxTokens,
      messages: [{ role: "user", content: prompt }],
    });

    const duration = Date.now() - startTime;
    console.log(JSON.stringify({
      level: "INFO",
      duration_ms: duration,
      input_tokens: response.usage.input_tokens,
      output_tokens: response.usage.output_tokens,
    }));

    return {
      statusCode: 200,
      body: JSON.stringify({
        text: response.content[0].type === "text" ? response.content[0].text : "",
        usage: response.usage,
      }),
    };
  } catch (error: any) {
    if (error.name === "ThrottlingException") {
      console.warn("Rate limited by Bedrock, client should retry");
      return { statusCode: 429, body: JSON.stringify({ error: "Rate limited, please retry" }) };
    }
    console.error("Bedrock error:", error);
    return { statusCode: 500, body: JSON.stringify({ error: "AI generation failed" }) };
  }
};

Política IAM de Lambda

// Configuración IAM con CDK
import * as iam from "aws-cdk-lib/aws-iam";

lambdaFunction.addToRolePolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW,
  actions: [
    "bedrock:InvokeModel",
    "bedrock:InvokeModelWithResponseStream",
  ],
  resources: [
    `arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-sonnet-4-6`,
    `arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-haiku-4-5-20251001`,
  ],
}));

Paso 4: Implementación de RAG (Retrieval-Augmented Generation)

Un patrón donde Claude lee documentos internos o información de productos para responder preguntas.

claude -p "
Implementa un sistema RAG usando Bedrock Knowledge Base.

Arquitectura:
- Almacenar documentos en S3
- Indexación vectorial con Bedrock Knowledge Base
- Recuperar documentos basándose en las preguntas del usuario
- Generar respuestas con Claude Sonnet

Implementar con TypeScript + AWS SDK v3.
Obtener el Knowledge Base ID de la variable de entorno KNOWLEDGE_BASE_ID.
"
// src/lib/rag.ts
import {
  BedrockAgentRuntimeClient,
  RetrieveAndGenerateCommand,
} from "@aws-sdk/client-bedrock-agent-runtime";

const agentClient = new BedrockAgentRuntimeClient({ region: "us-east-1" });

export async function ragQuery(question: string): Promise<{
  answer: string;
  citations: string[];
}> {
  const response = await agentClient.send(
    new RetrieveAndGenerateCommand({
      input: { text: question },
      retrieveAndGenerateConfiguration: {
        type: "KNOWLEDGE_BASE",
        knowledgeBaseConfiguration: {
          knowledgeBaseId: process.env.KNOWLEDGE_BASE_ID!,
          modelArn: `arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-sonnet-4-6`,
          retrievalConfiguration: {
            vectorSearchConfiguration: { numberOfResults: 5 },
          },
        },
      },
    })
  );

  const answer = response.output?.text ?? "";
  const citations = (response.citations ?? [])
    .flatMap((c) => c.retrievedReferences ?? [])
    .map((r) => r.location?.s3Location?.uri ?? "")
    .filter(Boolean);

  return { answer, citations };
}

Paso 5: Optimización de costos

// Utilidad de selección de modelo
type TaskType = "classify" | "extract" | "summarize" | "generate" | "complex";

const MODEL_MAP: Record<TaskType, string> = {
  classify: "anthropic.claude-haiku-4-5-20251001",  // $0.80/1M tokens de entrada
  extract:  "anthropic.claude-haiku-4-5-20251001",
  summarize: "anthropic.claude-sonnet-4-6",          // $3.00/1M tokens de entrada
  generate: "anthropic.claude-sonnet-4-6",
  complex:  "anthropic.claude-opus-4-5",             // $15.00/1M tokens de entrada
};

export function selectModel(task: TaskType): string {
  return MODEL_MAP[task];
}

Reducir costos de entrada con caché de prompts

// El caché de prompts también está disponible en Bedrock
const response = await bedrock.messages.create({
  model: "anthropic.claude-sonnet-4-6",
  max_tokens: 1024,
  system: [
    {
      type: "text",
      text: longSystemPrompt,
      cache_control: { type: "ephemeral" },  // Caché por 5 minutos
    },
  ],
  messages: [{ role: "user", content: userQuery }],
});

5 errores comunes

1. La región no es compatible

Claude en Bedrock no está disponible en todas las regiones. A partir de 2026, us-east-1 y us-west-2 son las regiones principales. Para usarlo desde Tokio, habilite Cross-region inference.

// Usar el ARN de modelo para Cross-region inference
const crossRegionModelArn = 
  "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-sonnet-4-6";

2. Olvidar solicitar acceso al modelo

En Bedrock, debe solicitar «Model access» para cada modelo que desee usar. Llamar a un modelo sin solicitud de acceso resulta en un AccessDeniedException. Solicite siempre el acceso antes de empezar a programar con Claude Code.

3. Timeout de Lambda demasiado corto

Las respuestas de Claude pueden tardar entre 10 y 30 segundos. El valor predeterminado de Lambda de 3 segundos definitivamente causará un timeout. Configúrelo en al menos 30 segundos, y de 60 a 300 segundos para generaciones más largas.

4. Confundir IDs de modelo de Bedrock con IDs de la API de Anthropic

❌ Usar el ID de la API de Anthropic directamente: "claude-sonnet-4-6"
✅ ID de Bedrock: "anthropic.claude-sonnet-4-6"

5. No tener en cuenta la latencia de Cross-region inference

Llamar a modelos en us-east-1 desde Tokio agrega una latencia de red de ida y vuelta de aproximadamente 100–200 ms. Para aplicaciones sensibles a la latencia, use streaming para reducir el retraso percibido.


Resumen

TareaContribución de Claude Code
Implementación básicaGenera cliente AnthropicBedrock y funciones
Integración con LambdaGenera handler y política IAM juntos
Implementación RAGGenera automáticamente código de integración con Knowledge Base
Optimización de costosDiseña lógica de selección de modelo según tipo de tarea
Resolución de problemasIdentifica causa y sugiere solución desde registros de errores

Desarrollar con Claude Code, operar en producción con Bedrock — esta combinación satisface todos los requisitos de seguridad, costos y escalabilidad. Empiece con la prueba gratuita de Bedrock y, cuando esté listo para producción, solo necesita configurar el rol IAM.

Artículos relacionados

Referencias

#claude-code #aws #bedrock #anthropic #typescript #generative-ai

Lleva tu flujo con Claude Code al siguiente nivel

50 plantillas de prompts probadas en producción, listas para copiar y pegar en Claude Code.

Gratis

PDF gratuito: Hoja de trucos de Claude Code en 5 minutos

Solo deja tu correo y te enviaremos al instante la hoja de trucos en una página A4.

Cuidamos tus datos personales y nunca enviamos spam.

Masa

Sobre el autor

Masa

Ingeniero apasionado por Claude Code. Dirige claudecode-lab.com, un medio tecnológico en 10 idiomas con más de 2.000 páginas.