3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS Amplify HostingからAgentCore RuntimeをCloudFormationでデプロイする (直接コードデプロイ版)

Posted at

はじめに

先日、AWS Amplify HostingのCI/CDからCloudFromationでAgentCore Runtimeを含むAIチャットアプリをデプロイしてみました。

その際、AgentCore RuntimeへデプロイするAIエージェントのソースコードはコンテナ上を指定していました。

今回は、S3バケットから直接コードをデプロイがどうやらCloudFormationでも対応したようなので、試してみたいと思います。

概要

おさらい

今回もデプロイする構成は以下となります。

image.png

AgentCore Runtimeがコンテナでなくとも直接コードをデプロイできるようになった!

11/5にAgentCore RuntimeのソースコードをS3から指定できるようになりました。

直接コードデプロイは、ソースコードのパッケージサイズが「250 MB」という制限があるようです。
コンテナの場合は、1GBまでいけるようなので、構築するAIエージェントの規模によって、選択するのが良さげです。pip installする依存パッケージのボリューム次第な気がします。

AWS Amplify HostingのCI/CDイメージ

CodeBuildやECRを経由しなくなったため、だいぶシンプルなフローになりました。

image.png

元Mermaid

CloudFormationの場合どうやるか

元々「AWS::BedrockAgentCore::Runtime AgentRuntimeArtifact」に指定できるのは「ContainerConfiguration」だけだったのですが、「CodeConfiguration」が追加されていました。
ここにS3バケットを指定してあげます。

image.png

やってみる

前提:デプロイするエージェント by StrandsAgents

main.py
import os, logging
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from strands import Agent
from strands.models import BedrockModel
from strands_tools import current_time
from system_prompt import test_system_prompt


log = logging.getLogger("SampleAgent")
logging.basicConfig(level=logging.INFO)

MODEL_ID = os.environ.get("MODEL_ID")

REGION = os.environ.get("REGION")

app = BedrockAgentCoreApp()

@app.entrypoint
async def invoke(payload):
    user_prompt = payload.get("prompt", "No prompt found in input, please guide customer to create a json payload with prompt key")

    agent = create_agent()
    agent_stream = agent.stream_async(user_prompt)
    async for event in agent_stream:
        if "event" in event:
            yield event

if __name__ == "__main__":
    app.run()

前回のコンテナデプロイから以下のCFnテンプレートは不要になりました!

  • ECR (コンテナイメージ用)
  • CodeDeploy (Dockerビルド用)

CFnテンプレートの作成

代わりに以下のAgentCoreのRuntimeにS3バケットを指定しています。

      AgentRuntimeArtifact:
        CodeConfiguration:
          Code:
            S3:
              Bucket: !Sub "${NamePrefix}-source-bucket"
              Prefix: "source.zip"
          EntryPoint:
            - "main.py"
          Runtime: "PYTHON_3_13"

また、今回の対応にあたり、zip化する際にpython-platformを指定する必要があります。

amplify.yml
        # ソースコードをZIP化してS3にアップロード
        - cd agent
        - mkdir -p deployment_package
        - |
          uv pip install \
            --python-platform aarch64-manylinux2014 \
            --python-version 3.13 \
            --target=deployment_package \
            --only-binary=:all: \
            -r requirements.txt
        - cp main.py system_prompt.py deployment_package/
        - cd deployment_package
        - zip -r ../source.zip .
        - cd ..
        - aws s3 cp source.zip s3://${NAME_PREFIX}-source-bucket/source.zip
        - cd ../

というわけでCFnテンプレートはAgentCore Runtime と S3バケットのみになりました。

S3バケット

s3.yaml
AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  NamePrefix:
    Type: String

Resources:
  SourceBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub '${NamePrefix}-source-bucket'
      VersioningConfiguration:
        Status: Enabled
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

Outputs:
  SourceBucketName:
    Value: !Ref SourceBucket

AgentCore Runtime

AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  NamePrefix:
    Type: String
  CognitoUserPoolId:
    Type: String
  CognitoUserPoolClientId:
    Type: String
  BuildTimestamp:
    Type: String

Resources:
  # AgentCoreの実行ロール
  AgentCoreExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${NamePrefix}-runtime-role
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: bedrock-agentcore.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: CloudWatchLogsAccess
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Sid: "CloudWatchLogs"
                Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                  - logs:DescribeLogGroups
                  - logs:DescribeLogStreams
                Resource: "*"
        - PolicyName: BedrockModelInvocation
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Sid: "BedrockModelInvocation"
                Effect: Allow
                Action:
                  - bedrock:InvokeModel
                  - bedrock:InvokeModelWithResponseStream
                Resource:
                  - arn:aws:bedrock:*::foundation-model/*
                  - arn:aws:bedrock:*:*:inference-profile/*
  
  # Amazon Bedrock AgentCore Runtime リソース
  AgentCoreRuntime:
    Type: AWS::BedrockAgentCore::Runtime
    Properties:
      AgentRuntimeName: "vite_agent_runtime_v2"
      AgentRuntimeArtifact:
        CodeConfiguration:
          Code:
            S3:
              Bucket: !Sub "${NamePrefix}-source-bucket"
              Prefix: "source.zip"
          EntryPoint:
            - "main.py"
          Runtime: "PYTHON_3_13"
      ProtocolConfiguration: HTTP # HTTP or MCP
      NetworkConfiguration:
        NetworkMode: PUBLIC # VPC or PUBLIC
      AuthorizerConfiguration:
        CustomJWTAuthorizer:
          AllowedClients:
            - !Sub "${CognitoUserPoolClientId}"
          DiscoveryUrl: !Sub "https://cognito-idp.${AWS::Region}.amazonaws.com/${CognitoUserPoolId}/.well-known/openid-configuration"
      EnvironmentVariables:
        MODEL_ID: "jp.anthropic.claude-haiku-4-5-20251001-v1:0"
        REGION: "ap-northeast-1"
        BUILD_TIMESTAMP: !Ref BuildTimestamp
      RoleArn: !GetAtt AgentCoreExecutionRole.Arn

あとは、AWSマネジメントコンソ

amplify.ymlの作成

Amplify Hostingでは、「amplify.yml」の内容に従って、デプロイが実行されます。
ということで、先ほど説明したフローに従いファイルを作成します。

amplify.yml
version: 1
appRoot: .
env:
  variables:
    AMPLIFY_DIFF_DEPLOY: false
    NAME_PREFIX: vite-agentcore-app-dev3
backend:
  phases:
    preBuild:
      commands:
        # uvをインストール
        - curl -LsSf https://astral.sh/uv/install.sh | sh
        - export PATH="$HOME/.local/bin:$PATH"

        # S3バケットをデプロイ
        - cd cfn
        - |
          aws cloudformation deploy \
            --stack-name ${NAME_PREFIX}-s3-stack \
            --template-file s3.yaml \
            --parameter-overrides \
              NamePrefix=${NAME_PREFIX} \
            --capabilities CAPABILITY_NAMED_IAM \
            --region ${REGION} \
            --no-fail-on-empty-changeset
        - cd ../
    build:
      commands:
        - export PATH="$HOME/.local/bin:$PATH"

        # Lambdaの依存ライブラリをインストール
        - cd frontend/amplify/functions/sseFunction
        - npm ci --cache .npm --prefer-offline
        - cd ../../../

        # Amplifyのバックエンドをデプロイ
        - ls
        - npm ci --cache .npm --prefer-offline
        - npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID

        # amplify_outputs.jsonの存在確認
        - |
          if [ ! -f "amplify_outputs.json" ]; then
            echo "amplify_outputs.json not found"
            exit 1
          fi

        # amplify_outputs.jsonからCognitoのID情報を取得
        - |
          COGNITO_USER_POOL_ID=$(node -e \
            "console.log(JSON.parse(\
            require('fs').readFileSync(\
            'amplify_outputs.json')).auth.user_pool_id)")
        - |
          COGNITO_USER_POOL_CLIENT_ID=$(node -e \
            "console.log(JSON.parse(\
            require('fs').readFileSync(\
            'amplify_outputs.json')).auth.user_pool_client_id)")
        - echo "COGNITO_USER_POOL_ID=${COGNITO_USER_POOL_ID}"
        - echo "COGNITO_USER_POOL_CLIENT_ID=${COGNITO_USER_POOL_CLIENT_ID}"
        - cd ../

        # ソースコードをZIP化してS3にアップロード
        - cd agent
        - mkdir -p deployment_package
        - |
          uv pip install \
            --python-platform aarch64-manylinux2014 \
            --python-version 3.13 \
            --target=deployment_package \
            --only-binary=:all: \
            -r requirements.txt
        - cp main.py system_prompt.py deployment_package/
        - cd deployment_package
        - zip -r ../source.zip .
        - cd ..
        - aws s3 cp source.zip s3://${NAME_PREFIX}-source-bucket/source.zip
        - cd ../

        # AgentCore Runtimeをデプロイ
        - cd cfn
        - BUILD_TIMESTAMP=$(date +%Y%m%d-%H%M%S)
        - echo "BUILD_TIMESTAMP=${BUILD_TIMESTAMP}"
        - |
          aws cloudformation deploy  \
            --stack-name ${NAME_PREFIX}-bedrock-agentcore-runtime \
            --template-file agentcore.yaml \
            --parameter-overrides \
              NamePrefix=${NAME_PREFIX} \
              CognitoUserPoolId=${COGNITO_USER_POOL_ID} \
              CognitoUserPoolClientId=${COGNITO_USER_POOL_CLIENT_ID} \
              BuildTimestamp=${BUILD_TIMESTAMP} \
            --capabilities CAPABILITY_NAMED_IAM \
            --region ${REGION} \
            --no-fail-on-empty-changeset
        - cd ../

frontend:
  phases:
    preBuild:
      commands:
        - cd frontend
        - ls
        - npm ci
        # amplify_outputs.jsonからSSE関数URLを取得して.envを更新
        - |
          VITE_LAMBDA_ENDPOINT=$(node -e \
            "console.log(JSON.parse(\
            require('fs').readFileSync(\
            'amplify_outputs.json')).custom.sseFunctionUrl)")
          echo "VITE_LAMBDA_ENDPOINT=${VITE_LAMBDA_ENDPOINT}" > .env
    build:
      commands:
        - npm run build
        - ls
  artifacts:
    baseDirectory: frontend/dist
    files:
      - '**/*'
  cache:
    paths:
      - frontend/node_modules/**/*
      - frontend/dist/**/*

あとは、AWSマネジメントコンソールからAmplifyHostingにデプロイすれば完了です。

まとめ

今回でCICDやIaC周りがシンプルになりました!だいぶ、敷居が下がったんじゃないでしょうか。
「250MB」制限は気になりますが、PoCなどで簡単なAIエージェントを作ってみる分には気にならないと思います。CDKも対応したら今度こそCDK版でデプロイしたいと思います...

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?