Claude Code × Amazon Bedrock: panduan praktis menjalankan Claude di produksi AWS
Bangun Claude produksi dengan Claude Code dan Amazon Bedrock: IAM, Converse API, logs, Guardrails, dan kontrol biaya.
Memanggil Anthropic API langsung adalah cara cepat untuk prototipe Claude. Di produksi AWS, masalahnya berubah: pengelolaan API key, batas IAM, audit log, atribusi biaya, retensi data, retry, dan quota. Di titik itu, Amazon Bedrock sebagai runtime Claude menjadi pilihan yang lebih praktis.
Amazon Bedrock adalah layanan managed foundation model dari AWS. Secara sederhana, aplikasi Anda dapat memanggil Claude lewat identity, permission, logging, billing, dan kontrol operasional AWS. Claude Code tetap berguna, tetapi jangan hanya meminta demo yang jalan. Minta kode yang bisa direview: IAM, model invocation, Guardrails, logging, error handling, dan batas biaya.
Pelajaran Masa dari project nyata cukup jelas: demo Bedrock bisa jalan cepat, tetapi review produksi menanyakan hal lain. Role mana yang memanggil model? Model ID mana yang boleh dipakai? Apa yang terjadi saat throttling? Prompt disimpan atau tidak? Bagaimana biaya ditelusuri per tim? Panduan ini mengubah pertanyaan itu menjadi kode dan prompt Claude Code.
Artikel ini mengikuti dokumentasi resmi AWS per 3 Juni 2026. Model ID, Region, quota, dan harga Bedrock dapat berubah; verifikasi dengan sumber resmi sebelum deploy.
- 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
Arsitektur Produksi
Jangan mulai dengan meminta Claude Code “tambahkan chat Bedrock”. Tentukan dulu caller, runtime, model, Guardrails, logs, dan atribusi biaya.
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 adalah interface chat terpadu di Bedrock. Guardrails mengevaluasi input user dan output model berdasarkan policy keamanan. model invocation logging dapat mengirim data invocation ke CloudWatch Logs atau S3. IAM principal attribution membantu melihat biaya Bedrock berdasarkan IAM user atau role.
Use Case Yang Cocok
Use case pertama adalah Q&A dokumen internal. Runbook, spesifikasi produk, dan prosedur support disimpan di S3 dan Knowledge Bases; potongan relevan diambil, lalu Claude membuat jawaban dengan citation. Ini disebut RAG, retrieval augmented generation.
Use case kedua adalah draft jawaban support. Claude menggabungkan pertanyaan pelanggan, detail paket, dan template yang sudah disetujui untuk membuat draft yang direview operator. Sebelum otomatis penuh, simpan human approval, Guardrails, pengelolaan data pribadi, dan audit log.
Use case ketiga adalah asisten operasi engineering. Ia bisa merangkum CloudWatch logs, membuat checklist deploy, menulis catatan incident, atau mengubah runbook menjadi daftar tugas. Claude Code membantu karena API, Lambda, IAM, test, dan dokumentasi bisa berubah dalam satu diff yang bisa direview.
Use case keempat adalah content operations untuk situs seperti ClaudeCodeLab. QA artikel, panjang description, saran internal link, dan review code block dapat berjalan di bawah IAM dan billing AWS. Jika kualitas konten memengaruhi revenue, gabungkan dengan panduan biaya Claude Code dan verification receipt workflow.
Setup
Anda membutuhkan Node.js 20 atau lebih baru, kredensial AWS CLI, akun dengan akses Bedrock, dan model Anthropic yang tersedia di Region target. Tergantung akun, model Anthropic bisa memerlukan first-time use details, permission AWS Marketplace, dan metode pembayaran valid.
Jangan hard-code model ID dari artikel. List model yang tersedia di akun Anda, lalu simpan pilihan di environment variable.
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}"
Buat project TypeScript kecil.
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
Tambahkan script ke package.json.
{
"type": "module",
"scripts": {
"chat": "tsx src/chat.ts",
"stream": "tsx src/stream.ts",
"typecheck": "tsc --noEmit"
}
}
IAM Minimum
Walaupun memakai Converse API, IAM tetap membutuhkan permission model invocation. Non-streaming memakai bedrock:InvokeModel; streaming memakai bedrock:InvokeModelWithResponseStream. Pisahkan permission log aplikasi dari konfigurasi model invocation logging 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"
}
]
}
Ganti account ID, Region, Guardrail ID, dan scope model sesuai environment. Jika memakai cross-Region inference, sertakan inference profile dan ARN model tujuan. Untuk review least privilege, baca panduan AWS IAM dengan Claude Code.
Memanggil Claude
Detail produksi yang penting adalah requestMetadata. AWS mendokumentasikannya sebagai cara membantu filter model invocation logs, jadi masukkan request ID, feature, dan kategori caller.
// 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);
Jalankan:
export AWS_REGION=us-east-1
export BEDROCK_MODEL_ID="anthropic.claude-sonnet-4-20250514-v1:0"
npm run chat -- "Jelaskan Amazon Bedrock dalam tiga baris"
npm run stream -- "Buat checklist produksi Bedrock"
npm run typecheck
Pola Lambda
Di Lambda, inisialisasi client di luar handler, validasi input, dan batasi maxTokens di server.
// 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" }),
};
}
};
Jangan retry ValidationException secara buta; biasanya input atau parameter salah. ThrottlingException dan ServiceUnavailableException dapat memakai exponential backoff dan jitter. Untuk serverless lengkap, baca Claude Code × AWS Lambda.
RAG Dengan Knowledge Bases
Untuk chat dokumen internal, Bedrock Knowledge Bases adalah titik awal yang lebih cepat daripada membangun vector store sendiri. Jawaban bisa menyertakan citation agar sumber mudah dicek. Catatan penting: Guardrails berlaku untuk input dan output yang dihasilkan, bukan referensi yang diambil. Batasi dokumen sensitif dengan S3, KMS, IAM, dan klasifikasi data.
// 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 Dan Biaya
Gunakan dua lapisan log. Log aplikasi mencatat requestId, feature, tipe caller, model ID, usage, latency, dan stop reason. Hindari menyimpan prompt mentah kecuali policy privasi dan retensi memang mengizinkan.
Model invocation logging Bedrock dapat menulis ke CloudWatch Logs atau S3. Ini membantu audit, tetapi juga bisa menyimpan input dan output sensitif. Tentukan retensi, enkripsi, lifecycle S3, dan akses sebelum mengaktifkannya secara luas.
Untuk biaya, batasi maxTokens di API, pilih model sesuai kompleksitas tugas, log usage, dan gunakan IAM principal attribution untuk mengelompokkan biaya per role. Prompt caching membantu konteks panjang yang berulang, bukan prompt pendek atau sangat dinamis.
Prompt Untuk Claude Code
claude -p "
Tambahkan pemanggilan Claude melalui Amazon Bedrock ke repository ini.
Syarat:
- Gunakan AWS SDK v3 Converse API
- Baca model dari BEDROCK_MODEL_ID
- Default AWS_REGION ke us-east-1
- Batasi maxTokens ke 1200 di server
- Tambahkan requestMetadata dengan requestId, feature, userId
- Tambahkan guardrailConfig hanya jika BEDROCK_GUARDRAIL_ID ada
- Log usage, latencyMs, stopReason sebagai JSON
- Jangan retry ValidationException
- Anggap ThrottlingException dan ServiceUnavailableException retryable
- Dokumentasikan policy IAM least privilege di README
- Mock Bedrock client di test; jangan panggil API asli
Tampilkan rencana sebelum edit, lalu laporkan typecheck dan hasil test.
"
Pitfall Umum
Pertama, menulis kode sebelum verifikasi model access. Jalankan list-foundation-models dan satu Converse request kecil.
Kedua, membekukan model ID dari artikel. Bedrock model ID dan dukungan Region berubah. Pakai konfigurasi dan validasi saat startup.
Ketiga, menganggap Guardrails menjamin kebenaran. Ia membantu safety policy, bukan pengganti validasi domain, authorization, atau human review.
Keempat, logging berlebihan. Prompt lengkap berguna untuk debug, tetapi bisa menyimpan data pribadi atau internal terlalu lama.
Kelima, retry error yang salah. Validation perlu perbaikan input atau kode; throttling dan error sementara bisa retry.
Keenam, membatasi biaya hanya di frontend. Batas nyata harus ditegakkan di API.
Jalur Monetisasi
Nilai artikel Bedrock bukan snippet SDK, melainkan cara membawa demo ke produksi: IAM, logs, biaya, Guardrails, review, dan rollout tim. Untuk template reusable, mulai dari produk ClaudeCodeLab. Untuk rollout di repository nyata dengan CLAUDE.md, review IAM, verification receipt, dan CI gate, gunakan training dan konsultasi Claude Code.
Bacaan terkait: Claude Code AWS Lambda, Claude Code AWS IAM, biaya Claude Code, dan verification receipt workflow.
Hasil Praktis
Setelah mencoba pola ini, peningkatan terbesar bukan dari menambah abstraksi, tetapi dari prompt Claude Code yang lebih jelas: model ID dari env, wajib log usage, jangan retry ValidationException, Guardrails opsional lewat env, dan policy IAM ditulis di README. Diff menjadi lebih kecil dan review lebih mudah. Keberhasilan Bedrock lebih bergantung pada batas produksi yang jelas sebelum code generation daripada menghafal SDK.
PDF gratis: cheatsheet Claude Code
Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.
Kami menjaga datamu dan tidak mengirim spam.
Tentang penulis
Masa
Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.
Artikel terkait
Workflow Obsidian ke CLAUDE.md untuk Claude Code
Ubah catatan kerja Obsidian menjadi operating note CLAUDE.md agar konteks tidak dijelaskan ulang.
Claude Code Revenue CTA Routing: dari artikel ke PDF, Gumroad, dan konsultasi
Workflow Claude Code untuk mengarahkan pembaca ke PDF gratis, Gumroad, atau konsultasi sesuai intent.
Aturan handoff tim Claude Code: bukti review, permission, rollback, dan jalur revenue
Format handoff Claude Code untuk tim: bukti, permission rule, rollback, PDF gratis, Gumroad, dan konsultasi.