NO IMAGE

Bedrock Agents 実戦編 Action Group OpenAPI Terraform Guardrails

NO IMAGE
目次

1. この記事について

2026 年 4 月時点の AWS 公式ドキュメントおよび Terraform AWS Provider v5.70、Bedrock Agents API を基準に記述しています。
料金・API 仕様・対応リージョンは変更の可能性があるため、実際の適用前に必ず公式ページを確認してください。

fig01: Bedrock Agents 全体アーキテクチャ

Amazon Bedrock Agents は、LLM の推論能力と外部ツール実行を組み合わせ、複雑なマルチステップタスクを自律的にこなす AWS マネージドサービスだ。
2023 年の GA 以降、Action Group・Knowledge Base 統合・Guardrails・Trace API と本番運用に必要な機能が次々と整い、
2025 年末には東京リージョンを含む主要リージョンで安定稼働が確認されている。

InvokeModel で LLM を単体呼び出しする段階では、モデルはリアルタイムデータを持たず、外部システムを操作する手段もない。
「今日の在庫数を確認して発注を確定してほしい」「社内規程を検索してコンプライアンス判断を下してほしい」といったタスクは LLM 単独では完結できない。
Bedrock Agents は Action Group(Lambda + OpenAPI Schema)という「ツール」と、Knowledge Base(S3 + ベクトルストア)という「記憶」を
Agent に持たせることで、この制約を突破する。

本記事は、その全機能を本番設計という視点で体系的に押さえる一冊だ。
アーキテクチャ設計から Terraform HCL・Lambda Handler 契約・Guardrails 安全設計・CloudWatch Trace による観測まで、
実際の本番稼働に必要な全工程を動作確認済みのサンプルで解説する。

この記事で得られること

  • Action Group + Lambda + OpenAPI Schema 3.0.x を組み合わせたツール連携の完全実装手順
  • Knowledge Base(OpenSearch Serverless 主軸)を Agent に統合した社内文書 RAG の本番設計
  • Bedrock Guardrails で禁止トピック・PII マスク・Prompt Attack 検知を設定する安全設計
  • Terraform aws_bedrockagent_agent / aws_bedrockagent_agent_action_group / aws_bedrockagent_knowledge_base リソースによる IaC 実装
  • CloudWatch Logs / Metrics / Trace API(enableTrace=true)を用いた本番観測基盤の構築
  • IAM 信頼関係・Lambda Permission・Agent Alias バージョニングなど本番投入前に潰すべき落とし穴 10 選
この記事を読む前に確認すること

  • Amazon Bedrock で InvokeModel / InvokeModelWithResponseStream の API 呼び出し経験がある
  • Knowledge Bases for Amazon Bedrock の単体 RAG(S3 → Embedding → Retrieve & Generate)は経験済み(未経験の場合は先に「Bedrock RAG 知識ベース入門」を参照)
  • Terraform で S3 バケット・IAM ロールを作成できるレベルの HCL 読み書き能力がある
  • Lambda 関数の作成・IAM ロールのアタッチ・CloudWatch Logs でのデバッグ経験がある
  • AWS CLI v2 のインストールと aws configure による認証設定が完了している

1-1. 本記事のゴール

この記事を完走すると、次の 6 つの状態を自分の AWS アカウントで再現できる。

  1. Agent の作成と呼び出し: マネジメントコンソール・AWS CLI・Terraform の 3 手段で Bedrock Agent を起動し、マルチターン会話が成立する状態を確認できる。
  2. Action Group によるツール連携: OpenAPI Schema 3.0.x で外部 API の仕様を定義し、Lambda Handler が Function Calling で呼び出される全フローを実装できる。
  3. Knowledge Base 統合: S3 の社内文書を OpenSearch Serverless でベクトル化し、Agent が RAG を使って文書を参照しながら回答を生成できる。
  4. Guardrails 設定: 禁止トピックフィルタ・PII マスク・Prompt Attack 検知を有効化し、本番環境での安全運用ルールを設計できる。
  5. Terraform 一括構築: aws_bedrockagent_* リソース群を含む完全 HCL を terraform apply 一発で展開できる。
  6. 観測基盤の確認: enableTrace=true で得られる Trace JSON の読み方を理解し、どのステップで何秒かかったか・どのツールを選択したかを CloudWatch で追跡できる。

本記事完走後のゴール状態:

確認項目期待動作
Agent invoke(multi-turn)セッション継続でコンテキストを保持した会話が成立する
Action Group 呼び出し外部 API(モック Lambda)の呼び出し成功・結果整形・Agent 応答確認
Knowledge Base RAGS3 文書を検索し引用付き回答を生成できる
Guardrails ブロック禁止キーワード入力時に適切なブロックメッセージが返る
Terraform destroyterraform destroy でリソース全削除が正常に完了する

Bedrock Agents の実装で最も難しいのは個々の機能より「各コンポーネントの繋ぎ方」だ。
IAM 信頼ポリシー・Lambda Resource-based Policy・OpenAPI Schema の operationId 命名・KB Sync のタイミングなど繋ぎ目の落とし穴が多い。
本記事はこれらを §6 の「Terraform 完全 HCL」と §8 の「落とし穴 10 選」で集中的に潰す設計になっている。

1-2. 読者像

この記事は次の読者を想定して書いている。

対象読者

読者像具体的な状況
AWS エンジニア(中級以上)Bedrock で Claude を直叩きした経験あり。次のステップとして Agent 設計を本番に持ち込みたい
AI アーキテクト複数ツール・複数データソースを組み合わせた AI ワークフローをマネージドサービスで設計したい
インフラエンジニアAction Group + Knowledge Base を Terraform でコード管理し、CI/CD パイプラインに組み込みたい

前提スキルレベル: Bedrock 中級以上。具体的には以下が条件だ。

  • InvokeModel / InvokeModelWithResponseStream の呼び出しコードを自分で書いた経験がある
  • Lambda 関数の作成・IAM ロールのアタッチ・CloudWatch Logs でのデバッグができる
  • Terraform で S3 バケットや IAM ロールを作成できるレベルの HCL 読み書き能力がある

対象外: Bedrock を初めて触る読者・Lambda の経験がない読者は、まず「Bedrock RAG 知識ベース入門」と AWS Lambda 基礎からスタートすることを推奨する。
本記事は「本番運用完全ガイド」であり入門書ではない。Action Group の設計・実装から IAM 落とし穴まで、実務水準の内容が続く。

この記事で扱わないこと

  • Bedrock 自体の入門(InvokeModel の基本呼び出し)
  • Amazon Q や Bedrock Studio の GUI 操作チュートリアル
  • Multi-Agent Collaboration(複数 Agent の連携設計)は本記事スコープ外

1-3. なぜ今これを書くか

LLM 単独利用の限界

InvokeModel で Claude にリクエストを送る段階では、LLM はリアルタイム情報を持たず、外部システムを操作する手段もない。
自然言語の理解と生成は優秀だが、「現在の在庫数を調べて発注を確定する」「社内 Confluence から最新規程を検索して回答する」
「CRM の顧客データを更新する」といったタスクは完結しない。
このギャップを埋めるのが Function Calling だ。
Bedrock Agents はこれを AWS マネージドで提供し、Lambda・OpenSearch・S3 といった既存インフラと直接統合できる点で、
LangChain Agents 等の汎用フレームワークより運用負荷が低い。

既存 Bedrock RAG 入門との差別化

「Bedrock RAG 知識ベース入門」(本ブログ既出)は、Knowledge Bases for Amazon Bedrock を単体で使い、S3 文書を Retrieve & Generate する流れを扱った。
本記事はその先の設計だ。

比較軸Bedrock RAG 入門(既出)本記事
主役Knowledge Base 単体Agent(KB はツールの 1 つ)
データソースS3 文書のみS3 文書 + 外部 API(Action Group)
オーケストレーションなし(Retrieve & Generate のみ)Agent が自律的にツール選定・呼び出し
セッション管理なしSessionAttributes・multi-turn 対応
安全設計なしGuardrails(PII/禁止/Prompt Attack)

KB 単体から Agent 統合へのステップアップが本記事の核心だ。
既存の Bedrock RAG 入門と本記事は補完関係にあり、KB の詳細設計は本記事 §4 と合わせて読むことで完結する。

国内情報の空白

2024 年の Bedrock Agents GA 以降、英語圏では AWS 公式サンプル(Booking Agent / Insurance Claims Agent 等)や re:Invent セッション資料が豊富に存在する。
しかし国内では入門レベルの紹介記事が多く、OpenAPI Schema の operationId 設計コツ・Lambda Handler の event/responseBody 契約・
aws_bedrockagent_* Terraform リソースの落とし穴を体系的に扱った日本語資料は少ない。
本記事はその空白を埋めることを目指す。

2026 年時点の技術的成熟

Bedrock Agents のエコシステムは 2025 年を通じて急速に安定した。
Agent Alias のバージョニング機能・Guardrails の本番適用事例の蓄積・OpenSearch Serverless の東京リージョン安定稼働が揃い、本番投入のリスクが大幅に低下した。
加えて、Terraform AWS Provider が aws_bedrockagent_agent リソースを v5.40 以降で安定サポートするようになり、
IaC でのライフサイクル管理が現実的になった。
このタイミングで「本番運用完全ガイド」をまとめる意義は大きい。

AWS 公式 Bedrock Agents ユーザーガイドを確認する


2. 全体像

fig02: Agent + Action Group + KB + Lambda + IAM 構成

Bedrock Agents の本番設計を理解するには、まず 5 つのコアコンポーネントとそれらの連携方式を俯瞰する必要がある。
本章では Agent の全体構成・呼び出しフロー・Foundation Model 選定の 3 軸を整理し、以降の実装章の読み進め方を示す。

2-1. Agent コンポーネント全体像

Bedrock Agents は次の 5 コンポーネントで構成される。

コンポーネント役割対応 AWS サービス
Agent 本体LLM を使ったオーケストレーション層。ユーザー入力を解析し、どのツールを呼ぶかを決定するAmazon Bedrock Agents
Action GroupAgent が呼び出せる「ツール」の定義。OpenAPI Schema で仕様を記述し、Lambda が実装するLambda + OpenAPI Schema (S3)
Knowledge BaseAgent が参照できる「記憶」。S3 文書をベクトル化して保存し、RAG で応答を強化するBedrock Knowledge Bases + OpenSearch Serverless
Guardrails安全フィルタ。禁止トピック・PII マスク・Prompt Attack 検知をリアルタイムで適用するBedrock Guardrails
IAM各コンポーネント間の信頼関係と権限制御。3 経路の設定が必要IAM Role / Policy

コンポーネント間の依存関係

Agent 本体は中心に位置し、Action Group・Knowledge Base・Guardrails をアタッチすることで機能を拡張する。
Action Group は「何をできるか(能力)」を定義し、Knowledge Base は「何を知っているか(知識)」を提供する。
Guardrails は入力・出力の両方に適用される安全層として機能する。

IAM 設計は 3 つの信頼関係を正しく設定する必要がある。

  1. Bedrock → Lambda: Agent が Action Group の Lambda 関数を呼び出す権限(Lambda Resource-based Policy)
  2. Bedrock Agent 実行ロール: Agent 実行時に使用するサービスロール(bedrock.amazonaws.com を Principal とする信頼ポリシー)
  3. Agent → Knowledge Base: Agent が KB の Retrieve API を呼び出す権限(Inline Policy に bedrock:Retrieve を含める)

この 3 経路の IAM 設定ミスが、本番投入で最も多いエラー原因だ。§6 の Terraform HCL ではこれらをすべてコード化して示す。

Agent の状態管理

Agent には DRAFTALIAS の 2 状態がある。
DRAFT は開発中の可変バージョンで、ALIAS はバージョンを固定したデプロイ用エントリポイントだ。
本番では必ず Alias を使い、Agent バージョンを固定して呼び出す。
Alias を経由することで、ブルーグリーンデプロイ(旧 Alias を保持しながら新 Alias を作成)が可能になる。

使用する技術スタック

技術要素バージョン / 仕様用途
Amazon Bedrock Agents2023 GA / 2026-04 時点Agent オーケストレーション層
Foundation ModelClaude 3.5 Sonnet (anthropic.claude-3-5-sonnet-20241022-v2:0)LLM 推論エンジン
OpenAPI Schema3.0.xAction Group ツール仕様定義
AWS LambdaPython 3.12 runtimeAction Group 実装(ハンドラ)
Bedrock Knowledge BasesOpenSearch Serverless 主軸社内文書 RAG
Bedrock Guardrails2024 GA安全フィルタ
Terraform AWS Provider~> 5.50aws_bedrockagent_* 安定版)Infrastructure as Code
AWS CLIv2 / bedrock-agent + bedrock-agent-runtime サブコマンド検証・デバッグ

2-2. 呼び出しフロー

ユーザーからのリクエストが Agent を経由してツールを呼び出し、回答として戻るまでの全フローを示す。

Agent 呼び出しの全フロー

1. ユーザー入力
└─ InvokeAgent API(sessionId 付き)

2. Agent 推論(ReAct ループ開始)
├─ Foundation Model が入力を解析
└─ どの Action Group / Knowledge Base を使うか決定

3. ツール選定と呼び出し
├─ [Action Group 選択時] → OpenAPI Schema 照合 → Lambda 呼び出し → 結果受信
└─ [Knowledge Base 選択時] → Retrieve API → ベクトル検索 → 関連チャンク取得

4. 結果整形と再推論
├─ Lambda / KB の結果を Foundation Model にフィードバック
└─ 最終回答に十分な情報が揃うまでステップ 2-4 を繰り返す

5. Guardrails 適用
├─ 入力フィルタ(ユーザー入力の時点で適用)
└─ 出力フィルタ(Agent の最終応答に適用)

6. 最終応答返却
└─ InvokeAgent レスポンス(streaming も選択可)
</code>

Python SDK での呼び出し例

import boto3

client = boto3.client("bedrock-agent-runtime", region_name="us-east-1")

response = client.invoke_agent(
 agentId="AGENT_ID",
 agentAliasId="ALIAS_ID",
 sessionId="session-001",
 enableTrace=True,
 inputText="現在の注文状況を確認して、在庫切れの商品をリストアップしてください",
)

for event in response["completion"]:
 if "chunk" in event:
  print(event["chunk"]["bytes"].decode("utf-8"), end="")
 if "trace" in event:
  trace = event["trace"]["trace"]
  if "orchestrationTrace" in trace:
print(f"[Trace] {trace['orchestrationTrace']}")
</code>

ReAct ループの挙動

Bedrock Agents は ReAct(Reasoning + Acting)パターンで動作する。
1 回のユーザー入力に対して、内部では「考える(LLM 推論)→ 行動する(ツール呼び出し)→ 観察する(結果確認)」を複数回繰り返す。
この反復は maxIterations(デフォルト 5)で制限される。
タスクが複雑すぎて maxIterations を超えると FAILED ステータスが返るため、ユースケースに応じた上限設計が必要だ。

sessionId の設計指針

sessionId は multi-turn 会話のコンテキストを維持するキーだ。
同一 sessionId で連続して InvokeAgent を呼ぶと、Agent は前の会話コンテキストを保持した状態で応答する。
セッションのデフォルト有効期間は 25 分で、idleSessionTTLInSeconds で最大 3600 秒まで延長できる。
本番ではユーザーごと・会話スレッドごとに一意な sessionId を生成して管理する。

2-3. Foundation Model 選定

Bedrock Agents はアタッチする Foundation Model を Agent 作成時に指定する。
2026 年 4 月時点での推奨選定指針を示す。

モデル推奨用途Function Calling 精度レイテンシコスト
Claude 3.5 Sonnet (us-east-1)本番メイン推奨。複雑なツール選定・日本語混在に強い◎ 最高水準
Claude 3 Haiku低レイテンシ要件・シンプルなツール呼び出し○ 良好
Amazon Nova Proコスト最適化・AWS ネイティブ連携○ 良好低〜中
Claude 4 系高難度推論・最新モデル(Bedrock 対応状況を要確認)中〜高

本記事の推奨: anthropic.claude-3-5-sonnet-20241022-v2:0(2026 年 4 月時点)

推奨する理由は 3 つある。
第一に、Action Group の Function Calling 精度が高く、OpenAPI Schema の description を LLM が正確に解釈してツールを選定する成功率が高い。
第二に、日本語の入出力に安定しており、日本語エンタープライズ環境での実績が豊富だ。
第三に、Bedrock Agents の公式サンプル実装の多くが Claude 3.5 Sonnet を使用しており、トラブルシュートの参考情報が揃っている。

モデル変更時の注意点として、foundation_model フィールドの値はリージョンごとに利用可能なモデル ID が異なる。
us-east-1ap-northeast-1(東京)ではサポートモデルセットが異なるため、aws bedrock list-foundation-models で事前確認が必要だ。
また、モデル変更後は Agent を再 PREPARE する必要がある(Terraform では prepare_agent = true 設定で自動化できる)。

⚙️ QG-1: Bedrock Agents 全体アーキテクチャ — 設計前に把握すべき 5 つの核心

  • Agent 本体(オーケストレーション層) — Foundation Model を使い「どのツールを呼ぶか」を自律決定する中枢。ReAct ループで最大 maxIterations 回の推論・行動・観察を繰り返す。本番では maxIterations を 10 以下に制限し、無限ループを防ぐこと。
  • Action Group(能力層) — Agent が呼び出せる「ツール」の定義。OpenAPI Schema 3.0.x で API 仕様を記述し、Lambda が実装する。description フィールドの書き方が LLM によるツール選定精度に直結するため、「何をするツールか・いつ使うか」を具体的に記述することが最重要ポイント。
  • Knowledge Base(知識層) — S3 文書を Embedding してベクトルストアに格納し、RAG で応答を強化する。OpenSearch Serverless(マネージド・推奨)または Aurora pgvector(コスト最適化代替)を選択する。KB は Action Group と独立しており、単体でも Agent との組み合わせでも使用できる。
  • Guardrails(安全層) — 入力・出力の両方に適用するフィルタ。禁止トピック(Denied Topics)・PII マスク・Prompt Attack 検知(Prompt Shield)・ワードフィルタの 4 種を組み合わせる。Agent とは独立したリソースとして作成し、Agent 作成時にアタッチする。本番環境では必ず有効化すること。
  • IAM(権限層) — 最も落とし穴が多い領域。Agent 実行ロール(bedrock.amazonaws.com 信頼ポリシー)・Lambda Resource-based Policy(bedrock.amazonaws.com からの呼び出し許可)・KB Retrieve 権限(bedrock:Retrieve)の 3 点セットを正確に設定する。いずれか 1 つでも欠けると Agent 呼び出しが AccessDeniedException で失敗する。

2-4. 3 点セット: 基本構成の確認

本章の内容を踏まえ、最小構成の Agent をどの手段で作成・確認できるかを示す。
詳細な実装(Action Group・KB 統合)は §3〜§5 で扱う。

Terraform: Agent 基本 skeleton

resource "aws_bedrockagent_agent" "main" {
  agent_name  = "my-production-agent"
  agent_resource_role_arn = aws_iam_role.bedrock_agent.arn
  foundation_model  = "anthropic.claude-3-5-sonnet-20241022-v2:0"
  idle_session_ttl_in_seconds = 1800
  instruction = <<-EOT
 あなたは社内 AI アシスタントです。
 利用可能なツールを使ってユーザーの質問に日本語で正確に回答してください。
  EOT
  prepare_agent = true
}

resource "aws_bedrockagent_agent_alias" "production" {
  agent_id= aws_bedrockagent_agent.main.id
  agent_alias_name = "production"
  description= "本番用 Alias(バージョン固定)"
}
</code>

AWS CLI: Agent 呼び出し確認

# Agent への直接テスト送信(DRAFT バージョン)
aws bedrock-agent-runtime invoke-agent \
  --agent-id AGENT_ID \
  --agent-alias-id TSTALIASID \
  --session-id test-session-001 \
  --input-text "こんにちは、何ができますか?" \
  --region us-east-1 \
  output.json && cat output.json

# Foundation Model の利用可能一覧を確認(リージョン別)
aws bedrock list-foundation-models \
  --region us-east-1 \
  --query 'modelSummaries[?contains(outputModalities, `TEXT`)].{id:modelId,provider:providerName}' \
  --output table
</code>

コンソール: Agent テスト手順

  1. マネジメントコンソール → Amazon Bedrock → 左メニュー「Agents」を選択する。
  2. 作成済み Agent を選択 → Test タブを開く。
  3. テキストボックスに入力 → Run ボタンで呼び出す。
  4. Show trace チェックボックスを有効にすると ReAct ループの各ステップが可視化される。
  5. DRAFT バージョンでのテストは本番 Alias と同等の挙動を確認できる。

3. Action Group 実装 (OpenAPI Schema + Lambda Handler + Function Calling)

fig03: Action Group Function Calling フロー

Bedrock Agents の核心が Action Group だ。LLM はユーザーの自然言語を解析し、適切な Action Group を選択し、Lambda 経由で外部 API・データベース・社内システムを呼び出す。本節では OpenAPI Schema 設計・Lambda Handler 実装・Function Calling 内部動作を実例で解説する。

3-1. Action Group とは

Action Group は「LLM がどのツールを・どう呼び出すか」を定義するコンポーネントだ。3 要素で構成される。

要素役割備考
OpenAPI Schema (3.0.x)利用可能なツール仕様を LLM に提示S3 またはインライン JSON/YAML で定義
Lambda 関数実際の処理を実行するハンドラBedrock からの event を受け取り responseBody を返す
IAM 権限Bedrock Agent → Lambda 呼び出し許可bedrock.amazonaws.com の resource-based policy

LLM は OpenAPI Schema を読み込み、ユーザーの意図に最も合う operationId を選択する。Bedrock は選択した operationId に対応する Lambda を呼び出し、返却値を次の推論コンテキストに注入する。

3-2. OpenAPI Schema 設計コツ

OpenAPI Schema 3.0.x 形式で定義するが、description フィールドが LLM の選択精度を左右する。以下の実例で設計ポイントを押さえる。

openapi: "3.0.0"
info:
  title: Customer Support API
  version: "1.0"
  description: "顧客サポート業務向け API。注文照会・在庫確認・返品処理を提供する。"
paths:
  /order/query:
 post:
operationId: queryOrderStatus
summary: "注文ステータスを照会する"
description: >
  注文 ID または顧客 ID から注文の配送状況・支払い状況・商品内容を取得する。
  配送が遅延しているか確認したい場合や、注文内容を確認したい場合に使用する。
requestBody:
  required: true
  content:
 application/json:
schema:
  type: object
  required:
 - order_id
  properties:
 order_id:
type: string
description: "注文 ID (例: ORD-2024-001234)。必須。"
 customer_id:
type: string
description: "顧客 ID。order_id が不明な場合に使用。省略可。"
responses:
  "200":
 description: "注文情報"
 content:
application/json:
  schema:
 type: object
 properties:
status:
  type: string
  description: "pending / shipped / delivered / cancelled"
tracking_number:
  type: string
  /inventory/check:
 post:
operationId: checkInventory
summary: "在庫数を確認する"
description: >
  商品 SKU の現在庫数と入荷予定日を返す。在庫切れ確認・入荷日照会に使用する。
requestBody:
  required: true
  content:
 application/json:
schema:
  type: object
  required: [sku]
  properties:
 sku:
type: string
description: "商品 SKU (例: PROD-ABC-001)"
responses:
  "200":
 description: "在庫情報 (quantity: 現在庫数, restock_date: 入荷予定日)"
</code>

Schema 設計の3原則:

  1. operationId は動詞+名詞の camelCase: LLM が選択する際のキーとなる。queryOrderStatus のように意味が一目でわかる名前にする。
  2. description はユーザーの自然言語意図に合わせる: 「いつ使うか」を具体的に書く。LLM はこの description を読んで operationId を選ぶため、「配送が遅延しているか確認したい場合」のようにシナリオを明示すると精度が上がる。
  3. required フィールドを最小化する: 必須でないパラメータは required から外す。LLM が不要なパラメータ収集を試みて会話が冗長になるのを防ぐ。

3-3. Lambda Handler 実装

Bedrock Agents は Lambda を呼び出す際、固定形式の event を渡す。Lambda は responseBody を固定形式で返す必要がある。

event 形式 (Bedrock → Lambda):

{
  "messageVersion": "1.0",
  "agent": { "name": "customer-support-agent", "id": "ABCDEFGH12" },
  "inputText": "注文 ORD-2024-001234 の配送状況を教えて",
  "sessionId": "550e8400-e29b-41d4-a716-446655440000",
  "actionGroup": "CustomerSupportActions",
  "apiPath": "/order/query",
  "httpMethod": "POST",
  "requestBody": {
 "content": {
"application/json": {
  "properties": [{ "name": "order_id", "type": "string", "value": "ORD-2024-001234" }]
}
 }
  }
}
</code>

Lambda Handler (Python 3.12):

import json
from typing import Any

def lambda_handler(event: dict, context: Any) -> dict:
 action_group = event["actionGroup"]
 api_path  = event["apiPath"]
 http_method  = event["httpMethod"]

 props  = event.get("requestBody", {}).get("content", {}).get(
  "application/json", {}).get("properties", [])
 params = {p["name"]: p["value"] for p in props}

 if api_path == "/order/query":
  result = query_order_status(params)
 elif api_path == "/inventory/check":
  result = check_inventory(params)
 else:
  result = {"error": f"Unknown path: {api_path}"}

 return {
  "messageVersion": "1.0",
  "response": {
"actionGroup": action_group,
"apiPath": api_path,
"httpMethod": http_method,
"httpStatusCode": 200,
"responseBody": {"application/json": {"body": json.dumps(result, ensure_ascii=False)}}
  }
 }

def query_order_status(params: dict) -> dict:
 return {
  "order_id": params.get("order_id", ""),
  "status": "shipped",
  "tracking_number": "1234-5678-9012",
  "estimated_delivery": "2024-01-20"
 }

def check_inventory(params: dict) -> dict:
 return {"sku": params.get("sku", ""), "quantity": 42, "restock_date": "2024-02-01"}
</code>

エラーハンドリング: httpStatusCode500 で返すと LLM は「ツール失敗」と解釈しエラーメッセージを生成する。Lambda のタイムアウトは 29 秒以内を推奨 (Bedrock Agents のデフォルトは 30 秒)。

3-4. Action Group 実装フロー

QG-2: Action Group 実装フロー (OpenAPI Schema → Lambda → Function Calling → 結果整形)

以下の 5 ステップが 1 回の Function Calling サイクルを構成する。

  1. Schema 照合・選択 (LLM 内部): LLM はユーザー入力と OpenAPI Schema の各 description を比較し、最も意図に合う operationId を選択する。enableTrace=true の InvocationInput で確認可能。
  2. パラメータ抽出: 選択した operationId の required パラメータが会話中に揃っていなければ、LLM は自動的にユーザーへ追加質問する。揃った時点で次ステップへ進む。
  3. Lambda 呼び出し: Bedrock が Lambda を invoke。event の actionGroupapiPathrequestBody にマッピング済みパラメータを格納して渡す。
  4. 結果整形: Lambda の responseBody.body (JSON 文字列) が LLM のコンテキストに追加される。LLM はこの JSON を解釈し、自然言語の応答を生成する。
  5. 再推論ループ: 1 回の呼び出しで回答が不十分な場合、LLM は別の operationId を選択して再度 Function Calling を実行する (最大ループ数はエージェント設定の max_iterations で制御)。

実装上の注意点: description が曖昧だと LLM の選択精度が低下するため Schema 変更後は必ず Prepare を再実行する。再推論ループで同じ operationId が複数回呼ばれることがあるため Lambda の冪等性を確保する。responseBody.bodyjson.dumps() で直列化した文字列を入れること (dict を直接渡すとパースエラー)。

3-5. Action Group の作成 (3点セット)

Terraform

resource "aws_bedrockagent_agent_action_group" "customer_support" {
  agent_id = aws_bedrockagent_agent.main.id
  agent_version  = "DRAFT"
  action_group_name = "CustomerSupportActions"
  description = "顧客サポート業務向けアクショングループ (注文照会・在庫確認)"

  action_group_executor {
 lambda = aws_lambda_function.customer_support.arn
  }

  api_schema {
 s3 {
s3_bucket_name = aws_s3_bucket.schemas.id
s3_object_key  = "customer-support-api.yaml"
 }
  }

  depends_on = [aws_lambda_permission.bedrock_invoke]
}

# Bedrock Agent が Lambda を Invoke できるよう resource-based policy を付与
resource "aws_lambda_permission" "bedrock_invoke" {
  statement_id  = "AllowBedrockInvoke"
  action  = "lambda:InvokeFunction"
  function_name = aws_lambda_function.customer_support.function_name
  principal  = "bedrock.amazonaws.com"
  source_arn = "${aws_bedrockagent_agent.main.agent_arn}/*"
}
</code>

api_schema は S3 オブジェクト参照とインライン JSON どちらも使える。スキーマサイズが 100 KB を超える場合は S3 参照を選択する。

AWS CLI

# Action Group 作成
aws bedrock-agent create-agent-action-group \
  --agent-id ABCDEFGH12 \
  --agent-version DRAFT \
  --action-group-name CustomerSupportActions \
  --description "顧客サポート業務向けアクショングループ" \
  --action-group-executor \
 '{"lambda":"arn:aws:lambda:us-east-1:123456789012:function:customer-support-handler"}' \
  --api-schema \
 '{"s3":{"s3BucketName":"my-schemas-bucket","s3ObjectKey":"customer-support-api.yaml"}}' \
  --region us-east-1

# Schema 変更後は必ず Prepare を実行
aws bedrock-agent prepare-agent \
  --agent-id ABCDEFGH12 \
  --region us-east-1

# Action Group 一覧確認
aws bedrock-agent list-agent-action-groups \
  --agent-id ABCDEFGH12 \
  --agent-version DRAFT \
  --region us-east-1
</code>

Schema を更新した後は prepare-agent を忘れずに実行する。Prepare しないと古い Schema が有効のままとなり、operationId の選択精度が低下する。

コンソール操作

  1. Bedrock コンソール → 「Agents」→ 対象 Agent → 「Action groups」タブ → 「Create」。
  2. Action group name: CustomerSupportActionsType: 「Define with API schemas」を選択。
  3. Invocation: Lambda 関数 ARN を入力。
  4. Schema: 「Select from S3」(s3://バケット名/customer-support-api.yaml) または「Enter inline schema」。
  5. 「Create」後、Agent ページの「Prepare」ボタンを押して Schema を反映。
  6. 「Test」タブで「注文 ORD-2024-001234 の配送状況は?」と入力して動作確認する。Test ペインでは Function Calling の選択結果もリアルタイム表示される。

4. Knowledge Base 統合 (S3ソース・Embedding・RAG動作)

fig04: Knowledge Base RAG 動作詳細

4-1. Knowledge Base の概要

Knowledge Bases for Amazon Bedrock は、S3 などのデータソースから文書を取り込み、Embedding モデルでベクトル化したうえで Vector Store に格納し、Agent からの Retrieval クエリに対して関連文書を返すマネージドサービスだ。Agent に KNOWLEDGE_BASE タイプのアクションが紐づくと、ユーザーの質問が自動で Knowledge Base に渡り、関連文書を引いたうえで Augmented Prompt として Foundation Model に入力される。

このフローを RAG の文脈で整理すると、以下のコンポーネントが連携する:

コンポーネント役割主要設定
S3 Data Source文書格納 (PDF/TXT/HTML/JSON/DOCX/CSV)バケット ARN・プレフィックス・KMS
Chunking Strategy文書分割方式FIXED_SIZE / SEMANTIC / HIERARCHICAL / NONE
Embedding Modelテキスト→ベクトル変換Titan Embeddings V2 / Cohere Embed Multilingual
Vector Storeベクトル検索エンジンOpenSearch Serverless / Aurora pgvector
Retrieval Config検索件数・スコア閾値numberOfResults / overrideSearchType

Knowledge Base を Agent に紐づけるには、Agent 定義に knowledge_base_iddescription (Knowledge Base をいつ使うかの自然言語説明) を設定する。Agent は Foundation Model の推論で、その質問が Knowledge Base を使うべきか判断し、自動で Retrieval を実行する。

4-2. データソース設定 (S3・ChunkStrategy・Metadata)

S3 バケット設定と IAM 権限

Knowledge Base が S3 からデータを取り込むには、Bedrock Knowledge Base 用 IAM Role に s3:GetObject / s3:ListBucket を付与し、信頼プリンシパルを bedrock.amazonaws.com にする必要がある。

resource "aws_iam_role" "kb_role" {
  name = "bedrock-kb-role"
  assume_role_policy = jsonencode({
 Version = "2012-10-17"
 Statement = [{
Effect = "Allow"
Principal = { Service = "bedrock.amazonaws.com" }
Action = "sts:AssumeRole"
Condition = {
  StringEquals = {
 "aws:SourceAccount" = data.aws_caller_identity.current.account_id
  }
}
 }]
  })
}

resource "aws_iam_role_policy" "kb_s3_policy" {
  role = aws_iam_role.kb_role.id
  policy = jsonencode({
 Version = "2012-10-17"
 Statement = [{
Effect= "Allow"
Action= ["s3:GetObject", "s3:ListBucket"]
Resource = [
  aws_s3_bucket.kb_docs.arn,
  "${aws_s3_bucket.kb_docs.arn}/*"
]
 }]
  })
}
</code>

ChunkStrategy の選び方

戦略特徴推奨ユースケース
FIXED_SIZE固定トークン数で分割 (デフォルト 300 トークン)FAQや均一構造のドキュメント
SEMANTIC意味的まとまりで分割 (Bedrock が自動判定)長文記事・技術ドキュメント
HIERARCHICAL親チャンク+子チャンクの2層構造QA精度重視・コンテキスト保持が必要なケース
NONE分割なし (1ファイル=1チャンク)短いメタデータ文書・コードファイル

日本語ドキュメントでは SEMANTIC または HIERARCHICAL が精度面で優位だ。FIXED_SIZE はトークン境界で意味が途切れるため、日本語の助詞・動詞変化が文脈から切り離されるリスクがある。

Metadata フィルタリング

S3 オブジェクトに {ファイル名}.metadata.json を配置することで、Retrieval 時にメタデータフィルタが使える。

{
  "metadataAttributes": {
 "department": "engineering",
 "doc_type": "runbook",
 "version": "2026-04"
  }
}
</code>

Retrieval 設定で filter 条件を指定すると department = "engineering" の文書のみを検索対象に絞れる。部署ごとに異なる Knowledge Base を立てずに、単一 KB でアクセス制御の代替として機能する。

4-3. Embedding モデル選定

Bedrock Knowledge Base が現在サポートする主要 Embedding モデルは以下のとおり:

モデル ID次元数最大トークン多言語推奨ユースケース
amazon.titan-embed-text-v2:0256 / 512 / 10248,192限定的英語中心・コスト優先
cohere.embed-multilingual-v31,024512100言語+日本語・多言語混在
cohere.embed-english-v31,024512英語のみ英語コンテンツ・高精度

日本語コンテンツを扱う場合は Cohere Embed Multilingual v3 を強く推奨する。 Titan Embeddings V2 は英語優位設計のため、日本語文書の意味的類似度計算精度が Cohere に劣る実績が報告されている。ただし Cohere はトークン上限 512 が制約になるため、長文文書は Chunking Strategy で適切に分割する必要がある。

次元数を小さく設定するとストレージと検索コストを削減できるが精度が下がる。本番では 1,024 次元をデフォルトとし、コスト課題が顕在化した段階で 512 への縮退を検討する。

4-4. Vector Store 選定

OpenSearch Serverless (主軸・AWS マネージド統合)

AWS マネージドで Bedrock との統合が最もシームレスな選択肢。容量プランニング不要で KB 作成時に自動プロビジョニングされる。データアクセスポリシーに KB Role ARN を追加することが必須で、これを忘れると Ingestion Job が 403 で失敗する。

コスト感: 最低 2 OCU (indexing 1 + search 1) で月約 $345 が発生する。小規模プロトタイプでは Aurora pgvector に比べてコストが高くなる点に注意が必要だ。

Aurora pgvector (コスト最適化代替)

既存 Aurora PostgreSQL クラスターに pgvector 拡張を有効化して Vector Store として利用するパターン。RDS 費用に加算される追加コストがなく、既存 DB インフラを流用したい場合に有効だ。Bedrock Knowledge Base の設定では storageConfiguration.type = "RDS" を指定し、DB クラスター ARN・テーブル名・認証情報 (Secrets Manager ARN) を提供する。

比較軸OpenSearch ServerlessAurora pgvector
セットアップ難易度低 (Bedrock が自動作成)中 (pgvector 拡張有効化・テーブル作成が必要)
コスト (最小)~$345/月 (2 OCU)~$30/月 (既存 Aurora 流用)
スケーラビリティ自動スケールAurora Auto Scaling 手動設定
既存インフラ流用不可
推奨シーン新規プロジェクト・本番大規模コスト最適化・既存 Aurora 保有環境

4-5. RAG 動作詳細

QG-3: Knowledge Base RAG 動作フロー (S3 → Vector Store → Augmented Generation)

Knowledge Base 統合の全フローは取り込みフェーズと検索フェーズの2段階に分かれる。

取り込みフェーズ (Ingestion Job):
1. S3 からドキュメントを取得 → テキスト抽出 (PDF/DOCX/HTML/TXT/JSON/CSV 対応)
2. ChunkStrategy に従って文書を分割 (SEMANTIC / FIXED_SIZE / HIERARCHICAL)
3. Embedding モデル (Titan Embeddings V2 または Cohere Embed Multilingual) でベクトル化
4. Vector Store (OpenSearch Serverless / Aurora pgvector) にインデックスとして格納
5. Ingestion Job ステータスが COMPLETE に移行

検索フェーズ (Retrieval + Augmented Generation):
1. ユーザー入力を Agent が受け取り、Knowledge Base への Retrieval クエリを生成
2. Embedding モデルでクエリテキストをベクトル化
3. Vector Store でコサイン類似度 / ドット積で上位 N 件を取得 (numberOfResults 設定値)
4. 取得チャンクを Augmented Prompt としてシステムプロンプトに注入
5. Foundation Model が文脈付きで応答生成 → 引用ソース (S3 URI) 付きでユーザーに返却

KB sync のよくある失敗パターン:

  • S3権限不足: KB Role に s3:GetObject / s3:ListBucket がない → AccessDenied で Ingestion Job が FAILED になる
  • Embedding quota 超過: ドキュメント数が多い場合、Embedding API の RateLimit に当たる → バッチサイズを小さくして再 sync
  • Vector Store 接続エラー: OpenSearch Serverless のデータアクセスポリシーに KB Role ARN が未追加 → 403 エラーで全 Ingestion Job が失敗
  • 大きなファイルで ChunkStrategy = NONE: 1チャンクのトークン数が Embedding モデル上限を超える → FIXED_SIZE (500 トークン) または SEMANTIC に変更

4-6. 3点セット: Knowledge Base 構築・操作

Terraform

resource "aws_bedrockagent_knowledge_base" "main" {
  name  = "production-kb"
  role_arn = aws_iam_role.kb_role.arn

  knowledge_base_configuration {
 type = "VECTOR"
 vector_knowledge_base_configuration {
embedding_model_arn = "arn:aws:bedrock:us-east-1::foundation-model/cohere.embed-multilingual-v3"
 }
  }

  storage_configuration {
 type = "OPENSEARCH_SERVERLESS"
 opensearch_serverless_configuration {
collection_arn = aws_opensearchserverless_collection.kb_collection.arn
vector_index_name = "bedrock-kb-index"
field_mapping {
  vector_field= "embedding"
  text_field  = "AMAZON_BEDROCK_TEXT_CHUNK"
  metadata_field = "AMAZON_BEDROCK_METADATA"
}
 }
  }
}

resource "aws_bedrockagent_data_source" "s3_source" {
  knowledge_base_id = aws_bedrockagent_knowledge_base.main.id
  name  = "s3-docs-source"

  data_source_configuration {
 type = "S3"
 s3_configuration {
bucket_arn = aws_s3_bucket.kb_docs.arn
 }
  }

  vector_ingestion_configuration {
 chunking_configuration {
chunking_strategy = "SEMANTIC"
 }
  }
}
</code>

AWS CLI

# Knowledge Base 作成状態確認
aws bedrock-agent get-knowledge-base \
  --knowledge-base-id kb-XXXXXXXXXX \
  --query "knowledgeBase.{status:status,name:name}" \
  --output json

# データソース同期 (Ingestion Job 開始)
aws bedrock-agent start-ingestion-job \
  --knowledge-base-id kb-XXXXXXXXXX \
  --data-source-id ds-XXXXXXXXXX

# Ingestion Job ステータス確認
aws bedrock-agent get-ingestion-job \
  --knowledge-base-id kb-XXXXXXXXXX \
  --data-source-id ds-XXXXXXXXXX \
  --ingestion-job-id ij-XXXXXXXXXX \
  --query "ingestionJob.{status:status,statistics:statistics}"

# Knowledge Base への直接クエリ (動作確認用)
aws bedrock-agent-runtime retrieve \
  --knowledge-base-id kb-XXXXXXXXXX \
  --retrieval-query '{"text": "Lambda のタイムアウト設定方法"}' \
  --retrieval-configuration '{"vectorSearchConfiguration":{"numberOfResults":5}}' \
  --query "retrievalResults[].content.text"
</code>

コンソール手順

  1. Amazon BedrockKnowledge BasesCreate knowledge base
  2. 名前・説明・IAM Role を入力し、データソースに Amazon S3 を選択
  3. S3 バケット URI を指定し、ChunkingStrategy を Semantic chunking に設定
  4. Embedding モデルに Cohere Embed Multilingual v3 を選択
  5. Vector Store に Quick create new vector store (OpenSearch Serverless) を選択
  6. レビュー画面で内容確認後 Create knowledge base を実行
  7. 作成完了後、Sync ボタンで Ingestion Job を手動起動
  8. Test Knowledge Base 画面でクエリを入力し、Retrieval 結果とスコアを確認

5. セッション管理 + メモリ (multi-turn 会話・SessionAttributes)

fig05: セッション+SessionAttributes ライフサイクル

5-1. sessionId の概念

Bedrock Agents の invoke_agent API は sessionId パラメータで会話の連続性を管理する。同一 sessionId で複数回呼び出すと、Agent は過去の会話履歴 (ターン) を参照して応答を生成する multi-turn 会話が成立する。

項目詳細
sessionId の形式任意文字列 (最大 100 文字)。UUID v4 推奨
TTL (Session Idle Timeout)デフォルト 1800 秒 (30 分)。設定範囲: 60〜3600 秒
会話履歴の保持Bedrock Agent 側で自動管理。クライアントはメモリ不要
セッション終了方法endSession: true フラグを最後の invoke_agent に渡す

sessionId の設計指針

  • ユーザー ID + 会話 ID の組み合わせ ({user_id}_{conversation_id}) を sessionId に使うと、マルチユーザー環境でのセッション衝突を防げる
  • TTL を短くしすぎると会話途中でセッションが切れるため、業務シナリオのターン数×応答時間に余裕を持たせる
  • セッションが切れても同一 sessionId で再接続すると新セッション扱いになる。継続会話が必要な場合はフロントエンドで切れた旨を検知してユーザーに通知する

5-2. SessionAttributes

sessionAttributes は、Agent の Lambda Function (Action Group ハンドラ) にユーザー属性を渡す仕組みだ。invoke_agent のリクエストボディに含め、Lambda の event オブジェクトの sessionAttributes キーで参照できる。

# Lambda Handler での sessionAttributes 参照例
def handler(event, context):
 session_attrs = event.get("sessionAttributes", {})
 user_id = session_attrs.get("userId", "anonymous")
 user_role = session_attrs.get("role", "viewer")

 # ユーザー属性に基づいてアクセス制御
 if user_role != "admin" and event["function"] == "delete_record":
  return {
"actionGroup": event["actionGroup"],
"function": event["function"],
"functionResponse": {
 "responseBody": {
  "TEXT": {"body": "削除権限がありません。管理者にお問い合わせください。"}
 }
}
  }
 # 通常処理...
</code>

sessionAttributes の主な用途:

用途具体例
ユーザー識別userId, email, employeeId
アクセス制御role = "admin" / role = "viewer"
テナント分離tenantId, organization
ロケール設定locale = "ja-JP", timezone = "Asia/Tokyo"

重要: sessionAttributes はセッション全体で共有され、各ターンのリクエストで上書き可能だ。機密情報 (パスワード・トークン) は含めず、認可・識別情報のみを渡すこと。

5-3. promptSessionAttributes

promptSessionAttributes は、Agent のシステムプロンプトに変数として展開される仕組みだ。Agent 定義の instruction フィールドに {{variableName}} 形式のプレースホルダーを記述し、invoke_agent 時に値を渡すと動的に置換される。

# Agent instruction フィールドの設定例 (コンソール / Terraform の instruction)
あなたは {{company_name}} の {{department}} 部門向けサポートエージェントです。
ユーザーの契約プランは {{plan_type}} です。機能制限に従って回答してください。
</code>
# boto3 での promptSessionAttributes 渡し方
import boto3
import uuid

bedrock_rt = boto3.client("bedrock-agent-runtime", region_name="us-east-1")

response = bedrock_rt.invoke_agent(
 agentId="AGENTXXXXXXXX",
 agentAliasId="AAAXXXXXXXXX",
 sessionId=str(uuid.uuid4()),
 inputText="現在の利用状況を教えてください",
 sessionState={
  "sessionAttributes": {
"userId": "user-12345",
"role": "admin"
  },
  "promptSessionAttributes": {
"company_name": "株式会社サンプル",
"department": "インフラ",
"plan_type": "Enterprise"
  }
 }
)
</code>

sessionAttributespromptSessionAttributes の違いを整理すると:

  • sessionAttributes → Lambda (Action Group ハンドラ) が参照。コード側での条件分岐に使う
  • promptSessionAttributes → Foundation Model へのプロンプト内で展開。モデルの応答スタイル・制約の動的設定に使う

5-4. セッション管理の使い分け

QG-4: セッション管理 3要素の使い分け早見表

パラメータ渡し先使い分け基準典型的な値
sessionIdBedrock Agent セッション管理会話の継続性を保持したい場合。ターン間で同一値を渡す。user-123_conv-456 / UUID v4
sessionAttributesLambda (Action Group ハンドラ) の eventLambda でユーザー識別・アクセス制御・テナント分離が必要な場合。コードロジックに関わる属性。{"userId": "u-123", "role": "admin"}
promptSessionAttributesAgent instruction の {{変数}} プレースホルダーモデルへのシステムプロンプトを動的にカスタマイズしたい場合。応答スタイル・制約の動的設定。{"company_name": "株式会社X", "plan_type": "Enterprise"}

設計判断フロー:

  1. 「この属性は Lambda のコードロジックで使うか?」→ YES → sessionAttributes
  2. 「この属性は Foundation Model のプロンプト動作を変えるか?」→ YES → promptSessionAttributes
  3. 「どちらでもない。会話の継続だけしたい」→ sessionId を統一するだけで OK

よくある誤用:

  • sessionAttributes に機密情報 (API キー・パスワード) を入れる → CloudTrail に平文で記録されるため NG。Secrets Manager を使う。
  • promptSessionAttributes に外部入力をそのまま渡す → プロンプトインジェクション攻撃のリスク。バリデーション・エスケープ処理を必ず実施する。
  • sessionId を毎回新規生成する → multi-turn 会話が成立しない。フロントエンドで sessionId を保持する設計にする。

5-5. Memory feature (プレビュー段階)

Bedrock Agents には、セッションをまたいで会話コンテキストを保持する Memory feature がプレビュー段階で提供されている (2026-04時点)。通常の sessionId ベース管理がセッション内のみの履歴保持であるのに対し、Memory は別セッションの過去会話を Agent が参照できる。

有効化方法 (Terraform)

resource "aws_bedrockagent_agent" "main" {
  # ... (他のフィールドは省略)

  memory_configuration {
 enabled_memory_types = ["SESSION_SUMMARY"]
 storage_days= 30
  }
}
</code>

Memory feature の主な制約 (プレビュー段階)

項目詳細
利用可能リージョンus-east-1 / us-west-2 のみ (2026-04時点)
enabledMemoryTypesSESSION_SUMMARY のみサポート (会話サマリを保存)
storageDays7〜365 日
利用料金追加料金あり (公式料金ページ参照)
GA 時期未定 (本番運用は慎重に評価すること)

Memory feature はプレビューのため、本番環境での採用は GA 後に仕様・料金が固まってから判断することを推奨する。

5-6. 3点セット: セッション管理・操作

Terraform

resource "aws_bedrockagent_agent" "main" {
  agent_name  = "production-agent"
  agent_resource_role_arn = aws_iam_role.agent_role.arn
  foundation_model  = "anthropic.claude-3-5-sonnet-20241022-v2:0"
  idle_session_ttl_in_seconds = 1800

  instruction = <<-EOT
 あなたは {{company_name}} のサポートエージェントです。
 {{department}} 部門向けに応答してください。
 ユーザーのプランは {{plan_type}} です。
  EOT

  # Memory feature (プレビュー段階 - 本番利用は GA 後に改めて評価する)
  # memory_configuration {
  #enabled_memory_types = ["SESSION_SUMMARY"]
  #storage_days= 30
  # }
}
</code>

AWS CLI (invoke-agent)

# セッション ID を固定して multi-turn 会話を開始
SESSION_ID="user-12345-$(date +%s)"

# 1ターン目
aws bedrock-agent-runtime invoke-agent \
  --agent-id AGENTXXXXXXXX \
  --agent-alias-id AAAXXXXXXXXX \
  --session-id "${SESSION_ID}" \
  --input-text "今日の予約状況を教えてください" \
  --session-state '{
 "sessionAttributes": {"userId": "user-12345", "role": "admin"},
 "promptSessionAttributes": {
"company_name": "株式会社サンプル",
"department": "インフラ",
"plan_type": "Enterprise"
 }
  }' \
  outfile=/dev/stdout

# 2ターン目 (同一 sessionId で継続)
aws bedrock-agent-runtime invoke-agent \
  --agent-id AGENTXXXXXXXX \
  --agent-alias-id AAAXXXXXXXXX \
  --session-id "${SESSION_ID}" \
  --input-text "では14時の予約をキャンセルしてください" \
  outfile=/dev/stdout

# セッション終了 (endSession フラグ)
aws bedrock-agent-runtime invoke-agent \
  --agent-id AGENTXXXXXXXX \
  --agent-alias-id AAAXXXXXXXXX \
  --session-id "${SESSION_ID}" \
  --input-text "ありがとう" \
  --end-session \
  outfile=/dev/stdout
</code>

コンソール手順

  1. Amazon BedrockAgents → 対象エージェントを選択
  2. Test タブ → Test agent ボタンでテストウィンドウを開く
  3. テストウィンドウ内の Session attributes セクションで sessionAttributes / promptSessionAttributes を key-value 形式で入力
  4. チャット入力欄にメッセージを入力し Run → 応答を確認
  5. 同一セッションで会話を続けて multi-turn 動作を確認
  6. View trace で各ターンの推論フロー (Knowledge Base クエリ・Action Group 呼び出し) を可視化

6. Terraform 実装 (Agent + Action Group + KB + IAM 完全 HCL)

Bedrock Agents の全コンポーネントを Terraform で管理することで、環境間の再現性と差分管理が保証される。本節では aws_bedrockagent_* リソース群を完全 HCL で実装し、IAM 設計・Agent Alias バージョニングまでワンセットで示す。

6-1. Terraform Provider 設定

hashicorp/aws v5.x 以降で aws_bedrockagent_* リソースが安定リリースされた。versions.tfvariables.tf を整備してから各リソースを定義する。

# versions.tf
terraform {
  required_version = ">= 1.9.0"

  required_providers {
 aws = {
source  = "hashicorp/aws"
version = "~> 5.50"
 }
  }
}

provider "aws" {
  region = var.aws_region
}
</code>
# variables.tf
variable "aws_region" {
  description = "デプロイ先リージョン (Bedrock 対応リージョン必須)"
  type  = string
  default  = "us-east-1"
}

variable "env" {
  description = "環境識別子 (dev / stg / prod)"
  type  = string
  default  = "dev"
}

variable "project" {
  description = "プロジェクト識別子"
  type  = string
  default  = "my-agent"
}

variable "foundation_model" {
  description = "Bedrock Agent が使用する Foundation Model ID"
  type  = string
  default  = "anthropic.claude-3-5-sonnet-20241022-v2:0"
}

variable "lambda_arn" {
  description = "Action Group が呼び出す Lambda 関数 ARN"
  type  = string
}

variable "kb_s3_bucket" {
  description = "Knowledge Base のデータソース S3 バケット名"
  type  = string
}

variable "api_schema_s3_bucket" {
  description = "OpenAPI Schema を格納する S3 バケット名"
  type  = string
}

variable "api_schema_s3_key" {
  description = "OpenAPI Schema の S3 オブジェクトキー"
  type  = string
  default  = "schemas/agent-api.json"
}
</code>

6-2. aws_bedrockagent_agent 完全 HCL

instruction フィールドは Agent の行動指針を LLM に与えるプロンプト相当であり、具体的・明示的に記述するほど挙動が安定する。

# agent.tf

locals {
  agent_name = "${var.project}-agent-${var.env}"
}

resource "aws_bedrockagent_agent" "main" {
  agent_name  = local.agent_name
  agent_resource_role_arn = aws_iam_role.bedrock_agent.arn
  foundation_model  = var.foundation_model
  description = "本番向け Bedrock Agent (${var.env} 環境)"

  instruction = <<-EOT
 あなたは社内ナレッジ検索と外部 API 連携を担う AI アシスタントです。
 ユーザーの質問に対し、Knowledge Base を参照して社内情報を回答します。
 外部サービスへのアクセスが必要な場合は Action Group の関数を呼び出してください。
 回答は日本語で行い、情報源を明示してください。
  EOT

  idle_session_ttl_in_seconds = 1800

  prepare_agent = true

  tags = {
 Environment = var.env
 Project  = var.project
 ManagedBy= "terraform"
  }
}
</code>

ポイント: prepare_agent = true を設定すると Terraform apply 後に自動的に Agent が PREPARED 状態になる。false のまま Alias を作成すると ConflictException: Agent is in CREATING state が発生するため必須。


6-3. aws_bedrockagent_agent_action_group

Action Group は Agent が呼び出せるツール群を定義する。api_schema を S3 経由で指定するのが推奨パターン。

# action_group.tf

resource "aws_bedrockagent_agent_action_group" "main" {
  agent_id = aws_bedrockagent_agent.main.id
  agent_version  = "DRAFT"
  action_group_name = "${var.project}-actions-${var.env}"
  description = "外部 API 連携アクションセット"

  action_group_executor {
 lambda = var.lambda_arn
  }

  api_schema {
 s3 {
s3_bucket_name = var.api_schema_s3_bucket
s3_object_key  = var.api_schema_s3_key
 }
  }

  action_group_state = "ENABLED"

  depends_on = [aws_bedrockagent_agent.main]
}
</code>

OpenAPI Schema は Terraform でアップロードも管理できる。

# schema_upload.tf

resource "aws_s3_object" "api_schema" {
  bucket = var.api_schema_s3_bucket
  key = var.api_schema_s3_key
  content_type = "application/json"

  content = jsonencode({
 openapi = "3.0.0"
 info = {
title= "Agent Actions API"
version = "1.0.0"
 }
 paths = {
"/search-external" = {
  get = {
 operationId = "searchExternal"
 description = "外部データソースを検索してリアルタイム情報を取得する"
 parameters = [
{
  name  = "query"
  in = "query"
  required = true
  description = "検索クエリ文字列"
  schema= { type = "string" }
}
 ]
 responses = {
"200" = {
  description = "検索結果"
  content = {
 "application/json" = {
schema = {
  type = "object"
  properties = {
 results = {
type  = "array"
items = { type = "string" }
 }
  }
}
 }
  }
}
 }
  }
}
 }
  })
}
</code>

6-4. aws_bedrockagent_knowledge_base + aws_bedrockagent_data_source

Knowledge Base には OpenSearch Serverless をベクトルストアとして使用する。embedding_model_arn には Bedrock が提供する Titan Embed v2 を指定する。

# knowledge_base.tf

data "aws_caller_identity" "current" {}

locals {
  kb_name = "${var.project}-kb-${var.env}"
}

resource "aws_bedrockagent_knowledge_base" "main" {
  name  = local.kb_name
  description = "社内ドキュメント用 Knowledge Base"
  role_arn = aws_iam_role.bedrock_kb.arn

  knowledge_base_configuration {
 type = "VECTOR"

 vector_knowledge_base_configuration {
embedding_model_arn = "arn:aws:bedrock:${var.aws_region}::foundation-model/amazon.titan-embed-text-v2:0"
 }
  }

  storage_configuration {
 type = "OPENSEARCH_SERVERLESS"

 opensearch_serverless_configuration {
collection_arn = aws_opensearchserverless_collection.kb.arn
vector_index_name = "bedrock-kb-index"

field_mapping {
  vector_field= "bedrock-knowledge-base-default-vector"
  text_field  = "AMAZON_BEDROCK_TEXT_CHUNK"
  metadata_field = "AMAZON_BEDROCK_METADATA"
}
 }
  }

  tags = {
 Environment = var.env
 Project  = var.project
 ManagedBy= "terraform"
  }
}

resource "aws_bedrockagent_data_source" "s3" {
  knowledge_base_id = aws_bedrockagent_knowledge_base.main.id
  name  = "${var.project}-s3-datasource-${var.env}"
  description = "S3 バケットからドキュメントを取得"

  data_source_configuration {
 type = "S3"

 s3_configuration {
bucket_arn = "arn:aws:s3:::${var.kb_s3_bucket}"
 }
  }

  vector_ingestion_configuration {
 chunking_configuration {
chunking_strategy = "FIXED_SIZE"

fixed_size_chunking_configuration {
  max_tokens= 512
  overlap_percentage = 20
}
 }
  }
}

resource "aws_bedrockagent_agent_knowledge_base_association" "main" {
  agent_id = aws_bedrockagent_agent.main.id
  agent_version  = "DRAFT"
  knowledge_base_id = aws_bedrockagent_knowledge_base.main.id
  description = "社内文書検索用 Knowledge Base"
  knowledge_base_state = "ENABLED"
}
</code>

データソース Sync は CLI で手動実行する。

# データソース同期ジョブ開始
aws bedrock-agent start-ingestion-job \
  --knowledge-base-id "$(terraform output -raw knowledge_base_id)" \
  --data-source-id "$(terraform output -raw data_source_id)" \
  --region us-east-1

# Sync 状態確認
aws bedrock-agent get-ingestion-job \
  --knowledge-base-id "$(terraform output -raw knowledge_base_id)" \
  --data-source-id "$(terraform output -raw data_source_id)" \
  --ingestion-job-id <JOB_ID> \
  --region us-east-1 \
  --query 'ingestionJob.{status:status,failureReasons:failureReasons}'
</code>

6-5. IAM 設計 (iam:PassRole + bedrock.amazonaws.com AssumeRole + Lambda Permission)

Bedrock Agents の IAM 設計は 4 層構造 になる。各権限の欠落が最も多いトラブル原因。

ロール / ポリシー主要権限
層1Bedrock Agent 実行ロールbedrock:InvokeModel / lambda:InvokeFunction / bedrock:Retrieve / s3:GetObject
層2Knowledge Base 実行ロールs3:GetObject / aoss:APIAccessAll / bedrock:InvokeModel (Embedding)
層3Lambda Resource Policylambda:InvokeFunction (Principal: bedrock.amazonaws.com)
層4デプロイ主体ロールiam:PassRole (Agent ロール・KB ロールの PassRole 権限)
# iam.tf

# ── 層1: Bedrock Agent 実行ロール ──────────────────────────────────

resource "aws_iam_role" "bedrock_agent" {
  name = "${var.project}-bedrock-agent-role-${var.env}"

  assume_role_policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Effect = "Allow"
  Principal = { Service = "bedrock.amazonaws.com" }
  Action = "sts:AssumeRole"
  Condition = {
 StringEquals = {
"aws:SourceAccount" = data.aws_caller_identity.current.account_id
 }
 ArnLike = {
"aws:SourceArn" = "arn:aws:bedrock:${var.aws_region}:${data.aws_caller_identity.current.account_id}:agent/*"
 }
  }
}
 ]
  })

  tags = { Environment = var.env, Project = var.project }
}

resource "aws_iam_role_policy" "bedrock_agent_policy" {
  name = "${var.project}-bedrock-agent-policy"
  role = aws_iam_role.bedrock_agent.id

  policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Sid= "InvokeFoundationModel"
  Effect= "Allow"
  Action= ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream"]
  Resource = "arn:aws:bedrock:${var.aws_region}::foundation-model/${var.foundation_model}"
},
{
  Sid= "InvokeLambda"
  Effect= "Allow"
  Action= ["lambda:InvokeFunction"]
  Resource = var.lambda_arn
},
{
  Sid= "RetrieveKnowledgeBase"
  Effect= "Allow"
  Action= ["bedrock:Retrieve", "bedrock:RetrieveAndGenerate"]
  Resource = aws_bedrockagent_knowledge_base.main.arn
},
{
  Sid= "ReadApiSchema"
  Effect= "Allow"
  Action= ["s3:GetObject"]
  Resource = "arn:aws:s3:::${var.api_schema_s3_bucket}/${var.api_schema_s3_key}"
}
 ]
  })
}

# ── 層2: Knowledge Base 実行ロール ─────────────────────────────────

resource "aws_iam_role" "bedrock_kb" {
  name = "${var.project}-bedrock-kb-role-${var.env}"

  assume_role_policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Effect = "Allow"
  Principal = { Service = "bedrock.amazonaws.com" }
  Action = "sts:AssumeRole"
  Condition = {
 StringEquals = {
"aws:SourceAccount" = data.aws_caller_identity.current.account_id
 }
  }
}
 ]
  })
}

resource "aws_iam_role_policy" "bedrock_kb_policy" {
  name = "${var.project}-bedrock-kb-policy"
  role = aws_iam_role.bedrock_kb.id

  policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Sid= "ReadS3DataSource"
  Effect= "Allow"
  Action= ["s3:GetObject", "s3:ListBucket"]
  Resource = ["arn:aws:s3:::${var.kb_s3_bucket}", "arn:aws:s3:::${var.kb_s3_bucket}/*"]
},
{
  Sid= "OpenSearchServerlessAccess"
  Effect= "Allow"
  Action= ["aoss:APIAccessAll"]
  Resource = aws_opensearchserverless_collection.kb.arn
},
{
  Sid= "InvokeEmbeddingModel"
  Effect= "Allow"
  Action= ["bedrock:InvokeModel"]
  Resource = "arn:aws:bedrock:${var.aws_region}::foundation-model/amazon.titan-embed-text-v2:0"
}
 ]
  })
}

# ── 層3: Lambda Resource Policy ────────────────────────────────────

resource "aws_lambda_permission" "bedrock_agent_invoke" {
  statement_id  = "AllowBedrockAgentInvoke"
  action  = "lambda:InvokeFunction"
  function_name = var.lambda_arn
  principal  = "bedrock.amazonaws.com"
  source_arn = "arn:aws:bedrock:${var.aws_region}:${data.aws_caller_identity.current.account_id}:agent/${aws_bedrockagent_agent.main.id}"
}
</code>

iam:PassRole について: Bedrock Agent 作成時に iam:PassRole が必要なのは Terraform や CLI を実行するデプロイ主体 IAM エンティティ側。Agent 実行ロール自体には iam:PassRole は不要。混同しやすいため注意。


6-6. Agent Alias + バージョニング

DRAFT は開発用。本番呼び出しには必ず明示的な Alias を作成して固定する。

# alias.tf

resource "aws_bedrockagent_agent_alias" "prod" {
  agent_id= aws_bedrockagent_agent.main.id
  agent_alias_name = "prod"
  description= "本番用 Alias"

  routing_configuration {
 agent_version = aws_bedrockagent_agent.main.agent_version
  }

  tags = {
 Environment = var.env
 Project  = var.project
  }
}

output "agent_id" {
  value = aws_bedrockagent_agent.main.id
  description = "Bedrock Agent ID"
}

output "agent_alias_id" {
  value = aws_bedrockagent_agent_alias.prod.agent_alias_id
  description = "本番用 Agent Alias ID"
}
</code>

CLI で Agent を呼び出す際は Terraform output から Alias ID を取得する。

# Agent 呼び出し (ストリーミングなし)
aws bedrock-agent-runtime invoke-agent \
  --agent-id "$(terraform output -raw agent_id)" \
  --agent-alias-id "$(terraform output -raw agent_alias_id)" \
  --session-id "session-$(date +%s)" \
  --input-text "東京オフィスの会議室予約手順を教えてください" \
  --region us-east-1 \
  output.json && cat output.json
</code>

コンソールでは Bedrock → Agents → [エージェント名] → Aliases から Alias を確認できる。「Test」ボタンでチャット形式の動作確認も可能。


6-7. Terraform 実装の落とし穴 4選

落とし穴4選: Terraform で Bedrock Agents をハマらずに構築するために

  • 落とし穴1: IAM 信頼関係の欠落 → Agent ロールが引き受けられない
  • 落とし穴2: KB sync 権限 (aoss:APIAccessAll) の未設定 → Ingestion job 失敗
  • 落とし穴3: Lambda Resource Policy の欠落 → Action Group 呼び出し拒否
  • 落とし穴4: DRAFT Alias のまま本番呼び出し → リビジョン不整合

落とし穴1: IAM 信頼関係 (bedrock.amazonaws.com AssumeRole 欠落)

エラーメッセージ:

An error occurred (AccessDeniedException) when calling the CreateAgent operation:
User: arn:aws:sts::123456789012:assumed-role/... is not authorized to perform:
iam:PassRole on resource: arn:aws:iam::123456789012:role/my-agent-bedrock-agent-role-prod
</code>

原因: Agent ロールの assume_role_policybedrock.amazonaws.com を追加し忘れ、または Conditionaws:SourceAccount に誤ったアカウント ID を設定している。

対処法: assume_role_policy の Principal を "Service": "bedrock.amazonaws.com" とし、Condition の aws:SourceAccountdata.aws_caller_identity.current.account_id を参照させる (6-5 の HCL 参照)。aws:SourceArnagent/* ワイルドカードで新規 Agent にも自動適用される。


落とし穴2: KB sync 権限 (aoss:APIAccessAll) の欠落

エラーメッセージ:

ValidationException: No access policy found for collection arn:aws:aoss:...
ResourceNotFoundException: The Knowledge Base sync job failed.
Status: FAILED, Reason: OPENSEARCH_ACCESS_DENIED
</code>

原因: Knowledge Base ロールに aoss:APIAccessAll を付与していない、または OpenSearch Serverless の Data Access Policy で対象ロールが許可されていない。IAM ポリシーだけでは不十分で、コレクション側の Data Access Policy も必要。

対処法: KB ロールポリシーに aoss:APIAccessAll を追加した上で、OpenSearch Serverless コレクションの Data Access Policy にも KB ロール ARN を明示的に許可する。

resource "aws_opensearchserverless_access_policy" "kb_data" {
  name  = "${var.project}-kb-data-access-${var.env}"
  type  = "data"
  description = "Knowledge Base ロールへのベクトル操作権限"

  policy = jsonencode([
 {
Rules = [
  {
 ResourceType = "index"
 Resource  = ["index/${aws_opensearchserverless_collection.kb.name}/*"]
 Permission= [
"aoss:CreateIndex",
"aoss:WriteDocument",
"aoss:ReadDocument",
"aoss:DescribeIndex",
"aoss:UpdateIndex"
 ]
  }
]
Principal = [aws_iam_role.bedrock_kb.arn]
 }
  ])
}
</code>

落とし穴3: Lambda Resource Policy (bedrock.amazonaws.com invocation 許可欠落)

エラーメッセージ:

The provided execution role does not have permissions to call InvokeFunction on Lambda.
ResourceConflictException: The action group executor Lambda function could not be invoked.
</code>

原因: Lambda 側の Resource Policy に bedrock.amazonaws.com からの Invoke を許可していない。Agent 実行ロールの IAM Policy に lambda:InvokeFunction を付与するだけでは不十分。IAM ポリシー (Identity-based) + Lambda Resource Policy (Resource-based) の両方が必要

対処法: aws_lambda_permission リソースで principal = "bedrock.amazonaws.com" を設定し、source_arn に Agent ARN を指定する (6-5 参照)。source_arn を省略すると全 Agent から呼び出せる過剰な権限になるため Agent ARN を明示する。


落とし穴4: DRAFT Alias のまま本番呼び出し (バージョニング不整合)

エラーメッセージ:

ConflictException: Agent is in CREATING state and cannot be invoked.
AgentAliasNotFoundException: The specified agent alias TSTALIASID does not exist.
</code>

原因: aws_bedrockagent_agent_alias を作成せず、コンソールのテスト用 TSTALIASID を本番スクリプトにハードコードしている。または prepare_agent = false のまま Alias を作成し、Agent が PREPARED 状態になっていない。

対処法:
1. prepare_agent = true で Agent を PREPARED 状態にする
2. aws_bedrockagent_agent_alias で明示的な本番 Alias を作成する
3. 呼び出し時は terraform output -raw agent_alias_id で取得した ID を使用する

# NG: コンソールのテスト用 Alias をそのまま使用
aws bedrock-agent-runtime invoke-agent \
  --agent-alias-id "TSTALIASID" ...

# OK: Terraform で作成した本番 Alias を参照
ALIAS_ID=$(terraform output -raw agent_alias_id)
aws bedrock-agent-runtime invoke-agent \
  --agent-id "$(terraform output -raw agent_id)" \
  --agent-alias-id "$ALIAS_ID" \
  --session-id "session-$(date +%s)" \
  --input-text "テスト入力" \
  --region us-east-1 \
  output.json
</code>

7. 観測性 + ガードレール (CloudWatch Logs/Metrics/Trace + Bedrock Guardrails)

本番運用において観測性とセキュリティは不可欠な2軸だ。Agent の推論フローを CloudWatch Logs/Metrics/Trace で可視化し、Bedrock Guardrails で PII 漏洩・禁止トピック・Prompt Attack を防御する構成を解説する。

7-1. CloudWatch Logs 設定

Bedrock Agents の CloudWatch Logs には Agent Invocation LogsLambda Logs (Action Group) の 2 種類がある。

Agent Invocation Logs は Agent コンソール → Edit → Advanced settings → Logging から有効化する。ログは /aws/bedrock/agents/{agent_id} に出力される。

# Terraform: ログ格納 Log Group
resource "aws_cloudwatch_log_group" "bedrock_agent" {
  name  = "/aws/bedrock/agents/${var.agent_name}"
  retention_in_days = 30

  tags = var.tags
}

# ※ aws_bedrockagent_agent の logging_configuration は 2026-04 現在 Terraform 未対応
# コンソールまたは boto3 で手動設定が必要 (§7-6 落とし穴#1 参照)
</code>

Lambda Logs は Action Group の Lambda 関数がデフォルトで /aws/lambda/{function_name} に出力する。本番では logger.setLevel(logging.INFO) + json.dumps() 形式で構造化ログ出力し、CloudWatch Logs Insights でクエリできる形式にする。

AWS CLI:

# Agent Invocation ログの最新10件
aws logs filter-log-events \
  --log-group-name "/aws/bedrock/agents/${AGENT_NAME}" \
  --limit 10 \
  --region us-east-1

# Lambda ログストリーム一覧
aws logs describe-log-streams \
  --log-group-name "/aws/lambda/bedrock-agent-action-group" \
  --order-by LastEventTime --descending \
  --limit 5
</code>

コンソール: Bedrock → Agents → [エージェント名] → Edit → Advanced settings → Logging → CloudWatch Logs を有効化。

7-2. CloudWatch Metrics

主要 Metrics と推奨アラーム設定:

MetricNamespaceディメンション用途
InvocationCountAWS/BedrockAgentId呼び出し回数トレンド
InvocationThrottlesAWS/BedrockAgentIdスロットリング検知
InvocationLatencyAWS/BedrockAgentIdレイテンシ劣化検知
KnowledgeBaseRetrievalLatencyAWS/BedrockKnowledgeBaseIdKB 検索遅延
ErrorsAWS/BedrockAgentIdエラー率監視
# Terraform: スロットリングアラーム
resource "aws_cloudwatch_metric_alarm" "agent_throttles" {
  alarm_name = "${var.agent_name}-throttles"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2
  metric_name= "InvocationThrottles"
  namespace  = "AWS/Bedrock"
  period  = 60
  statistic  = "Sum"
  threshold  = 5
  alarm_actions = [aws_sns_topic.alerts.arn]

  dimensions = {
 AgentId = aws_bedrockagent_agent.main.agent_id
  }
}
}
</code>

AWS CLI (過去1時間のスロットリング確認):

aws cloudwatch get-metric-statistics \
  --namespace AWS/Bedrock \
  --metric-name InvocationThrottles \
  --start-time "$(date -u -v-1H +%Y-%m-%dT%H:%M:%SZ)" \
  --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  --period 3600 \
  --statistics Sum \
  --dimensions Name=AgentId,Value="${AGENT_ID}" \
  --region us-east-1
</code>

7-3. Trace API (enableTrace)

Agent 呼び出し時に enableTrace=True を設定すると、推論フロー全体を Trace JSON で取得できる。どのステップに何秒かかったか・どのツールを選んだかが一目でわかる。

import boto3, json

client = boto3.client("bedrock-agent-runtime", region_name="us-east-1")

response = client.invoke_agent(
 agentId=AGENT_ID,
 agentAliasId="TSTALIASID",
 sessionId="trace-demo-001",
 inputText="東京支店の在庫状況を確認して",
 enableTrace=True,# Trace 有効化
)

for event in response["completion"]:
 if "trace" in event:
  orch = event["trace"]["trace"].get("orchestrationTrace", {})

  if "modelInvocationInput" in orch:
print("モデル入力:")
print(json.dumps(orch["modelInvocationInput"], indent=2, ensure_ascii=False))

  if "rationale" in orch:
print("推論理由:", orch["rationale"].get("text", ""))

  if "observation" in orch:
obs = orch["observation"]
if "actionGroupInvocationOutput" in obs:
 print("Action Group 結果:")
 print(obs["actionGroupInvocationOutput"].get("text", ""))
if "knowledgeBaseLookupOutput" in obs:
 print("KB 検索結果件数:",
 len(obs["knowledgeBaseLookupOutput"].get("retrievedReferences", [])))

  if "finalResponse" in orch:
print("最終応答:", orch["finalResponse"].get("text", ""))

 if "chunk" in event:
  print(event["chunk"]["bytes"].decode(), end="")
</code>

Trace JSON 主要キー一覧:

キー説明
modelInvocationInputモデルへの入力 (プロンプト・SessionAttributes)
modelInvocationOutput推論結果 (選択したツール・パラメータ)
rationaleモデルが選択したツールの理由テキスト
observationAction Group / KB 呼び出し結果
finalResponseストリーミング前の最終応答テキスト

7-4. X-Ray 連携

Bedrock Agents 自体は X-Ray をネイティブ対応していないが、Lambda (Action Group) 側で X-Ray を有効化することで Agent → Lambda の分散トレースが実現できる。

# Terraform: Lambda X-Ray 有効化
resource "aws_lambda_function" "action_group" {
  function_name = "${var.prefix}-action-group"
  # ...

  tracing_config {
 mode = "Active"# X-Ray Active Tracing
  }
}

resource "aws_iam_role_policy_attachment" "lambda_xray" {
  role = aws_iam_role.lambda_role.name
  policy_arn = "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess"
}
</code>
# AWS CLI: X-Ray トレース検索
aws xray get-trace-summaries \
  --start-time "$(date -u -v-1H +%s)" \
  --end-time "$(date -u +%s)" \
  --filter-expression 'service("bedrock-agent-action-group")' \
  --region us-east-1
</code>

Trace API (§7-3) で取得した Agent の trace_id を X-Ray に渡すことで、Agent 推論 → Lambda 実行 → 外部 API 呼び出し の完全なレイテンシ分析が可能になる。

7-5. Bedrock Guardrails 統合

Bedrock Guardrails は Agent の入出力をフィルタリングする安全機構だ。3 つのユースケースを段階的に実装する。

PII マスク (最小構成)

resource "aws_bedrock_guardrail" "main" {
  name = "${var.prefix}-guardrail"
  blocked_input_messaging= "入力に不適切な内容が含まれています。"
  blocked_outputs_messaging = "応答に個人情報が含まれるため表示できません。"

  sensitive_information_policy_config {
 pii_entities_config {
action = "BLOCK"
type= "EMAIL"
 }
 pii_entities_config {
action = "ANONYMIZE"
type= "NAME"
 }
 pii_entities_config {
action = "ANONYMIZE"
type= "PHONE"
 }
  }
}
</code>

禁止トピック設定

  topic_policy_config {
 topics_config {
name = "competitor-recommendation"
definition = "競合他社の製品・サービスを推奨すること"
examples= [
  "AWSの代わりにGCPを使うべきですか",
  "Azureの方が安くないですか"
]
type = "DENY"
 }
 topics_config {
name = "financial-advice"
definition = "具体的な投資・金融アドバイスを提供すること"
examples= ["この株を買うべきですか", "FXで稼ぐ方法を教えて"]
type = "DENY"
 }
  }
</code>

Prompt Attack 検知

  content_policy_config {
 filters_config {
input_strength  = "HIGH"
output_strength = "HIGH"
type= "PROMPT_ATTACK"
 }
 filters_config {
input_strength  = "MEDIUM"
output_strength = "MEDIUM"
type= "HATE"
 }
  }
</code>
resource "aws_bedrock_guardrail_version" "main" {
  guardrail_arn = aws_bedrock_guardrail.main.guardrail_arn
  description= "v1 - PII + topic policy + prompt attack"
}
</code>

Agent への適用 (guardRailConfiguration)

resource "aws_bedrockagent_agent" "main" {
  agent_name  = var.agent_name
  agent_resource_role_arn = aws_iam_role.agent_role.arn
  foundation_model  = "anthropic.claude-3-5-sonnet-20241022-v2:0"
  instruction = var.agent_instruction

  guardrail_configuration {
 guardrail_identifier = aws_bedrock_guardrail.main.guardrail_id
 guardrail_version = aws_bedrock_guardrail_version.main.version
  }
}
</code>

AWS CLI (Guardrails 確認):

# Guardrail 一覧
aws bedrock list-guardrails --region us-east-1

# Guardrail 詳細
aws bedrock get-guardrail \
  --guardrail-identifier "${GUARDRAIL_ID}" \
  --guardrail-version DRAFT \
  --region us-east-1

# Guardrail テスト (入力フィルタリング確認)
aws bedrock apply-guardrail \
  --guardrail-identifier "${GUARDRAIL_ID}" \
  --guardrail-version DRAFT \
  --source INPUT \
  --content '[{"text": {"text": "田中太郎の電話番号を教えて"}}]' \
  --region us-east-1
</code>

コンソール: Bedrock → Guardrails → [名前] → Test で対話的なフィルタリング確認が可能。

fig06: Guardrails 検知フロー + 落とし穴ヒートマップ

7-6. QG-5: 観測性 + Guardrails チェックポイント

⚠️ QG-5: 本番投入前に確認すべき観測性+Guardrails 重要10件

  1. Invocation Logs 有効化漏れ: コンソール/boto3 でのみ設定可能・Terraform 自動化不可 (2026-04現在)。デプロイ直後に手動確認必須。
  2. Lambda Log Level が DEBUG のまま: デフォルト DEBUG は本番非推奨。構造化 JSON + INFO レベルに変更し CloudWatch Logs Insights でクエリできる形式にする。
  3. Trace API の EventStream 処理漏れ: enableTrace=True にしても EventStream を最後まで読まないと trace イベントが欠落する。必ず for event in response["completion"]: で全読みする。
  4. X-Ray サービスマップに Bedrock が出ない: Bedrock Agents 本体は X-Ray 非対応。Lambda 側の X-Ray 有効化のみで対応し、Agent Trace との手動紐付けが必要。
  5. Guardrails の DRAFT vs バージョン混同: Agent に適用する guardrail_version は DRAFT 指定可だが本番では番号指定版を推奨。DRAFT は変更即時反映されるため予期しないブロックが起きる。
  6. PII ANONYMIZE vs BLOCK の選択ミス: ANONYMIZE は "*NAME*" のように置換して応答を継続、BLOCK は応答を完全にブロック。ユーザー体験への影響度で使い分ける。
  7. 禁止トピックの description が曖昧: description と examples の精度がフィルタリング精度を決める。具体的な examples を5件以上追加する。
  8. Guardrails テスト不足: apply-guardrail CLI でテストせずに本番適用すると誤検知リスクが高い。テスト→バージョン発行→Agent 適用の順を厳守する。
  9. CloudWatch Alarm のディメンション指定ミス: AgentId ではなく AgentAliasId が必要なメトリクスも存在する。Metrics → Bedrock で目視確認してから Terraform に落とす。
  10. Guardrails と Foundation Model の相性確認不足: 一部モデルでは Guardrails の適用タイミングが異なる。Claude 3.5 Sonnet 以外を使う場合は Bedrock 公式ドキュメントで動作を事前確認する。

8. まとめ + よくある落とし穴10選 + 次回予告

Bedrock Agents の本番運用に必要な全要素 (Action Group / Knowledge Base / Session 管理 / Terraform / 観測性 / Guardrails) を通してきた。本セクションではチートシートと落とし穴10選で知識を定着させる。

8-1. 全体チートシート

Agent 操作 (CLI):

# Agent 一覧
aws bedrock-agent list-agents --region us-east-1

# Agent 詳細
aws bedrock-agent get-agent --agent-id "${AGENT_ID}"

# Agent Alias 一覧
aws bedrock-agent list-agent-aliases --agent-id "${AGENT_ID}"

# Agent 呼び出し (DRAFT)
aws bedrock-agent-runtime invoke-agent \
  --agent-id "${AGENT_ID}" \
  --agent-alias-id TSTALIASID \
  --session-id "$(uuidgen)" \
  --input-text "質問内容" \
  --region us-east-1 \
  outfile.json

# Knowledge Base 同期
aws bedrock-agent start-ingestion-job \
  --knowledge-base-id "${KB_ID}" \
  --data-source-id "${DS_ID}"

# Guardrail 適用テスト
aws bedrock apply-guardrail \
  --guardrail-identifier "${GUARDRAIL_ID}" \
  --guardrail-version DRAFT \
  --source INPUT \
  --content '[{"text":{"text":"テスト入力"}}]'
</code>

Terraform リソース早見表:

リソース用途
aws_bedrockagent_agentAgent 本体
aws_bedrockagent_agent_action_groupAction Group (Lambda + OpenAPI)
aws_bedrockagent_knowledge_baseKnowledge Base
aws_bedrockagent_data_sourceKB データソース (S3)
aws_bedrockagent_agent_alias本番/ステージング Alias
aws_bedrock_guardrailGuardrails ポリシー
aws_bedrock_guardrail_versionGuardrails バージョン固定

8-2. よくある落とし穴10選

⚠️ Bedrock Agents 本番運用 落とし穴10選

  1. OpenAPI Schema の operationId 命名不整合
    症状: Agent が Action Group を呼び出さない / "Cannot find the function" エラー
    原因: Lambda Handler の分岐キーと OpenAPI Schema の operationId が不一致
    対処: operationId を Lambda 関数ロジックの分岐キーと完全一致させる。大文字小文字も厳密に一致が必要。
  2. Lambda timeout (Action Group 30秒制限)
    症状: Action Group 呼び出しがタイムアウト、Agent がリトライループに入る
    原因: Bedrock Agents の Action Group Lambda timeout は最大 30 秒。外部 API が遅い場合に超過する
    対処: Lambda を非同期化し SQS + polling パターンに変更するか、外部 API のタイムアウトを 25 秒以内に設定する。
  3. Knowledge Base sync 失敗 (S3 Event Notification 未設定)
    症状: S3 に新ファイルを追加しても KB の検索結果に反映されない
    原因: KB はデフォルトで手動同期 (start-ingestion-job) が必要。自動同期は別途設計が必要
    対処: EventBridge Rules + Lambda で S3 PutObject イベントを検知して自動同期ジョブを起動する。
  4. Guardrails 誤検知 (description の表現が曖昧)
    症状: 正常なリクエストがブロックされる
    原因: 禁止トピックの description と examples が不十分で意図しないリクエストにマッチする
    対処: apply-guardrail CLI で 20 件以上のテストケース (ブロック期待/通過期待 両方) を実行してから本番適用する。
  5. Agent Alias の DRAFT vs 本番 Alias 混同
    症状: 開発中の変更が本番環境に即時反映されてしまう
    原因: TSTALIASID (DRAFT) と本番 Alias ID を混用している
    対処: 環境ごとに Alias を分離 (dev-alias / prod-alias) し、本番 Alias は Agent バージョンを固定する。Terraform で aws_bedrockagent_agent_alias を環境別に管理する。
  6. IAM PassRole 欠落
    症状: AccessDeniedException: User is not authorized to perform: iam:PassRole
    原因: Agent Resource Role を作成する IAM ユーザー/ロールに iam:PassRole が付与されていない
    対処: Terraform デプロイに使う IAM Role に iam:PassRole を明示追加。対象は最小スコープで設定する。
  7. foundation_model 変更時の既存 Session への影響
    症状: foundation_model 変更後、既存 sessionId を使ったリクエストで予期しない応答が出る
    原因: モデル変更後も同じ sessionId を使うと会話履歴がモデル切り替え前後で混在する
    対処: foundation_model 変更後は新しい sessionId を払い出す。AB テスト目的なら Agent Alias 単位でモデルを分離する。
  8. SessionAttributes 型不整合 (String のみ受付)
    症状: ValidationException: SessionAttribute value must be a string
    原因: SessionAttributes の value は String 型のみ。数値・オブジェクトを直接渡すと型エラーになる
    対処: 数値は str() で文字列変換、複合オブジェクトは json.dumps() で文字列化して渡す。Lambda Handler 側でデシリアライズする。
  9. Trace API レスポンスサイズ超過
    症状: ResponseSizeTooLargeException または Trace が途中で切れる
    原因: 長い会話セッションや複数の Action Group 呼び出しがある場合、Trace JSON がバッファサイズを超える
    対処: EventStream の chunk を逐次処理 (streaming) し、Trace を S3 または CloudWatch Logs に書き出す設計にする。本番では分析用途に絞りデバッグ時のみ enableTrace を有効化する。
  10. 同時実行制限 (Lambda concurrency + Bedrock quota)
    症状: 負荷試験時に ThrottlingException が多発
    原因: Lambda の同時実行数上限 (デフォルト 1000/リージョン) と Bedrock のモデル呼び出し TPS quota が同時にボトルネックになる
    対処: Lambda に Reserved Concurrency を設定し過剰な Bedrock 呼び出しをシェイプする。Bedrock quota は Service Quotas コンソールから引き上げ申請する。InvocationThrottles アラームを設置する (§7-2 参照)。

8-3. 次回予告

次回予告

TODO: 次回記事テーマを記載 (Bedrock Multi-Agent Collaboration / Bedrock Inline Agents / Bedrock Flows など)


AWS 公式 Bedrock Agents ユーザーガイドを確認する

Terraform Registry: aws_bedrockagent_agent を確認する

関連記事: Bedrock Knowledge Bases 入門を読む