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.
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.
Artigos relacionados
Workflow Obsidian para CLAUDE.md com Claude Code
Transforme notas de trabalho do Obsidian em notas operacionais CLAUDE.md para preservar contexto.
Claude Code Revenue CTA Routing: artigos para PDF, Gumroad e consultoria
Um fluxo com Claude Code para levar leitores ao PDF grátis, Gumroad ou consultoria conforme intenção.
Regras de handoff para equipes com Claude Code: evidências, permissões, rollback e receita
Formato prático para entregar trabalho do Claude Code com prova, permissões, rollback, PDF grátis, Gumroad e consultoria.