最終確認: 2026年5月
AIP-C01 試験の対象となる AWS サービスを、プレーンな Terraform を使用して構築します。1 ブロックずつ、それぞれ試験ドメインに関連付けられています。同じコードが OpenTofu でも動作します。
このラボを完了するまでに、プレーンなTerraformを使って、本番環境向けのBedrockエージェントをプロビジョニングします。これには、あらゆるソースデータ用のS3バケット、エージェントが引き受ける最小権限のIAMロール、本番環境レベルのBedrockガードレール(コンテンツ + PII + 拒否トピックフィルター)、Bedrockエージェント自体、そしてエージェントがツールとしてLambda関数を呼び出せるようにするアクショングループが含まれます。これは、ツール呼び出し型の生成AIのためのAIP-C01リファレンスアーキテクチャです。安全レール、スコープされた権限、および呼び出し可能な拡張サーフェスを備えたモデルです。
すべてのリソースはプレーンなTerraformです。スニペットを単一のmain.tfにドロップし、terraform initを実行し、その後terraform applyをステップバイステップで実行してください。
>= 1.5 または OpenTofu >= 1.6。us-east-1向けにAWS CLIが認証済みであること(Bedrock Agentのサポートが最も広範囲に利用可能です)。anthropic.claude-3-haiku-20240307-v1:0を有効にしてください(ステップ4のエージェントがこれを参照します)。モデルアクセスはインフラストラクチャ・アズ・コードの範囲外のアカウントレベルのトグルです。aws_bedrockagent_*リソースにはAWSプロバイダー ~> 5.60 が必要であり、Bedrock Agentサービスがお使いのリージョンで一般提供(GA)されている必要があります。aws bedrock-agent list-agentsが動作するかどうかをAWSコンソールで確認してください。アイドル状態での請求は最小限であり、請求額は使用量に応じて変動します。
AIP-C01が特にテストするコストの罠: Bedrockナレッジベースは、アイドル状態で月額最低約$350かかるOpenSearch Serverlessコレクションを必要とします。このラボでは意図的にナレッジベースをプロビジョニングしません — ステップ5のアクショングループパターンは、OpenSearchの罠なしで、より一般的なツール呼び出しエージェントの形状を示します。ナレッジベースを学習したい場合は、まず概念的に学習し、実際に使用する準備ができてからOSSコレクションをプロビジョニングしてください。
標準的な導入部です。Bedrock + Bedrock Agent機能の利用可能性を最大化するためにはus-east-1を使用します。プロバイダーのバージョン固定は必須です。aws_bedrockagent_*リソースには~> 5.60以降が必要です。
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.60"
}
archive = {
source = "hashicorp/archive"
version = "~> 2.4"
}
}
}
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
Project = "certlabpro-aip-c01"
ManagedBy = "terraform"
}
}
}
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}ほとんどの本番環境のBedrockエージェントは、S3から何らかのものを読み取ることになります — ナレッジベースのソースドキュメント、JSONツール定義、応答テンプレートなどです。後で権限を配線する必要がないように、事前にバケットをプロビジョニングします。暗号化とパブリックアクセスブロックのデフォルトは、AIP-C01の「基盤モデルの統合、データ管理、およびコンプライアンス」のドメインが適用されています。
AIP-C01試験では、このバケットに関する特定のコンプライアンスパターンがテストされます。規制が「AWSは暗号化されていないデータを決して保持してはならない」と述べている場合、アプリケーションが制御するキーによるクライアントサイド暗号化が正しい答えです。それ以外のすべての場合、SSE-S3(ここで使用する方法)で十分です。
resource "aws_s3_bucket" "agent_data" {
bucket_prefix = "certlabpro-aip-c01-"
}
resource "aws_s3_bucket_public_access_block" "agent_data" {
bucket = aws_s3_bucket.agent_data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_server_side_encryption_configuration" "agent_data" {
bucket = aws_s3_bucket.agent_data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}AIP-C01の「AIの安全性、セキュリティ、およびガバナンス」ドメイン(試験の20%)は、AIF-C01バージョンよりもはるかに深いです。試験では、多層ガードレールの構成がテストされます。高い強度での有害なカテゴリに対するコンテンツフィルター、PIIに対する機密情報ポリシー(AIFスタイルのANONYMIZEではなくBLOCKを使用 — 本番環境のエージェントは通常、ハードブロックが必要です)、およびアプリケーション固有の禁止トピックに対するトピックポリシーです。
これら3つすべてを設定します。ポリシー内の拒否トピック"FinancialAdvice"は、非金融チャットボットにとって一般的な本番環境のガードレールです — Claude 3でさえ、ガードレールにトピックの逸脱をブロックするように指示しない限り、株のヒントを与えることがあります。AIP-C01は、プロンプトは無害であるものの、応答がポリシーに反する可能性があるシナリオ問題で、この正確な構成パターンをテストします。
resource "aws_bedrock_guardrail" "production" {
name = "certlabpro-aip-c01-production"
description = "Production-grade safety rail for the AIP-C01 lab agent."
blocked_input_messaging = "I can't help with that request."
blocked_outputs_messaging = "I can't share that response."
content_policy_config {
filters_config {
input_strength = "HIGH"
output_strength = "HIGH"
type = "HATE"
}
filters_config {
input_strength = "HIGH"
output_strength = "HIGH"
type = "VIOLENCE"
}
filters_config {
input_strength = "HIGH"
output_strength = "HIGH"
type = "SEXUAL"
}
filters_config {
input_strength = "HIGH"
output_strength = "HIGH"
type = "INSULTS"
}
filters_config {
input_strength = "HIGH"
output_strength = "HIGH"
type = "MISCONDUCT"
}
}
sensitive_information_policy_config {
pii_entities_config {
action = "BLOCK"
type = "EMAIL"
}
pii_entities_config {
action = "BLOCK"
type = "PHONE"
}
pii_entities_config {
action = "BLOCK"
type = "US_SOCIAL_SECURITY_NUMBER"
}
pii_entities_config {
action = "BLOCK"
type = "CREDIT_DEBIT_CARD_NUMBER"
}
}
topic_policy_config {
topics_config {
name = "FinancialAdvice"
definition = "Specific recommendations to buy, sell, or hold financial instruments."
examples = ["Should I buy NVDA?", "Is now a good time to sell my Bitcoin?"]
type = "DENY"
}
}
}エージェントは、基盤モデル、システムプロンプト、そして(ステップ5で)その機能を拡張する1つ以上のアクショングループを結び付けます。私たちがアタッチするIAMロールはエージェントの実行ロールです。エージェントがモデルを呼び出し、ナレッジベースから取得し、アクショングループのLambdaを呼び出すために使用するものです。AIP-C01の「実装と統合」ドメインは、この正確なロール/信頼の形状をテストします。プリンシパルとしてbedrock.amazonaws.com、特定のモデルARNに対するbedrock:InvokeModelへのスコープされた権限、および特定の関数ARNに対するlambda:InvokeFunctionです。
エージェントのinstructionフィールドはシステムプロンプトです — 短く、行動指向で、エージェントの目的を名指しするものです。エージェントレベルでのプロンプトエンジニアリングに関するAIP-C01の質問は、まさにこれをテストします。命令は永続的な個性であり、ユーザーメッセージはターンごとに変化します。
resource "aws_iam_role" "agent" {
name = "certlabpro-aip-c01-agent"
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" "agent_invoke_model" {
name = "invoke-foundation-model"
role = aws_iam_role.agent.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream"]
Resource = "arn:aws:bedrock:${data.aws_region.current.name}::foundation-model/anthropic.claude-3-haiku-20240307-v1:0"
}]
})
}
resource "aws_bedrockagent_agent" "main" {
agent_name = "certlabpro-aip-c01-agent"
agent_resource_role_arn = aws_iam_role.agent.arn
foundation_model = "anthropic.claude-3-haiku-20240307-v1:0"
instruction = "You are a helpful assistant for the certlabpro AIP-C01 lab. Answer concisely. When the user asks about the current time, use the get_current_time tool."
idle_session_ttl_in_seconds = 600
# Attach the guardrail from Step 3. Bedrock evaluates inputs and outputs
# against the guardrail policy on every model call.
guardrail_configuration {
guardrail_identifier = aws_bedrock_guardrail.production.guardrail_id
guardrail_version = aws_bedrock_guardrail.production.version
}
}アクショングループは、Bedrockエージェントがあなたのコードを呼び出す方法です。パターンは次のとおりです。APIスキーマ(ツールが受け入れるものと返すもの)を定義し、アクションを実装するLambdaを指し、残りはBedrockが処理します — モデルがツールを必要と判断すると、構造化された引数でLambdaを呼び出し、応答を会話にフィードバックします。
Bedrockが期待するOpenAPI 3.0スキーマを使用して、最小限のget_current_timeアクションを定義します。Lambdaの実装は意図的に非常に小さいものです。試験がテストするのは、統合の形状(関数呼び出しLambda + OpenAPIスキーマ + Bedrock呼び出し権限)であり、関数の内部ロジックではありません。
aws_lambda_permissionリソースは、AIP-C01の典型的な注意点です。これがないと、他のすべての要素が正しく接続されていても、エージェントのLambda呼び出しがAccessDeniedになります。Bedrock Agent → Lambdaは外部サービス呼び出しパターンであり、関数のリソースポリシーでbedrock.amazonaws.comを明示的に許可する必要があります。
アクショングループが配置されると、エージェントの完全な形状が完成します。モデル + システムプロンプト + セキュリティガードレール + ツール呼び出しの拡張性、これらすべてが1つのスコープされたIAMアイデンティティの下にあります。その他のAIP-C01パターン(ナレッジベースの取得、複数アクションエージェント、スーパーバイザーエージェントを介したエージェント間の連携)はすべて、この基本を拡張するものです。
# ── Lambda tool ───────────────────────────────────────────────
data "archive_file" "tool" {
type = "zip"
output_path = "${path.module}/build/tool.zip"
source {
filename = "index.py"
content = <<-EOT
import json
from datetime import datetime, timezone
def handler(event, context):
# Bedrock Agent passes the parsed args under `requestBody` / `parameters`.
# For a simple no-arg tool, just return the current time.
now_iso = datetime.now(timezone.utc).isoformat()
return {
"messageVersion": "1.0",
"response": {
"actionGroup": event.get("actionGroup", ""),
"apiPath": event.get("apiPath", "/"),
"httpMethod": event.get("httpMethod", "GET"),
"httpStatusCode": 200,
"responseBody": {"application/json": {"body": json.dumps({"current_time_utc": now_iso})}},
},
}
EOT
}
}
resource "aws_iam_role" "tool_lambda" {
name = "certlabpro-aip-c01-tool"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "lambda.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy_attachment" "tool_logs" {
role = aws_iam_role.tool_lambda.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_lambda_function" "tool" {
function_name = "certlabpro-aip-c01-tool"
role = aws_iam_role.tool_lambda.arn
runtime = "python3.12"
handler = "index.handler"
filename = data.archive_file.tool.output_path
source_code_hash = data.archive_file.tool.output_base64sha256
timeout = 10
}
resource "aws_lambda_permission" "agent_invoke_tool" {
statement_id = "AllowBedrockAgentInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.tool.function_name
principal = "bedrock.amazonaws.com"
source_arn = aws_bedrockagent_agent.main.agent_arn
}
# Also let the agent invoke the lambda from its execution role.
resource "aws_iam_role_policy" "agent_invoke_lambda" {
name = "invoke-tool"
role = aws_iam_role.agent.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = "lambda:InvokeFunction"
Resource = aws_lambda_function.tool.arn
}]
})
}
# ── Action Group ──────────────────────────────────────────────
resource "aws_bedrockagent_agent_action_group" "time" {
action_group_name = "time-tools"
agent_id = aws_bedrockagent_agent.main.agent_id
agent_version = "DRAFT"
description = "Time-related tool calls for the agent."
skip_resource_in_use_check = false
action_group_executor {
lambda = aws_lambda_function.tool.arn
}
api_schema {
payload = jsonencode({
openapi = "3.0.0"
info = { title = "Time tools", version = "1.0.0" }
paths = {
"/get_current_time" = {
get = {
operationId = "get_current_time"
description = "Returns the current UTC time as an ISO-8601 string."
responses = {
"200" = {
description = "Current UTC time"
content = {
"application/json" = {
schema = {
type = "object"
properties = {
current_time_utc = { type = "string", format = "date-time" }
}
}
}
}
}
}
}
}
}
})
}
}terraform destroyは、このラボのすべてを順序に注意して破棄します。
force_destroy = falseです。参照データをアップロードした場合は、破棄する前に空にしてください(aws s3 rm s3://<bucket> --recursive)。AIP-C01は、このラボでは扱いきれない本番環境のGenAIサーフェスをカバーしています — Bedrockナレッジベース(OpenSearch Serverlessが必要で、アイドル状態で月額$350以上かかるため、費用に関する注意書きに従って意図的にスキップ)、トラフィックシフトとバージョン管理のためのBedrockエージェントエイリアス、マルチエージェント連携(スペシャリストサブエージェントに委任するスーパーバイザーエージェント)、長期間の会話状態を維持するためのエージェントメモリ、Bedrockカスタムモデル(ファインチューニング)、高ボリュームの本番デプロイのためのBedrockプロビジョニング済みスループット、Amazon Q for Business(Terraformリソースなし)、プラットフォーム外の基盤モデルホスティングのためのSageMaker JumpStart、およびBedrockオブザーバビリティスタック(AIF-C01でカバーされたよりも深いモデル呼び出しロギング)です。
私たちはエージェント + アクショングループ + 本番ガードレールの形状に限定しています。これは、試験で最もテストされる本番環境のGenAIアーキテクチャであり、より高度なすべてのパターンがこれに付随する基盤となるためです。ナレッジベースはこのエージェントにアタッチされます。エイリアスはこのエージェントをバージョン管理します。マルチエージェント連携はこのようなエージェントを構成します。
上記のサーフェスの詳細については、この認定ページの閲覧、プレイブック、およびEditorialセクションに概念的な資料があります。自然な次のラボとしては、この基本の上にナレッジベースを追加するでしょう(OpenSearchのコストが、ここに含めない唯一の理由です)。