Use Cases

Claude Code × Amazon Bedrock 完全ガイド|AWS上でClaudeを本番運用する

Claude CodeでAmazon Bedrockを活用する完全ガイド。IAM認証・ストリーミング・Lambda統合・RAG実装・コスト最適化まで、Masaの業務実装経験をもとに解説。

「Claude API を本番サービスで使いたいが、API キーの管理が不安」「社内セキュリティ要件でデータを AWS 外に出せない」——こういった壁にぶつかったエンジニアに、Amazon Bedrock は最良の解答です。

私は業務でECS上のAPIサーバーにAIを組み込む際、最初は Anthropic の API を直接使っていましたが、セキュリティ審査で「外部サービスへのAPI キー管理が課題」と指摘されました。Bedrock に切り替えてからは IAM ロールだけで認証が完結し、API キー管理から解放されました。この記事では、Claude Code を使った Bedrock の実装から本番運用まで解説します。


Amazon Bedrock とは

Amazon Bedrock は AWS のマネージド AI モデルサービス。Claude (Anthropic)・Llama (Meta)・Titan (Amazon) など複数のモデルを統一した API で呼べます。

なぜ Bedrock を使うのか

観点Anthropic APIAmazon Bedrock
認証API キーAWS IAM ロール
請求Anthropic に直接AWS 請求に統合
VPC 対応なしPrivateLink で完全閉域
データ保持Anthropic のポリシーAWS のポリシー
コンプライアンスSOC2 等SOC2/ISO27001/HIPAA 等

個人開発なら Anthropic API が手軽ですが、エンタープライズ・金融・医療系では Bedrock 一択になるケースが増えています。


Step 1: 初期セットアップ

モデルアクセスの申請

まず AWS コンソールで Claude モデルへのアクセスを申請します。

# 有効なモデル一覧を確認
aws bedrock list-foundation-models \
  --by-provider anthropic \
  --region us-east-1 \
  --query 'modelSummaries[].{id:modelId, name:modelName}'

# 出力例
[
  {"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"}
]

重要: 利用可能なリージョンは us-east-1 (バージニア) と us-west-2 (オレゴン) が主力。東京リージョンは Cross-region inference 経由で使えます。

SDK インストール

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

Step 2: 基本実装

Anthropic SDK の Bedrock 対応を使う (推奨)

Anthropic 公式 SDK には Bedrock 対応が組み込まれています。通常の Anthropic API とほぼ同じ書き方で使えるため、既存コードの移行コストが最小です。

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

// Lambda/ECS 等の IAM ロールが使われる場合は認証情報不要
const bedrock = new Anthropic.AnthropicBedrock({
  awsRegion: process.env.AWS_REGION ?? "us-east-1",
  // ローカル開発時は 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 : "";
}

Bedrock のモデル ID は Anthropic API と異なります:

Anthropic API: claude-sonnet-4-6
Bedrock:       anthropic.claude-sonnet-4-6  (プレフィックスが付く)

ストリーミング対応

長い応答にはストリーミングが必須です。

// 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;
    }
  }
}

// 使用例 (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" },
  });
}

Step 3: Lambda + Bedrock のパターン

サーバーレスで AI 機能を提供する最もよく使われる構成です。

claude -p "
src/lambda/ai-handler.ts に以下の Lambda 関数を実装して:
- イベントから prompt と maxTokens を受け取る
- Bedrock (claude-sonnet-4-6) を呼んで結果を返す
- エラーは ThrottlingException (リトライ) と ValidationException (400) で処理分岐
- 実行時間をログに記録
- コンテナ外でクライアント初期化 (コールドスタート最適化)
"
// src/lambda/ai-handler.ts
import { Handler, APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
import Anthropic from "@anthropic-ai/sdk";

// モジュールスコープで初期化 (コンテナ再利用時にキャッシュされる)
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" }) };
  }
};

Lambda の IAM ポリシー

// CDK での IAM 設定
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`,
  ],
}));

Step 4: RAG (Retrieval-Augmented Generation) の実装

社内ドキュメントや製品情報を Claude に読ませて回答させるパターン。

claude -p "
Bedrock Knowledge Base を使った RAG システムを実装して。

構成:
- S3 にドキュメントを保存
- Bedrock Knowledge Base でベクトルインデックス化
- ユーザーの質問に基づいてドキュメントを検索
- Claude Sonnet で回答生成

TypeScript + AWS SDK v3 で実装。
Knowledge Base ID は環境変数 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 };
}

Step 5: コスト最適化

// モデル選択ユーティリティ
type TaskType = "classify" | "extract" | "summarize" | "generate" | "complex";

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

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

プロンプトキャッシュで入力コストを削減

// 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" },  // 5分間キャッシュ
    },
  ],
  messages: [{ role: "user", content: userQuery }],
});

落とし穴5選

1. リージョンが対応していない

Claude on Bedrock は全リージョンで使えません。2026年現在、us-east-1 us-west-2 が主力。東京から使う場合は Cross-region inference (クロスリージョン推論) を有効化します。

// クロスリージョン推論用の model ARN を使う
const crossRegionModelArn = 
  "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-sonnet-4-6";

2. モデルアクセス申請を忘れる

Bedrock では使いたいモデルごとに「Model access」の申請が必要です。申請なしに呼ぶと AccessDeniedException が出ます。Claude Code でのコーディング前に必ず申請してください。

3. Lambda のタイムアウトが短い

Claude の応答に 10〜30秒かかることがあります。Lambda のデフォルト3秒では確実にタイムアウトします。最低30秒、長い生成なら60〜300秒に設定しましょう。

4. Bedrock のモデル ID を Anthropic API の ID と混同する

❌ Anthropic API のID をそのまま使う: "claude-sonnet-4-6"
✅ Bedrock 用の ID: "anthropic.claude-sonnet-4-6"

5. Cross-region inference のレイテンシを考慮しない

東京から us-east-1 のモデルを呼ぶと、往復のネットワーク遅延が加算されます (100〜200ms 程度)。リアルタイム性が求められるアプリでは、ストリーミングで体感遅延を軽減しましょう。


まとめ

タスクClaude Code の貢献
基本実装AnthropicBedrock クライアントと関数を生成
Lambda 統合ハンドラー・IAM ポリシーを一括生成
RAG 実装Knowledge Base 連携コードを自動生成
コスト最適化タスクに応じたモデル選択ロジックを設計
トラブル解決エラーログから原因と修正案を提示

Claude Code で開発し、Bedrock で本番運用——この組み合わせは セキュリティ・コスト・スケーラビリティ のすべてを満たします。まず無料の Bedrock 試用から始めて、本番に移行する際は IAM ロールの設定だけで完結します。

関連記事

参考資料

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

Claude Codeをもっと活用しませんか?

実務で使えるプロンプトテンプレート50選。コピペですぐ使えます。

無料プレゼント

無料PDF: Claude Code 5分でわかるチートシート

メールアドレスを登録するだけで、A4 1枚のチートシートPDFを今すぐお送りします。

個人情報は厳重に管理し、スパムは送りません。

Masa

この記事を書いた人

Masa

現役DX室長|Claude Code でゼロから多言語AI技術メディア運営中。実務直結の自動化、AI開発相談・研修受付中。

PR

関連書籍・参考図書

この記事のテーマに関連する書籍を楽天ブックスで探せます。

※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。