Claude Code × Amazon Bedrock : guide pratique pour exécuter Claude en production sur AWS
Mettre Claude en production avec Claude Code et Amazon Bedrock : IAM, Converse API, logs, Guardrails et coûts.
Appeler directement l’API Anthropic est souvent le chemin le plus rapide pour tester Claude. En production sur AWS, les questions changent : gestion des clés, limites IAM, journaux d’audit, attribution des coûts, rétention des données, retries et quotas. C’est là que Amazon Bedrock comme runtime Claude devient intéressant.
Amazon Bedrock est le service managé de modèles de fondation d’AWS. Concrètement, il permet d’invoquer Claude avec l’identité, les permissions, les logs, la facturation et les contrôles opérationnels AWS. Claude Code reste utile, mais il faut lui demander du code exploitable et révisable : IAM, invocation du modèle, Guardrails, logging, erreurs et garde-fous de coût.
Dans un projet réel, Masa a constaté qu’un démo Bedrock peut marcher très vite, mais qu’une revue production pose d’autres questions. Quel rôle appelle le modèle ? Quels modèles sont autorisés ? Que faire en cas de throttling ? Les prompts sont-ils stockés ? Comment attribuer le coût par équipe ? Ce guide transforme ces questions en code et en prompt Claude Code.
Cet article suit la documentation officielle AWS consultée le 3 juin 2026. Les IDs de modèles, Regions, quotas et prix Bedrock peuvent changer ; vérifie toujours les sources officielles avant de déployer.
- 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
Architecture de production
Ne commence pas par demander à Claude Code « ajoute un chat Bedrock ». Définis d’abord l’appelant, le runtime, le modèle, les Guardrails, les logs et l’attribution des coûts.
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 est l’interface conversationnelle unifiée de Bedrock. Guardrails évalue les entrées et sorties selon des politiques de sécurité. model invocation logging peut envoyer les données d’invocation vers CloudWatch Logs ou S3. IAM principal attribution aide à suivre les coûts Bedrock par utilisateur ou rôle IAM.
Cas d’usage
Premier cas : le chat sur documentation interne. Tu places runbooks, spécifications et procédures dans S3 et Knowledge Bases, tu récupères les passages pertinents, puis Claude répond avec citations. C’est du RAG, retrieval augmented generation : le modèle répond avec du contexte récupéré dans tes données.
Deuxième cas : la rédaction d’ébauches de support. Claude combine une question client, le plan concerné et des modèles de réponse validés. Tant que le processus n’est pas mature, garde une validation humaine, des Guardrails, un traitement des données personnelles et des logs d’audit.
Troisième cas : l’assistant d’exploitation pour l’équipe d’ingénierie. Il peut résumer des logs CloudWatch, préparer une checklist de déploiement, rédiger une note d’incident ou transformer un runbook en tâches. Claude Code aide parce qu’il peut modifier API, Lambda, IAM, tests et documentation dans un changement révisable.
Quatrième cas : l’exploitation de contenu pour un site comme ClaudeCodeLab. Contrôle qualité d’articles, longueur des descriptions, liens internes et vérification de blocs de code peuvent tourner sous IAM et facturation AWS. Si la qualité du contenu influence les revenus, lis aussi le guide des coûts Claude Code et le workflow de preuve de vérification.
Mise en place
Il faut Node.js 20 ou plus, des credentials AWS CLI, un compte AWS ayant accès à Bedrock et un modèle Anthropic disponible dans la Region choisie. Selon le compte, Anthropic peut demander des informations de premier usage, des permissions AWS Marketplace et un moyen de paiement valide.
Ne fige pas un ID de modèle trouvé dans un article. Liste les modèles disponibles pour ton compte et passe l’ID par variable d’environnement.
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}"
Crée un petit projet TypeScript.
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
Ajoute ces scripts à package.json.
{
"type": "module",
"scripts": {
"chat": "tsx src/chat.ts",
"stream": "tsx src/stream.ts",
"typecheck": "tsc --noEmit"
}
}
IAM minimal
Même avec Converse API, l’IAM doit autoriser l’invocation du modèle. Les appels non streaming utilisent bedrock:InvokeModel; le streaming utilise bedrock:InvokeModelWithResponseStream. Sépare les permissions de logs applicatifs de la configuration Bedrock de model invocation logging.
{
"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"
}
]
}
Remplace l’ID de compte, les Regions, le Guardrail et le périmètre de modèles. Avec cross-Region inference, ajoute aussi le profil d’inférence et les ARNs de destination. Pour aller plus loin sur le moindre privilège, consulte le guide AWS IAM avec Claude Code.
Invoquer Claude
Le détail à ne pas oublier est requestMetadata. AWS indique que ce champ peut servir à filtrer les journaux d’invocation, donc ajoute un request ID, une feature et une catégorie d’utilisateur.
// 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);
Lance l’exemple :
export AWS_REGION=us-east-1
export BEDROCK_MODEL_ID="anthropic.claude-sonnet-4-20250514-v1:0"
npm run chat -- "Explique Amazon Bedrock en trois lignes"
npm run stream -- "Crée une checklist de production Bedrock"
npm run typecheck
Pattern Lambda
Dans Lambda, initialise le client hors du handler, valide l’entrée et limite maxTokens côté serveur.
// 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" }),
};
}
};
Ne retry pas ValidationException sans réfléchir : l’entrée ou les paramètres sont invalides. ThrottlingException et ServiceUnavailableException se traitent avec backoff exponentiel et jitter. Pour l’architecture serverless complète, lis Claude Code × AWS Lambda.
RAG avec Knowledge Bases
Pour un chat sur documents internes, Bedrock Knowledge Bases est un bon point de départ avant de construire une stack vectorielle maison. Les réponses peuvent inclure des citations, ce qui facilite la vérification. Attention : Guardrails s’applique à l’entrée et à la réponse générée, pas aux références récupérées. Limite les documents sensibles avec S3, KMS, IAM et une classification claire.
// 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 et coûts
Utilise deux couches de logs. Les logs applicatifs doivent contenir requestId, feature, type d’appelant, ID de modèle, usage, latence et stop reason. Évite de stocker les prompts bruts sauf si ta politique de confidentialité et de rétention l’autorise.
Le model invocation logging de Bedrock peut écrire dans CloudWatch Logs ou S3. C’est utile pour l’audit, mais cela peut stocker des entrées et sorties sensibles. Définis rétention, chiffrement, lifecycle S3 et accès avant activation large.
Pour les coûts, limite maxTokens côté API, choisis le modèle selon la complexité de la tâche, logge usage et utilise IAM principal attribution pour regrouper les coûts par rôle. Prompt caching aide pour les longs contextes répétés, pas pour les prompts courts ou très dynamiques.
Prompt pour Claude Code
claude -p "
Ajoute l'invocation de Claude via Amazon Bedrock dans ce dépôt.
Exigences:
- Utiliser AWS SDK v3 Converse API
- Lire le modèle depuis BEDROCK_MODEL_ID
- Utiliser us-east-1 si AWS_REGION est absent
- Limiter maxTokens à 1200 côté serveur
- Ajouter requestMetadata avec requestId, feature et userId
- Ajouter guardrailConfig seulement si BEDROCK_GUARDRAIL_ID existe
- Logger usage, latencyMs et stopReason en JSON
- Ne pas retry ValidationException
- Traiter ThrottlingException et ServiceUnavailableException comme retryable
- Documenter une politique IAM de moindre privilège dans README
- Mocker le client Bedrock dans les tests; ne pas appeler l'API réelle
Montre le plan avant modification, puis rapporte typecheck et tests.
"
Pièges fréquents
Le premier piège est de coder avant de vérifier l’accès modèle. Teste list-foundation-models puis une petite requête Converse.
Le deuxième est de figer un model ID copié d’un article. Utilise la configuration et vérifie au démarrage.
Le troisième est de croire que Guardrails garantit la vérité métier. Il sécurise des politiques, mais ne remplace pas revue humaine, validation domaine ou autorisation.
Le quatrième est de trop logger. Les prompts complets aident au debug, mais peuvent exposer des données personnelles ou internes.
Le cinquième est de retry les mauvais errors. Validation demande une correction ; throttling et erreurs temporaires peuvent être retry.
Le sixième est de limiter les coûts uniquement côté frontend. Les limites réelles doivent être appliquées par l’API.
Chemin de monétisation
La valeur d’un contenu Bedrock n’est pas le snippet SDK, mais le passage du demo à la production : IAM, logs, coûts, Guardrails, revues et adoption d’équipe. Pour des templates réutilisables, commence par les produits ClaudeCodeLab. Pour un déploiement adapté à ton dépôt avec CLAUDE.md, revue IAM, preuves de vérification et gates CI, utilise la formation et consultation Claude Code.
À lire aussi : Claude Code AWS Lambda, Claude Code AWS IAM, coûts Claude Code et workflow de vérification.
Résultat pratique
Après test, l’amélioration principale n’est pas venue d’une couche de code supplémentaire, mais du prompt donné à Claude Code. En précisant « model ID via env », « logger usage », « ne pas retry ValidationException », « Guardrails optionnel par env » et « politique IAM dans README », les diffs sont devenus plus petits et la revue plus claire. Réussir Bedrock dépend moins de mémoriser le SDK que de formuler les contraintes de production avant la génération de code.
PDF gratuit: cheatsheet Claude Code
Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.
Nous protégeons vos données et n'envoyons pas de spam.
À propos de l'auteur
Masa
Ingénieur spécialisé dans les workflows pratiques avec Claude Code.
Articles liés
Workflow Obsidian vers CLAUDE.md avec Claude Code
Transformer des notes Obsidian en notes CLAUDE.md concises pour reprendre les sessions sans réexpliquer.
Claude Code Revenue CTA Routing : relier articles, PDF, Gumroad et consultation
Un workflow Claude Code pour orienter les lecteurs vers PDF gratuit, Gumroad ou consultation selon l'intention.
Règles de handoff Claude Code en équipe: preuves, permissions, rollback et revenus
Un format concret pour transmettre un travail Claude Code avec preuves, permissions, rollback, PDF gratuit, Gumroad et consultation.