every Tech Blog

株式会社エブリーのTech Blogです。

Amazon Bedrock AgentCoreをTerraformで構築してみた

この記事は every Tech Blog Advent Calendar 2025の 18 日目の記事です。

はじめに

こんにちは、開発1部に所属している25卒の江﨑です。

2025年10月に一般提供開始されたAmazon Bedrock AgentCoreは、AIエージェントの構築・運用を支援するマネージドサービスです。エージェントの実行環境(Runtime)、既存APIやLambdaをツールとして呼び出すためのインターフェース(Gateway)、認証管理(Identity)など、エージェント開発に必要な機能がまとめて提供されています。

今回、私が担当するデリッシュリサーチというサービスで分析エージェントを構築する中で、AgentCoreのインフラをTerraformで管理しました。 しかし、AgentCore関連のTerraformリソースは、事例がほとんど見当たりませんでした。

本記事では、実際にAgentCoreをTerraformで構築した経験をもとに、各リソースの設定方法とポイントを解説します。

AgentCoreの全体アーキテクチャ

今回構築したシステムの全体像は以下のとおりです。

アーキテクチャ図

このエージェントは、レシピのレビューコメントを分析し、インサイトを生成します。処理の流れは以下のとおりです。

まず、DynamoDBに保存されたキャッシュを確認します。同じレシピに対する分析結果が24時間以内に存在すれば、それを返却して処理を終了します。

キャッシュがない場合、AgentCore Gateway経由でLambda関数を呼び出し、Athenaからレビューデータを取得します。次に、取得したレビューコメントをOpenAI APIに送信し、カテゴリにグルーピングします。最後に、グルーピング結果をもとに要約文を生成し、DynamoDBにキャッシュして返却します。

Terraformで管理する主なリソースは以下の3つです。

リソース 役割
aws_bedrockagentcore_gateway エージェントからのリクエストを受け付けるGateway
aws_bedrockagentcore_gateway_target Gateway配下のターゲット(Lambda等)
aws_bedrockagentcore_api_key_credential_provider API Key認証情報の管理

AWS Provider バージョン要件

AgentCore関連リソースを使用するには、AWS Provider 6.17以上が必要です。

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

2025年10月に、Provider 6.17と6.18で、AgentCore関連のリソースが一気に追加されました。

v6.17.0で追加

  • aws_bedrockagentcore_gateway / aws_bedrockagentcore_gateway_target
  • aws_bedrockagentcore_api_key_credential_provider
  • aws_bedrockagentcore_agent_runtime / aws_bedrockagentcore_agent_runtime_endpoint
  • aws_bedrockagentcore_browser / aws_bedrockagentcore_code_interpreter

v6.18.0で追加

  • aws_bedrockagentcore_memory / aws_bedrockagentcore_memory_strategy
  • aws_bedrockagentcore_oauth2_credential_provider
  • aws_bedrockagentcore_workload_identity / aws_bedrockagentcore_token_vault_cmk

これにより、AgentCoreの主要なリソースはTerraformで管理できるようになっています。

Gateway の構築

AgentCore Gatewayは、既存のAPI、Lambda関数、各種サービスをMCP互換のツールに変換して、AIエージェントから呼び出せる統一したインターフェースを提供してくれます。

resource "aws_bedrockagentcore_gateway" "review_analysis" {
  name        = "RecipeReviewAnalysisGateway"
  description = "Gateway for Recipe Review Analysis Agent"

  authorizer_type = "AWS_IAM"
  protocol_type   = "MCP"

  role_arn = aws_iam_role.agentcore_gateway.arn
}

必須パラメータ

Gatewayの作成には以下の4つのパラメータが必須です。

パラメータ 説明
name Gatewayの名前
authorizer_type 認証方式(AWS_IAM または CUSTOM_JWT
protocol_type プロトコル(現時点では MCP のみ)
role_arn GatewayがAWSサービスにアクセスする際に使用するIAMロールのARN

authorizer_type の選択

authorizer_type は認証方式を指定します。

説明
AWS_IAM IAM認証(SigV4署名)
CUSTOM_JWT カスタムJWT認証(OpenID Connect対応)

今回は AWS_IAM を採用しました。理由は以下のとおりです。

  • IdentityやCognitoの設定・管理が不要
  • 追加の認証設定が不要でシンプル

CUSTOM_JWT を選択した場合は、authorizer_configuration ブロックでOpenID Connectの設定(discovery_url等)が必要になります。

protocol_type について

protocol_type はGatewayが使用するプロトコルを指定します。現時点では MCP(Model Context Protocol)のみがサポートされています。

MCPはエージェントがツールを呼び出す際の標準プロトコルで、ツールスキーマの定義やレスポンス形式が規格化されています。

Gateway Target の構築

Gateway Targetは、Gatewayが呼び出す具体的なツール(Lambda関数など)を定義します。

resource "aws_bedrockagentcore_gateway_target" "recipe_review_fetcher" {
  gateway_identifier = aws_bedrockagentcore_gateway.review_analysis.gateway_id
  name               = "RecipeReviewFetcher"
  description        = "Fetch recipe reviews via Lambda"

  target_configuration {
    mcp {
      lambda {
        lambda_arn = data.aws_lambda_function.get_recipe_reviews.arn

        tool_schema {
          inline_payload {
            name        = "fetch_reviews"
            description = "指定されたレシピIDのレビューコメントを取得します"

            input_schema {
              type        = "object"
              description = "レビュー取得リクエスト"

              property {
                name        = "recipe_id"
                type        = "string"
                description = "レビューを取得するレシピのID"
                required    = true
              }
            }
          }
        }
      }
    }
  }

  credential_provider_configuration {
    gateway_iam_role {}
  }
}

必須パラメータ

Gateway Targetの作成には以下の3つのパラメータが必須です。

パラメータ 説明
name Targetの名前
gateway_identifier 親GatewayのID
target_configuration ターゲットエンドポイントの設定

target_configuration のターゲット種類

target_configurationmcp ブロック内で、以下のターゲット種類を選択できます。

種類 説明
lambda Lambda関数をターゲットにする(今回使用)
mcp_server 外部のMCPサーバーをターゲットにする
open_api_schema OpenAPIスキーマベースでAPIを定義
smithy_model Smithyモデルベースで定義

今回は lambda を使用し、Athenaでレビューデータを取得するLambda関数を呼び出しています。

tool_schema の定義

tool_schema はエージェントがツールを呼び出す際のインターフェースを定義します。inline_payload で直接定義するか、s3 でS3上のスキーマファイルを参照できます。

tool_schema {
  inline_payload {
    name        = "fetch_reviews"
    description = "指定されたレシピIDのレビューコメントを取得します"

    input_schema {
      type        = "object"
      description = "レビュー取得リクエスト"

      property {
        name        = "recipe_id"
        type        = "string"
        description = "レビューを取得するレシピのID"
        required    = true
      }
    }
  }
}

この定義により、エージェントは「fetch_reviews」というツールを認識し、recipe_id パラメータを渡して呼び出すことができます。

credential_provider_configuration

credential_provider_configuration はターゲット呼び出し時の認証方式を指定します。

認証方式 説明
gateway_iam_role GatewayのIAMロールを使用(今回使用)
api_key APIキー認証(外部API向け)
oauth OAuth認証(外部サービス向け)

今回は gateway_iam_role を使用し、GatewayのIAMロールでLambdaを呼び出しています。

credential_provider_configuration {
  gateway_iam_role {}
}

gateway_iam_role を指定すると、GatewayのIAMロールを使用してLambdaを呼び出します。これにより、別途認証情報を管理する必要がなくなります。

SigV4署名によるGateway呼び出し

Gatewayの authorizer_typeAWS_IAM を指定した場合、エージェントからGatewayを呼び出す際にSigV4署名が必要です。

以下は、MCPクライアントを使用してSigV4署名付きでGatewayを呼び出す例です。

import boto3
from mcp import ClientSession
from mcp_lambda.client.streamable_http_sigv4 import streamablehttp_client_with_sigv4

session = boto3.Session(region_name="ap-northeast-1")
credentials = session.get_credentials()

async with streamablehttp_client_with_sigv4(
    url=gateway_url,
    credentials=credentials,
    region="ap-northeast-1",
    service="bedrock-agentcore",
) as (read, write, _):
    async with ClientSession(read, write) as mcp_session:
        await mcp_session.initialize()

        result = await mcp_session.call_tool(
            "RecipeReviewFetcher___fetch_reviews",
            arguments={"recipe_id": recipe_id}
        )

ポイントは以下のとおりです。

  • mcp_lambda パッケージの streamablehttp_client_with_sigv4 を使用
  • service には bedrock-agentcore を指定
  • ツール名は {TargetName}___{tool_name} の形式(アンダースコア3つ)

Identity Provider の構築

AgentCore Identityは、エージェントが外部APIにアクセスする際の認証情報を管理します。今回はOpenAI APIのキーを管理するために aws_bedrockagentcore_api_key_credential_provider を使用しました。

# Secrets ManagerからAPIキーを取得
data "aws_secretsmanager_secret" "openai_api_key" {
  name = "bedrock-agentcore/openai-api-key"
}

data "aws_secretsmanager_secret_version" "openai_api_key" {
  secret_id = data.aws_secretsmanager_secret.openai_api_key.id
}

# AgentCore Identity ProviderにAPIキーを登録
resource "aws_bedrockagentcore_api_key_credential_provider" "openai" {
  name = "OpenAIApiKey"

  api_key_wo         = jsondecode(data.aws_secretsmanager_secret_version.openai_api_key.secret_string)["OPENAI_API_KEY"]
  api_key_wo_version = 1
}

必須パラメータ

パラメータ 説明
name Providerの名前(変更するとリソースが再作成される)

APIキーの指定方法

APIキーは以下の2つの方法で指定できます。

方法 パラメータ 説明
通常 api_key APIキー値がTerraform plan/stateに表示される
Write-Only(推奨) api_key_wo + api_key_wo_version stateファイルに保存されずセキュア

本番環境では api_key_wo の使用を推奨します。

api_key_wo は Write-Onlyの属性です。Terraformの state ファイルには保存されず、セキュリティが確保されます。

api_key_wo_version はキーのバージョン管理に使用します。キーを更新する際はこの値をインクリメントすることで、Terraformに変更を検知させます。

Secrets Manager との連携

API Keyは直接Terraformに記述せず、Secrets Managerから取得しています。事前に以下のようなシークレットを作成しておきます。

aws secretsmanager create-secret \
  --name "bedrock-agentcore/openai-api-key" \
  --secret-string '{"OPENAI_API_KEY":"sk-..."}' \
  --region ap-northeast-1

このリソースを作成すると、AgentCore側でも自動的にSecrets Managerにシークレットが作成され、api_key_secret_arn 属性で参照できます。

エージェントからのAPIキー取得

登録したAPIキーは、エージェントのコード内で @requires_api_key デコレータを使用して取得できます。

from bedrock_agentcore.identity.auth import requires_api_key

IDENTITY_OPENAI_PROVIDER = "OpenAIApiKey"  # Terraformで登録したname

@requires_api_key(provider_name=IDENTITY_OPENAI_PROVIDER)
async def get_openai_api_key(*, api_key: str) -> str:
    """api_key はデコレータにより自動注入される"""
    return api_key

デコレータが自動的にIdentity Providerから認証情報を取得し、api_key 引数に注入してくれます。これにより、エージェントのコード内でAPIキーを直接扱う必要がなくなります。

IAM設計のポイント

AgentCoreを運用するには、適切なIAMロールとポリシーの設計が重要です。

AgentCore Runtime用ロール

resource "aws_iam_role" "agentcore_review_analysis" {
  name = "RecipeReviewAnalysisAgentRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          Service = "bedrock-agentcore.amazonaws.com"
        }
        Action = "sts:AssumeRole"
      }
    ]
  })
}

信頼ポリシーで bedrock-agentcore.amazonaws.com を指定することで、AgentCoreサービスがこのロールを引き受けられるようになります。

必要なアクション

AgentCore Identity経由でAPI Keyを取得する場合、以下のアクションが必要です。

data "aws_iam_policy_document" "agentcore_identity" {
  statement {
    sid    = "TokenVault"
    effect = "Allow"
    actions = [
      "bedrock-agentcore:GetResourceApiKey"
    ]
    resources = [
      "arn:aws:bedrock-agentcore:ap-northeast-1:${var.account_id}:token-vault/*",
      "arn:aws:bedrock-agentcore:ap-northeast-1:${var.account_id}:workload-identity-directory/*"
    ]
  }

OAuth2認証を使用する場合は、bedrock-agentcore:GetResourceOauth2Token も追加します。

Gateway呼び出し権限

エージェントがIAM認証でGatewayを呼び出すには、bedrock-agentcore:InvokeGateway アクションが必要です。

data "aws_iam_policy_document" "agentcore_invoke_gateway" {
  statement {
    sid    = "InvokeGateway"
    effect = "Allow"
    actions = [
      "bedrock-agentcore:InvokeGateway"
    ]
    resources = [
      "arn:aws:bedrock-agentcore:ap-northeast-1:${var.account_id}:gateway/${aws_bedrockagentcore_gateway.review_analysis.gateway_id}"
    ]
  }
}

GatewayからLambdaを呼び出す権限

Gateway Targetで credential_provider_configurationgateway_iam_role を指定した場合、GatewayのIAMロールに lambda:InvokeFunction 権限が必要です。

resource "aws_iam_role_policy" "agentcore_gateway_lambda" {
  name = "agentcore-gateway-lambda-invoke"
  role = aws_iam_role.agentcore_gateway.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect   = "Allow"
        Action   = "lambda:InvokeFunction"
        Resource = data.aws_lambda_function.get_recipe_reviews.arn
      }
    ]
  })
}

この権限がないと、GatewayからLambdaを呼び出す際にエラーが発生します。

AgentCore Runtime のデプロイ

AgentCore Runtimeについては、Terraformではなく AgentCore CLI を使用してデプロイしました。CLIがビルド・デプロイ・環境設定を自動化してくれるため、Runtimeの管理には CLI の方が適していると判断しました。

agentcore configure

まず agentcore configure でエージェントの設定を行います。

オプション 説明
--entrypoint エージェントのエントリーポイントとなるPythonファイル
--name エージェント名
--execution-role エージェントが使用するIAMロールのARN
--requirements-file 依存ライブラリを記載したファイル
--region デプロイ先のリージョン
agentcore configure \
  --entrypoint ./invoke.py \
  --name recipe_review_analysis_agent \
  --execution-role arn:aws:iam::<account-id>:role/RecipeReviewAnalysisAgentRole \
  --requirements-file ./requirements.txt \
  --region ap-northeast-1

--execution-role には、Terraformで作成したIAMロールのARNを指定します。CLIがデプロイ時に自動でこのロールをRuntimeに割り当ててくれます。

agentcore launch

設定完了後、agentcore launch でAWSにデプロイします。--env オプションで環境変数を渡すことができます。

agentcore launch \
  --env GATEWAY_URL="https://<gateway-name>.gateway.bedrock-agentcore.ap-northeast-1.amazonaws.com/mcp"

TerraformでGatewayを作成した際に出力されるURLを、--env で環境変数としてエージェントに渡しています。

まとめ

本記事では、Amazon Bedrock AgentCoreをTerraformで構築する方法を解説しました。

主なポイントは以下のとおりです。

  • AWS Provider 6.17以上が必要
  • aws_bedrockagentcore_gateway でGatewayを作成し、認証方式とプロトコルを指定
  • aws_bedrockagentcore_gateway_target で呼び出し先(Lambda等)とtool_schemaを定義
  • aws_bedrockagentcore_api_key_credential_provider で外部API用のAPIキーを管理
  • IAMロールの信頼ポリシーに bedrock-agentcore.amazonaws.com を指定
  • RuntimeはAgentCore CLIでデプロイし、Terraformで作成したIAMロールを --execution-role で指定

AgentCoreはまだ新しいサービスであり、ドキュメントや事例が少ない状況です。私たちも試行錯誤しながら構築を進めている段階ですが、本記事が同様の構築を行う方の参考になれば幸いです。

参考リンク