Claude Code × Amazon Bedrock: guia prático para rodar Claude em produção na AWS
Use Claude Code e Amazon Bedrock em produção: IAM, Converse API, logs, Guardrails e controle de custos.
Chamar a API da Anthropic diretamente é o caminho mais rápido para um protótipo com Claude. Em produção na AWS, a conversa muda: gestão de API keys, limites de IAM, logs de auditoria, atribuição de custos, retenção de dados, retries e quotas. É aí que Amazon Bedrock como runtime para Claude se torna uma opção prática.
Amazon Bedrock é o serviço gerenciado de foundation models da AWS. Na prática, ele permite invocar Claude usando identidade, permissões, logs, cobrança e controles operacionais da AWS. Claude Code continua útil, mas não peça apenas um demo. Peça código revisável: IAM, chamada de modelo, Guardrails, logging, tratamento de erros e limites de custo.
A lição de Masa em projetos reais foi simples: um demo de Bedrock funciona rápido, mas a revisão de produção pergunta coisas difíceis. Qual role invoca o modelo? Quais modelos são permitidos? O que acontece em throttling? Prompts são armazenados? Como atribuir custo por equipe? Este guia transforma essas perguntas em implementação.
Este artigo segue a documentação oficial da AWS consultada em 3 de junho de 2026. Model IDs, Regions, quotas e preços do Bedrock podem mudar; confirme nas fontes oficiais antes de publicar ou implantar.
- Amazon Bedrock User Guide
- Inference using Converse API
- Request access to models
- Get information about foundation models
- How Amazon Bedrock Guardrails works
- Model invocation logging
- Troubleshooting Amazon Bedrock API error codes
- Prompt caching
- IAM principal attribution
Arquitetura de produção
Não comece pedindo ao Claude Code “adicione um chat com Bedrock”. Primeiro defina chamador, runtime, modelo, Guardrails, logs e atribuição de custos.
flowchart LR
U["User / Admin UI"] --> A["API Gateway or ALB"]
A --> R["Lambda or ECS task"]
R --> G["Input validation and budget guard"]
G --> B["Amazon Bedrock Runtime<br/>Converse / ConverseStream"]
B --> C["Claude model"]
R --> L["App logs<br/>CloudWatch Logs"]
B --> M["Model invocation logs<br/>CloudWatch Logs or S3"]
R --> K["Knowledge Bases<br/>optional RAG"]
R --> Q["Cost Explorer / CUR<br/>IAM principal attribution"]
Converse API é a interface de chat unificada do Bedrock. Guardrails avalia entradas e respostas do modelo com políticas de segurança configuradas. model invocation logging pode enviar dados de chamada para CloudWatch Logs ou S3. IAM principal attribution ajuda a acompanhar custos por usuário ou role IAM.
Casos de uso
O primeiro caso é Q&A sobre documentação interna. Runbooks, especificações e processos ficam em S3 e Knowledge Bases; trechos relevantes são recuperados e Claude responde com citações. Isso é RAG, ou retrieval augmented generation.
O segundo caso é rascunho de respostas de suporte. Claude combina pergunta do cliente, plano contratado e templates aprovados para criar uma resposta que um operador revisa. Antes da automação total, mantenha revisão humana, Guardrails, tratamento de dados pessoais e logs de auditoria.
O terceiro caso é um assistente de operações para engenharia. Ele resume logs do CloudWatch, cria checklists de deploy, prepara notas de incidente e transforma runbooks em tarefas. Claude Code ajuda porque consegue alterar API, Lambda, IAM, testes e documentação em uma mudança revisável.
O quarto caso é operação de conteúdo em sites como ClaudeCodeLab. QA de artigos, tamanho de description, links internos e revisão de blocos de código podem rodar dentro do IAM e da cobrança AWS. Se conteúdo afeta receita, combine com o guia de custos do Claude Code e o workflow de verificação.
Configuração
Você precisa de Node.js 20 ou superior, credenciais AWS CLI, uma conta com Bedrock e um modelo Anthropic disponível na Region escolhida. Dependendo da conta, modelos Anthropic podem exigir informações de primeiro uso, permissões AWS Marketplace e método de pagamento válido.
Não fixe um model ID copiado de um artigo. Liste os modelos disponíveis na sua conta e use variável de ambiente.
export AWS_REGION=us-east-1
aws bedrock list-foundation-models \
--region "$AWS_REGION" \
--query "modelSummaries[?providerName=='Anthropic'].[modelId,modelName]" \
--output table
export BEDROCK_MODEL_ID="anthropic.claude-sonnet-4-20250514-v1:0"
aws bedrock get-foundation-model \
--region "$AWS_REGION" \
--model-identifier "$BEDROCK_MODEL_ID" \
--query "modelDetails.{input:inputModalities,output:outputModalities,streaming:responseStreamingSupported}"
Crie um projeto TypeScript mínimo.
mkdir bedrock-claude-lab
cd bedrock-claude-lab
npm init -y
npm install @aws-sdk/client-bedrock @aws-sdk/client-bedrock-runtime @aws-sdk/client-bedrock-agent-runtime
npm install --save-dev typescript tsx @types/node
npx tsc --init --module NodeNext --moduleResolution NodeNext --target ES2022
mkdir -p src/lambda
Adicione scripts ao package.json.
{
"type": "module",
"scripts": {
"chat": "tsx src/chat.ts",
"stream": "tsx src/stream.ts",
"typecheck": "tsc --noEmit"
}
}
IAM mínimo
Mesmo com Converse API, IAM precisa permitir invocação de modelo. Chamadas sem streaming usam bedrock:InvokeModel; streaming usa bedrock:InvokeModelWithResponseStream. Separe permissões de logs da aplicação da configuração de model invocation logging do Bedrock.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListBedrockModelsForStartupCheck",
"Effect": "Allow",
"Action": ["bedrock:ListFoundationModels", "bedrock:GetFoundationModel"],
"Resource": "*"
},
{
"Sid": "InvokeOnlyApprovedClaudeModels",
"Effect": "Allow",
"Action": ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream"],
"Resource": [
"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-*",
"arn:aws:bedrock:us-west-2::foundation-model/anthropic.claude-*",
"arn:aws:bedrock:us-east-1:123456789012:inference-profile/*"
]
},
{
"Sid": "ApplyApprovedGuardrail",
"Effect": "Allow",
"Action": ["bedrock:ApplyGuardrail"],
"Resource": "arn:aws:bedrock:us-east-1:123456789012:guardrail/your-guardrail-id"
}
]
}
Troque conta, Regions, Guardrail e escopo de modelos. Se usar cross-Region inference, inclua o inference profile e os ARNs dos modelos de destino. Para revisão de privilégio mínimo, veja o guia AWS IAM com Claude Code.
Invocar Claude
O detalhe de produção é requestMetadata. A AWS documenta esse campo como útil para filtrar logs de invocação, então inclua request ID, feature e categoria do usuário.
// src/bedrock-client.ts
import { randomUUID } from "node:crypto";
import {
BedrockRuntimeClient,
ConverseCommand,
ConverseStreamCommand,
type ConverseCommandInput,
} from "@aws-sdk/client-bedrock-runtime";
export const AWS_REGION = process.env.AWS_REGION ?? "us-east-1";
export const BEDROCK_MODEL_ID =
process.env.BEDROCK_MODEL_ID ?? "anthropic.claude-sonnet-4-20250514-v1:0";
export const bedrock = new BedrockRuntimeClient({
region: AWS_REGION,
maxAttempts: Number(process.env.BEDROCK_MAX_ATTEMPTS ?? "3"),
});
type AskClaudeInput = {
prompt: string;
system?: string;
maxTokens?: number;
temperature?: number;
userId?: string;
feature?: string;
};
function optionalGuardrail(): ConverseCommandInput["guardrailConfig"] | undefined {
const guardrailIdentifier = process.env.BEDROCK_GUARDRAIL_ID;
if (!guardrailIdentifier) return undefined;
return {
guardrailIdentifier,
guardrailVersion: process.env.BEDROCK_GUARDRAIL_VERSION ?? "DRAFT",
trace: "enabled",
};
}
export async function askClaude(input: AskClaudeInput) {
const requestId = randomUUID();
const startedAt = Date.now();
const response = await bedrock.send(
new ConverseCommand({
modelId: BEDROCK_MODEL_ID,
system: input.system ? [{ text: input.system }] : undefined,
messages: [{ role: "user", content: [{ text: input.prompt }] }],
inferenceConfig: {
maxTokens: input.maxTokens ?? 800,
temperature: input.temperature ?? 0.2,
},
guardrailConfig: optionalGuardrail(),
requestMetadata: {
requestId,
feature: input.feature ?? "local-cli",
userId: input.userId ?? "anonymous",
},
})
);
const text =
response.output?.message?.content
?.map((block: { text?: string }) => block.text ?? "")
.join("") ?? "";
console.log(
JSON.stringify({
level: "info",
event: "bedrock_converse",
requestId,
modelId: BEDROCK_MODEL_ID,
latencyMs: Date.now() - startedAt,
stopReason: response.stopReason,
usage: response.usage,
metrics: response.metrics,
})
);
return { text, usage: response.usage, stopReason: response.stopReason, requestId };
}
export async function streamClaude(prompt: string) {
const response = await bedrock.send(
new ConverseStreamCommand({
modelId: BEDROCK_MODEL_ID,
messages: [{ role: "user", content: [{ text: prompt }] }],
inferenceConfig: { maxTokens: 1200, temperature: 0.2 },
guardrailConfig: optionalGuardrail(),
requestMetadata: { feature: "stream-cli", requestId: randomUUID() },
})
);
if (!response.stream) throw new Error("Bedrock did not return a stream.");
for await (const event of response.stream) {
const text = event.contentBlockDelta?.delta?.text;
if (text) process.stdout.write(text);
if (event.metadata?.usage) {
process.stderr.write(`\nusage=${JSON.stringify(event.metadata.usage)}\n`);
}
}
}
// src/chat.ts
import { askClaude } from "./bedrock-client.js";
const prompt = process.argv.slice(2).join(" ").trim();
if (!prompt) {
console.error('Usage: npm run chat -- "Summarize Amazon Bedrock in three bullets"');
process.exit(1);
}
const result = await askClaude({
prompt,
system: "You are a concise AWS assistant. If you are unsure, say what to verify.",
maxTokens: 600,
feature: "developer-chat",
});
console.log(result.text);
// src/stream.ts
import { streamClaude } from "./bedrock-client.js";
const prompt = process.argv.slice(2).join(" ").trim();
if (!prompt) {
console.error('Usage: npm run stream -- "Write a deployment checklist"');
process.exit(1);
}
await streamClaude(prompt);
Execute:
export AWS_REGION=us-east-1
export BEDROCK_MODEL_ID="anthropic.claude-sonnet-4-20250514-v1:0"
npm run chat -- "Explique Amazon Bedrock em três linhas"
npm run stream -- "Crie uma checklist de produção para Bedrock"
npm run typecheck
Padrão Lambda
No Lambda, inicialize o cliente fora do handler, valide entrada e limite maxTokens no servidor.
// src/lambda/assistant-handler.ts
import { askClaude } from "../bedrock-client.js";
type ApiEvent = {
body?: string | null;
requestContext?: { requestId?: string };
};
const headers = { "content-type": "application/json; charset=utf-8" };
export const handler = async (event: ApiEvent) => {
try {
const body = JSON.parse(event.body ?? "{}") as {
prompt?: string;
maxTokens?: number;
userId?: string;
};
if (!body.prompt || body.prompt.length > 8000) {
return {
statusCode: 400,
headers,
body: JSON.stringify({ error: "prompt is required and must be <= 8000 chars" }),
};
}
const result = await askClaude({
prompt: body.prompt,
maxTokens: Math.min(body.maxTokens ?? 800, 1200),
userId: body.userId ?? "anonymous",
feature: "support-assistant",
});
return {
statusCode: 200,
headers,
body: JSON.stringify({
text: result.text,
usage: result.usage,
stopReason: result.stopReason,
requestId: result.requestId,
}),
};
} catch (error) {
const name =
typeof error === "object" && error && "name" in error ? String(error.name) : "UnknownError";
const retryable = ["ThrottlingException", "ServiceUnavailableException", "InternalServerException"].includes(name);
console.error(JSON.stringify({ level: "error", event: "assistant_failed", name, retryable }));
return {
statusCode: retryable ? 503 : 500,
headers,
body: JSON.stringify({ error: retryable ? "Please retry later" : "Generation failed" }),
};
}
};
Não faça retry cego de ValidationException; normalmente é entrada ou parâmetro inválido. ThrottlingException e ServiceUnavailableException aceitam backoff exponencial com jitter. Para serverless completo, leia Claude Code × AWS Lambda.
RAG com Knowledge Bases
Para chat com documentos internos, Bedrock Knowledge Bases é um bom começo antes de criar um vector store próprio. Ele retorna respostas com citações, facilitando validação. Atenção: Guardrails se aplica à entrada e à resposta gerada, não às referências recuperadas. Restrinja documentos sensíveis com S3, KMS, IAM e classificação de dados.
// src/rag.ts
import {
BedrockAgentRuntimeClient,
RetrieveAndGenerateCommand,
} from "@aws-sdk/client-bedrock-agent-runtime";
const agentRuntime = new BedrockAgentRuntimeClient({
region: process.env.AWS_REGION ?? "us-east-1",
});
export async function askKnowledgeBase(question: string) {
const knowledgeBaseId = process.env.BEDROCK_KNOWLEDGE_BASE_ID;
const modelArn = process.env.BEDROCK_GENERATION_MODEL_ARN;
if (!knowledgeBaseId || !modelArn) {
throw new Error("Set BEDROCK_KNOWLEDGE_BASE_ID and BEDROCK_GENERATION_MODEL_ARN");
}
const response = await agentRuntime.send(
new RetrieveAndGenerateCommand({
input: { text: question },
retrieveAndGenerateConfiguration: {
type: "KNOWLEDGE_BASE",
knowledgeBaseConfiguration: {
knowledgeBaseId,
modelArn,
retrievalConfiguration: {
vectorSearchConfiguration: { numberOfResults: 5 },
},
},
},
})
);
const sources =
response.citations
?.flatMap((citation) => citation.retrievedReferences ?? [])
.map((reference) => reference.location?.s3Location?.uri)
.filter(Boolean) ?? [];
return { answer: response.output?.text ?? "", sources };
}
Logs e custos
Use duas camadas de logs. Logs da aplicação devem incluir requestId, feature, tipo de usuário, modelo, usage, latência e stop reason. Evite guardar prompts brutos se a política de privacidade e retenção não permitir.
O model invocation logging do Bedrock pode escrever no CloudWatch Logs ou S3. Ele ajuda em auditoria, mas também pode armazenar entradas e saídas sensíveis. Defina retenção, criptografia, lifecycle de S3 e acesso antes de ativar amplamente.
Para custos, limite maxTokens na API, escolha modelo por complexidade, registre usage e use IAM principal attribution para agrupar gastos por role. Prompt caching ajuda com contextos longos e repetidos, não com prompts curtos ou totalmente dinâmicos.
Prompt para Claude Code
claude -p "
Adicione invocação de Claude via Amazon Bedrock a este repositório.
Requisitos:
- Usar AWS SDK v3 Converse API
- Ler o modelo de BEDROCK_MODEL_ID
- Usar us-east-1 se AWS_REGION não existir
- Limitar maxTokens a 1200 no servidor
- Adicionar requestMetadata com requestId, feature e userId
- Adicionar guardrailConfig somente se BEDROCK_GUARDRAIL_ID existir
- Logar usage, latencyMs e stopReason em JSON
- Não fazer retry de ValidationException
- Tratar ThrottlingException e ServiceUnavailableException como retryable
- Documentar política IAM de menor privilégio no README
- Mockar o cliente Bedrock nos testes; não chamar a API real
Mostre o plano antes de editar e reporte typecheck e testes no final.
"
Armadilhas comuns
A primeira é não verificar acesso ao modelo. Teste list-foundation-models e uma chamada Converse pequena.
A segunda é congelar um model ID de um artigo. Use configuração e validação no startup.
A terceira é tratar Guardrails como garantia de verdade. Ele ajuda em segurança, mas não substitui revisão humana, validação de domínio ou autorização.
A quarta é logar demais. Prompts completos ajudam no debug, mas podem vazar dados pessoais ou internos.
A quinta é repetir erros errados. Validation exige correção; throttling e falhas temporárias podem ter retry.
A sexta é controlar custos só no frontend. Limites reais pertencem à API.
Caminho de monetização
O valor de Bedrock não está no snippet do SDK, mas em sair do demo para produção: IAM, logs, custos, Guardrails, reviews e adoção em equipe. Para templates reutilizáveis, comece pelos produtos ClaudeCodeLab. Para rollout em um repositório real com CLAUDE.md, revisão IAM, verification receipts e CI gates, use treinamento e consultoria Claude Code.
Leituras relacionadas: Claude Code AWS Lambda, Claude Code AWS IAM, custos de Claude Code e workflow de verificação.
Resultado prático
Ao testar este padrão, o maior ganho não veio de mais abstrações, mas de um prompt mais claro para Claude Code: model ID por variável de ambiente, log de usage, não repetir ValidationException, Guardrails opcional por ambiente e política IAM no README. O diff ficou menor e a revisão mais objetiva. Sucesso com Bedrock depende menos de decorar o SDK e mais de declarar as restrições de produção antes de gerar código.
Artigos relacionados
Claude Code e AWS API Gateway: HTTP API com SAM, CORS, logs, autenticação e limites
Implemente AWS API Gateway com Claude Code, SAM, CORS, logs, auth e throttling com exemplos práticos.
Claude Code com AWS CloudFormation e CDK: guia prático de revisão IaC
Revise AWS CDK e CloudFormation com Claude Code: IAM mínimo, diffs, drift, rollback e guardrails práticos.
Claude Code e AWS IAM: guia prático de políticas de menor privilégio
Projete e valide políticas AWS IAM de menor privilégio com Claude Code, Access Analyzer e CDK.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.