[小ネタ] Bedrock AgentCore Starter Toolkitにcreateコマンドが追加されていたので試してみた
はじめに
こんにちは、コンサルティング部の神野です。いよいよあと2日で2025年も終わりですね。
Amazon Bedrock AgentCoreのブログをまだまだ今年中にいっぱい書きたいですが、来年の自分に託そうと諦めかけています。
今日、AgentCoreの公式ドキュメントを覗いてたらStarter Toolkitの実行するコマンドが変わっていて、びっくりしました。
今まではconfigureコマンドで設定を行い、launchデプロイを実施して・・・といった感じでしたが、ドキュメントを読むとconfigureコマンドではなく、createコマンドを実行していたので何が違うか気になります。
Starter ToolKitのGitHubを確認すると1ヶ月前にはcreateコマンド追加の変更が入っていました。
変更されたのは結構前だったんですね・・・気づかなかった。
先に結論
今回agentcore --helpを実行して、今までとの違いが気になったコマンドをまとめます。
createコマンド- ゼロからStrandsやBedrockを使用するコードのテンプレートを作成してくれます。今までの
configureコマンドはすでに実装していたコードをエントリーポイント指定するものだったので違いがあります。- なので、
configureコマンドがなくなるというより使い分けになるかと思います。- ゼロからテンプレートを活用してエージェントを作成したい→
createコマンド - 自分で作成したAIエージェントのコードをAgentCoreにホストしたい、
createで作った設定を変更したい→configureコマンド
- ゼロからテンプレートを活用してエージェントを作成したい→
- テンプレートから作成するにしても2種類から選択可能
- 本番環境を想定したテンプレートでCDKやTerraformコードも作成される。GatewayやMemory、Cognito認証も設定される設定のコード
- 検証用途。シンプルなテンプレートでサクッとエージェントを試すことができる。
- なので、
- ゼロからStrandsやBedrockを使用するコードのテンプレートを作成してくれます。今までの
devコマンド- ローカル上でAIエージェントのサーバーを起動して、リクエストを送ってテストすることを可能にします。
invokeコマンドに--devをつけることで起動した状態ならリクエストを送信できます。- コードの変更もホットローディング可能です。
Strands Agentsの場合、元々ローカルで動かせたので、agentcore devで特別新しいことができるようになったわけではないですね。
- ローカル上でAIエージェントのサーバーを起動して、リクエストを送ってテストすることを可能にします。
deployコマンド- 旧
launchコマンドと記載がありました。より名称が直感的に変わっただけでできることは特に変わっていないようです。いつか完全に名称が変わるかもしれませんね。
- 旧
今回はこのコマンド群を早速試してみます。
試してみる
環境構築
まずはプロジェクトフォルダを作成し、仮想環境をセットアップします。
mkdir agentcore-runtime-quickstart
cd agentcore-runtime-quickstart
python3 -m venv .venv
source .venv/bin/activate
続いて、pipをアップグレードして必要なパッケージをインストールします。
pip install --upgrade pip
pip install bedrock-agentcore strands-agents bedrock-agentcore-starter-toolkit
インストールが完了したら、agentcore --helpコマンドで確認してみます。
agentcore --help
Usage: agentcore [OPTIONS] COMMAND [ARGS]...
BedrockAgentCore CLI
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --help Show this message and exit. │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ──────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ create create an agentcore project │
│ dev Start a local development server for your agent with hot reloading. │
│ deploy Deploy Bedrock AgentCore with three deployment modes (formerly 'launch'). │
│ invoke Invoke Bedrock AgentCore endpoint. │
│ status Get Bedrock AgentCore status including config and runtime details. │
│ destroy Destroy Bedrock AgentCore resources. │
│ stop-session Stop an active runtime session. │
│ create_mcp_gateway Creates an MCP Gateway. │
│ create_mcp_gateway_target Creates an MCP Gateway Target. │
│ configure Configuration management │
│ identity Manage Identity service resources │
│ gateway Manage Bedrock AgentCore Gateways │
│ memory Manage Bedrock AgentCore Memory resources │
│ obs Query and visualize agent observability data (spans, traces, logs) │
│ policy Manage Bedrock AgentCore Policy Engines and Policies │
│ eval Evaluate agent performance using built-in and custom evaluators │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
確かにcreateとdevコマンドが追加されていますね!configureコマンドは無くなっているわけではなく変わらず使えそうです。
またlaunchコマンドもdeployコマンドといった名称に変わっていました。
機能的には一緒だと思いますが、地味に色々と変わっていますね。
agentcore create
それではagentcore createコマンドを実行してみます。このコマンドは対話形式でプロジェクトを作成できます。
agentcore create
まず対話型プロンプトの流れを説明してから、実際に2つのパターンで実行してみます。
対話型プロンプトの解説
agentcore createを実行すると、以下の質問が順番に表示されます。
1. Where should we create your new agent?
プロジェクトを作成するディレクトリ名を入力します。
ここで入力した名前がそのままプロジェクトフォルダ名になります。
Where should we create your new agent?
./neoAmber
すでにneoAmberといったフォルダ名が入っていたのでそのまま使用しました。
2. How would you like to start?
プロジェクトのテンプレートを選択します。
> ● A basic starter project (recommended)
○ A production-ready agent defined with Terraform or CDK
A basic starter project- すぐに始められるシンプルな構成。zipデプロイ(direct_code_deploy)です。A production-ready agent defined with Terraform or CDK- IaCで本番環境向けのリソース一式を構築できます。
3. What agent framework should we use?
エージェントフレームワークを選択します。
> ● Strands Agents SDK
○ Google Agent Development Kit
○ LangChain + LangGraph
○ Microsoft AutoGen
○ OpenAI Agents SDK
Strands以外のフレームワークも選択できるのは驚きました・・・!!
結構種類のサポートが手厚いですね。
4. Which model provider will power your agent?
モデルプロバイダーを選択します。今回はAmazon Bedrockを選択します。
> ● Amazon Bedrock
○ Anthropic
○ Google Gemini
○ OpenAI
5. What kind of memory should your agent have?
エージェントのメモリ設定を選択します。
> ● None
○ Short-term memory
○ Long-term and short-term memory
今回はメモリを使用しないので、Noneを選択します。
6. (IaCを選んだ場合のみ) Which IaC provider will define your AgentCore resources?
> ● Terraform
○ CDK
TerraformまたはCDKを選択します。
7. (IaCを選んだ場合のみ) Run agentcore configure first?
○ Yes
> ● No
configureコマンドを実行するか聞かれています。今回はNoとします。
8. Initialize a new git repository?
○ Yes
> ● No
gitリポジトリを初期化するかどうかを選択します。
ここからは、実際に2つのテンプレートパターンでプロジェクトを作成して、違いを確認していきます。
パターン1: A basic starter project
まずは推奨されているシンプルな構成である、A basic starter projectで作成してみます。
----------------------------------------------------------------------------------------------------
🤖 AgentCore activated. Let's build your agent.
----------------------------------------------------------------------------------------------------
Where should we create your new agent?
./neoAmber
How would you like to start?
A basic starter project (recommended)
What agent framework should we use?
Strands Agents SDK
Which model provider will power your agent?
Amazon Bedrock
What kind of memory should your agent have?
None
Initialize a new git repository?
No
Agent initializing...
• Template copied.
• Venv created and installed.
✓ Agent initialized.
----------------------------------------------------------------------------------------------------
You're ready to go! Happy building 🚀
Enter your project directory using cd neoAmber
Run agentcore dev to start the dev server
Log into AWS with aws login
Add memory with agentcore configure
Launch with agentcore deploy
----------------------------------------------------------------------------------------------------
プロジェクトが作成されました!生成されたファイルを確認してみましょう。
cd neoAmber && ls -la
total 1016
drwxr-xr-x 11 user staff 352 Dec 30 17:40 .
drwxr-xr-x 11 user staff 352 Dec 30 17:38 ..
-rw-r--r-- 1 user staff 1733 Dec 30 17:38 .bedrock_agentcore.yaml
-rw-r--r-- 1 user staff 323 Dec 30 17:38 .gitignore
drwxr-xr-x 8 user staff 256 Dec 30 17:38 .venv
-rw-r--r-- 1 user staff 1444 Dec 30 17:38 README.md
-rw-r--r-- 1 user staff 437 Dec 30 17:38 pyproject.toml
drwxr-xr-x 6 user staff 192 Dec 30 17:38 src
drwxr-xr-x 4 user staff 128 Dec 30 17:38 test
-rw-r--r-- 1 user staff 494510 Dec 30 17:38 uv.lock
.venvも自動で作成されているのが嬉しいですね。srcディレクトリの中身も確認してみます。
ls -la src
total 8
drwxr-xr-x 6 user staff 192 Dec 30 17:38 .
drwxr-xr-x 11 user staff 352 Dec 30 17:40 ..
-rw-r--r-- 1 user staff 2615 Dec 30 17:38 main.py
drwxr-xr-x 3 user staff 96 Dec 30 17:38 mcp_client
drwxr-xr-x 3 user staff 96 Dec 30 17:38 model
drwxr-xr-x 7 user staff 224 Dec 30 17:38 neoAmber.egg-info
生成されたsrc/main.pyを確認してみます。
import os
from strands import Agent, tool
from strands_tools.code_interpreter import AgentCoreCodeInterpreter
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from mcp_client.client import get_streamable_http_mcp_client
from model.load import load_model
app = BedrockAgentCoreApp()
log = app.logger
REGION = os.getenv("AWS_REGION")
# Import AgentCore Gateway as Streamable HTTP MCP Client
mcp_client = get_streamable_http_mcp_client()
# Define a simple function tool
@tool
def add_numbers(a: int, b: int) -> int:
"""Return the sum of two numbers"""
return a+b
@app.entrypoint
async def invoke(payload, context):
session_id = getattr(context, 'session_id', 'default')
# Create code interpreter
code_interpreter = AgentCoreCodeInterpreter(
region=REGION,
session_name=session_id,
auto_create=True,
persist_sessions=True
)
with mcp_client as client:
# Get MCP Tools
tools = client.list_tools_sync()
# Create agent
agent = Agent(
model=load_model(),
system_prompt="""
You are a helpful assistant with code execution capabilities. Use tools when appropriate.
""",
tools=[code_interpreter.code_interpreter, add_numbers] + tools
)
# Execute and format response
stream = agent.stream_async(payload.get("prompt"))
async for event in stream:
if "data" in event and isinstance(event["data"], str):
yield event["data"]
if __name__ == "__main__":
app.run()
Code InterpreterやMCP Clientまで含まれたコードが実装されていますね。結構充実した設定ですね。
.bedrock_agentcore.yamlも確認してみます。
default_agent: neoAmber_Agent
agents:
neoAmber_Agent:
name: neoAmber_Agent
entrypoint: /path/to/neoAmber/src/main.py
deployment_type: direct_code_deploy
runtime_type: PYTHON_3_10
platform: linux/arm64
aws:
execution_role: null
execution_role_auto_create: true
region: null
network_configuration:
network_mode: PUBLIC
observability:
enabled: true
memory:
mode: NO_MEMORY
identity:
credential_providers: []
is_generated_by_agentcore_create: true
deployment_typeがdirect_code_deployになっているのでzipデプロイですね。
デフォルトで作成されるとIAM認証なので、JWT認証に切り替えたい場合やPythonのランライムバージョンなどを変更したい場合は、今まで通りconfigureコマンドで設定変更は可能です。
agentcore configure -e src/main.py
パターン2: A production-ready agent (Terraform)
次に本番環境を想定した、A production-ready agent defined with Terraform or CDKを選択して作成してみます。
----------------------------------------------------------------------------------------------------
🤖 AgentCore activated. Let's build your agent.
----------------------------------------------------------------------------------------------------
Where should we create your new agent?
./deltaCyan
How would you like to start?
A production-ready agent defined with Terraform or CDK
What agent framework should we use?
Strands Agents SDK
Which model provider will power your agent?
Amazon Bedrock
Which IaC provider will define your AgentCore resources?
Terraform
Run agentcore configure first? (Further define configuration and reference existing resources like a JWT authorizer in the generated IaC?)
No
Initialize a new git repository?
No
Agent initializing...
• Template copied.
• Venv created and installed.
✓ Agent initialized.
----------------------------------------------------------------------------------------------------
You're ready to go! Happy building 🚀
Project Details
SDK Provider: Strands
Runtime Entrypoint: deltaCyan/src/main.py
IAC Entrypoint: deltaCyan/terraform/
Deployment: container
Configuration
Agent Name: deltaCyan_Agent
Gateway Name: deltaCyan-AgentCoreGateway
Gateway Authorization: Cognito
Network Mode: Public
Memory Name: deltaCyan_Memory
📄 Config saved to: deltaCyan/.bedrock_agentcore.yaml
Next Steps
cd deltaCyan
agentcore dev - Start local development server
Log into AWS with aws login
agentcore invoke --dev "Hello" - Test your agent locally
Deployment
cd terraform && terraform init && terraform apply - Deploy your project
agentcore invoke - Test your deployed agent
----------------------------------------------------------------------------------------------------
完了メッセージ違いますね!Terraformでのデプロイを勧められます。
こちらはDeployment: containerと表示されており、
Gateway、Memory、Cognito認証が自動で設定されていることがわかります。
生成されたファイルを確認してみましょう。
cd deltaCyan && ls -la
total 1024
drwxr-xr-x 14 user staff 448 Dec 30 18:00 .
drwxr-xr-x 12 user staff 384 Dec 30 18:00 ..
-rw-r--r-- 1 user staff 500 Dec 30 18:00 .bedrock_agentcore.yaml
-rw-r--r-- 1 user staff 150 Dec 30 18:00 .dockerignore
-rw-r--r-- 1 user staff 323 Dec 30 18:00 .gitignore
drwxr-xr-x 8 user staff 256 Dec 30 18:00 .venv
-rw-r--r-- 1 user staff 800 Dec 30 18:00 Dockerfile
-rw-r--r-- 1 user staff 1444 Dec 30 18:00 README.md
drwxr-xr-x 3 user staff 96 Dec 30 18:00 mcp
-rw-r--r-- 1 user staff 437 Dec 30 18:00 pyproject.toml
drwxr-xr-x 6 user staff 192 Dec 30 18:00 src
drwxr-xr-x 4 user staff 128 Dec 30 18:00 terraform
drwxr-xr-x 4 user staff 128 Dec 30 18:00 test
-rw-r--r-- 1 user staff 494510 Dec 30 18:00 uv.lock
Dockerfile、terraform/、mcp/ディレクトリが追加されていますね。
terraformディレクトリの中身も確認してみます。
ls -la terraform
total 32
drwxr-xr-x 6 user staff 192 Dec 30 18:00 .
drwxr-xr-x 14 user staff 448 Dec 30 18:00 ..
-rw-r--r-- 1 user staff 14325 Dec 30 18:00 bedrock_agentcore.tf
-rw-r--r-- 1 user staff 576 Dec 30 18:00 main.tf
-rw-r--r-- 1 user staff 248 Dec 30 18:00 terraform.tfvars
-rw-r--r-- 1 user staff 300 Dec 30 18:00 variables.tf
bedrock_agentcore.tfを見て、Terraformで自動生成されるリソースを確認してみましょう。
bedrock_agentcore.tf 全量
################################################################################
# ECR Repository
################################################################################
resource "aws_ecr_repository" "agentcore_terraform_runtime" {
name = "bedrock-agentcore/${lower(var.app_name)}"
image_tag_mutability = "MUTABLE"
image_scanning_configuration {
scan_on_push = true
}
encryption_configuration {
encryption_type = "KMS"
}
}
data "aws_ecr_authorization_token" "token" {}
locals {
src_files = fileset("../${path.root}/src", "**")
src_hashes = [
for f in local.src_files :
filesha256("../${path.root}/src/${f}")
]
# Collapse all file hashes into one
src_hash = sha256(join("", local.src_hashes))
}
resource "null_resource" "docker_image" {
depends_on = [aws_ecr_repository.agentcore_terraform_runtime]
triggers = {
src_hash = local.src_hash
}
provisioner "local-exec" {
interpreter = ["/bin/bash", "-c"]
command = <<EOF
source ~/.bash_profile || source ~/.profile || true
if ! command -v docker &> /dev/null; then
echo "Docker is not installed or not in PATH. Please install Docker and try again."
exit 1
fi
aws ecr get-login-password | docker login --username AWS --password-stdin ${data.aws_ecr_authorization_token.token.proxy_endpoint}
docker build -t ${aws_ecr_repository.agentcore_terraform_runtime.repository_url}:latest ../${path.root}
docker push ${aws_ecr_repository.agentcore_terraform_runtime.repository_url}:latest
EOF
}
}
################################################################################
# MCP Lambda Function
################################################################################
data "archive_file" "mcp_lambda_zip" {
type = "zip"
source_dir = "../${path.root}/mcp/lambda"
output_path = "../${path.root}/mcp_lambda.zip"
}
resource "aws_lambda_function" "mcp_lambda" {
function_name = "${var.app_name}-McpLambda"
role = aws_iam_role.mcp_lambda_role.arn
handler = "handler.lambda_handler"
runtime = "python3.12"
filename = data.archive_file.mcp_lambda_zip.output_path
source_code_hash = data.archive_file.mcp_lambda_zip.output_base64sha256
}
resource "aws_iam_role" "mcp_lambda_role" {
name = "${var.app_name}-McpLambdaRole"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}]
})
}
resource "aws_iam_role_policy_attachment" "mcp_lambda_basic" {
role = aws_iam_role.mcp_lambda_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
################################################################################
# AgentCore Gateway Roles
################################################################################
resource "aws_iam_role" "agentcore_gateway_role" {
name = "${var.app_name}-AgentCoreGatewayRole"
assume_role_policy = data.aws_iam_policy_document.bedrock_agentcore_assume_role.json
}
resource "aws_iam_role_policy_attachment" "agentcore_gateway_permissions" {
role = aws_iam_role.agentcore_gateway_role.name
policy_arn = "arn:aws:iam::aws:policy/BedrockAgentCoreFullAccess"
}
resource "aws_iam_role_policy" "agentcore_gateway_lambda_invoke" {
role = aws_iam_role.agentcore_gateway_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = ["lambda:InvokeFunction"]
Effect = "Allow"
Resource = [aws_lambda_function.mcp_lambda.arn]
}]
})
}
################################################################################
# AgentCore Gateway Inbound Auth - Cognito
################################################################################
resource "aws_cognito_user_pool" "cognito_user_pool" {
name = "${var.app_name}-CognitoUserPool"
}
resource "aws_cognito_resource_server" "cognito_resource_server" {
identifier = "${var.app_name}-CognitoResourceServer"
name = "${var.app_name}-CognitoResourceServer"
user_pool_id = aws_cognito_user_pool.cognito_user_pool.id
scope {
scope_description = "Basic access to ${var.app_name}"
scope_name = "basic"
}
}
resource "aws_cognito_user_pool_client" "cognito_app_client" {
name = "${var.app_name}-CognitoUserPoolClient"
user_pool_id = aws_cognito_user_pool.cognito_user_pool.id
generate_secret = true
allowed_oauth_flows = ["client_credentials"]
allowed_oauth_flows_user_pool_client = true
allowed_oauth_scopes = ["${aws_cognito_resource_server.cognito_resource_server.identifier}/basic"]
supported_identity_providers = ["COGNITO"]
}
resource "aws_cognito_user_pool_domain" "cognito_domain" {
domain = "${lower(var.app_name)}-${data.aws_region.current.region}"
user_pool_id = aws_cognito_user_pool.cognito_user_pool.id
}
locals {
cognito_discovery_url = "https://cognito-idp.${data.aws_region.current.region}.amazonaws.com/${aws_cognito_user_pool.cognito_user_pool.id}/.well-known/openid-configuration"
}
################################################################################
# AgentCore Gateway
################################################################################
resource "aws_bedrockagentcore_gateway" "agentcore_gateway" {
name = "${var.app_name}-Gateway"
protocol_type = "MCP"
role_arn = aws_iam_role.agentcore_gateway_role.arn
authorizer_type = "CUSTOM_JWT"
authorizer_configuration {
custom_jwt_authorizer {
discovery_url = local.cognito_discovery_url
allowed_clients = [aws_cognito_user_pool_client.cognito_app_client.id]
}
}
}
resource "aws_bedrockagentcore_gateway_target" "agentcore_gateway_lambda_target" {
name = "${var.app_name}-Target"
gateway_identifier = aws_bedrockagentcore_gateway.agentcore_gateway.gateway_id
credential_provider_configuration {
gateway_iam_role {}
}
target_configuration {
mcp {
lambda {
lambda_arn = aws_lambda_function.mcp_lambda.arn
tool_schema {
inline_payload {
name = "placeholder_tool"
description = "Placeholder tool (no-op)."
input_schema {
type = "object"
description = "Example input schema for placeholder tool"
property {
name = "string_param"
type = "string"
description = "Example string parameter."
}
property {
name = "int_param"
type = "integer"
description = "Example integer parameter."
}
property {
name = "float_array_param"
type = "array"
description = "Example float array parameter."
items {
type = "number"
}
}
}
}
}
}
}
}
}
################################################################################
# AgentCore Runtime IAM Roles
################################################################################
data "aws_iam_policy_document" "bedrock_agentcore_assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["bedrock-agentcore.amazonaws.com"]
}
}
}
resource "aws_iam_role" "agentcore_runtime_execution_role" {
name = "${var.app_name}-AgentCoreRuntimeRole"
description = "Execution role for Bedrock AgentCore Runtime"
assume_role_policy = data.aws_iam_policy_document.bedrock_agentcore_assume_role.json
}
# https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-permissions.html#runtime-permissions-execution
resource "aws_iam_role_policy" "agentcore_runtime_execution_role_policy" {
role = aws_iam_role.agentcore_runtime_execution_role.id
name = "${var.app_name}-AgentCoreRuntimeExecutionPolicy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "ECRImageAccess"
Effect = "Allow"
Action = [
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer",
]
Resource = [
"arn:aws:ecr:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:repository/*",
]
},
{
Effect = "Allow"
Action = [
"logs:DescribeLogStreams",
"logs:CreateLogGroup",
]
Resource = [
"arn:aws:logs:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:log-group:/aws/bedrock-agentcore/runtimes/*",
]
},
{
Effect = "Allow"
Action = [
"logs:DescribeLogGroups",
]
Resource = [
"arn:aws:logs:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:log-group:*",
]
},
{
Effect = "Allow"
Action = [
"logs:CreateLogStream",
"logs:PutLogEvents",
]
Resource = [
"arn:aws:logs:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*",
]
},
{
Sid = "ECRTokenAccess"
Effect = "Allow"
Action = [
"ecr:GetAuthorizationToken",
]
Resource = "*"
},
{
Effect = "Allow"
Action = [
"xray:PutTraceSegments",
"xray:PutTelemetryRecords",
"xray:GetSamplingRules",
"xray:GetSamplingTargets",
]
Resource = [
"*",
]
},
{
Effect = "Allow"
Resource = "*"
Action = "cloudwatch:PutMetricData"
Condition = {
StringEquals = {
"cloudwatch:namespace" = "bedrock-agentcore"
}
}
},
{
Sid = "GetAgentAccessToken"
Effect = "Allow"
Action = [
"bedrock-agentcore:GetWorkloadAccessToken",
"bedrock-agentcore:GetWorkloadAccessTokenForJWT",
"bedrock-agentcore:GetWorkloadAccessTokenForUserId",
]
Resource = [
"arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default",
"arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default/workload-identity/agentName-*",
]
},
{
Sid = "BedrockModelInvocation"
Effect = "Allow"
Action = [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream",
]
Resource = [
"arn:aws:bedrock:*::foundation-model/*",
"arn:aws:bedrock:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:*",
]
},
]
})
}
################################################################################
# AgentCore Memory
################################################################################
resource "aws_bedrockagentcore_memory" "agentcore_memory" {
name = "deltaCyan_Memory"
description = "Memory resource with 30 days event expiry"
event_expiry_duration = 30
}
# Add a built-in strategy from https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/built-in-strategies.html or define a custom one
# Example of adding semantic memory
# resource "aws_bedrockagentcore_memory_strategy" "semantic" {
# name = "semantic-strategy"
# memory_id = aws_bedrockagentcore_memory.agentcore_memory.id
# type = "SEMANTIC"
# description = "Semantic understanding strategy"
# namespaces = ["default"]
# }
################################################################################
# AgentCore Runtime
################################################################################
resource "aws_bedrockagentcore_agent_runtime" "agentcore_runtime" {
agent_runtime_name = "deltaCyan_Agent"
role_arn = aws_iam_role.agentcore_runtime_execution_role.arn
agent_runtime_artifact {
container_configuration {
container_uri = "${aws_ecr_repository.agentcore_terraform_runtime.repository_url}:latest"
}
}
depends_on = [null_resource.docker_image, aws_bedrockagentcore_memory.agentcore_memory]
network_configuration {
network_mode = "PUBLIC"
}
environment_variables = {
AWS_REGION = data.aws_region.current.region
MEMORY_ID = aws_bedrockagentcore_memory.agentcore_memory.id
GATEWAY_URL = aws_bedrockagentcore_gateway.agentcore_gateway.gateway_url
COGNITO_CLIENT_ID = aws_cognito_user_pool_client.cognito_app_client.id
COGNITO_CLIENT_SECRET = aws_cognito_user_pool_client.cognito_app_client.client_secret
COGNITO_TOKEN_URL = "https://${aws_cognito_user_pool_domain.cognito_domain.domain}.auth.${data.aws_region.current.region}.amazoncognito.com/oauth2/token"
COGNITO_SCOPE = "${aws_cognito_resource_server.cognito_resource_server.identifier}/basic"
}
}
################################################################################
# AgentCore Runtime Endpoints
################################################################################
resource "aws_bedrockagentcore_agent_runtime_endpoint" "dev_endpoint" {
name = "DEV"
agent_runtime_id = aws_bedrockagentcore_agent_runtime.agentcore_runtime.agent_runtime_id
agent_runtime_version = var.agent_runtime_version
}
resource "aws_bedrockagentcore_agent_runtime_endpoint" "prod_endpoint" {
name = "PROD"
agent_runtime_id = aws_bedrockagentcore_agent_runtime.agentcore_runtime.agent_runtime_id
agent_runtime_version = var.agent_runtime_version
depends_on = [aws_bedrockagentcore_agent_runtime_endpoint.dev_endpoint] # Prevents ConflictException
}
Terraformで作成されるリソース
bedrock_agentcore.tfを確認すると以下のリソースが定義されています。
| リソース | 説明 |
|---|---|
| ECRリポジトリ | Dockerイメージを格納するリポジトリ |
| Docker イメージビルド | null_resourceでビルド・プッシュを自動化 |
| MCP Lambda関数 | MCPツールを提供するLambda関数 |
| Cognito User Pool | ユーザー認証用のCognitoリソース一式 |
| Cognito Resource Server | OAuth2スコープの定義 |
| Cognito App Client | クライアント認証情報 |
| AgentCore Gateway | MCP Gatewayとターゲット設定 |
| AgentCore Memory | 30日間のイベント保持設定 |
| AgentCore Runtime | コンテナベースのランタイム |
| Runtime Endpoints | DEVとPROD の2つのエンドポイント |
本番環境に必要なリソースが一式揃っていますね。結構多くのリソースが作られていてびっくりしました。
IaCで一式作るのは自分で作るのは手間なので、一式作ってもらえるのはありがたい気がします。
ソースコードの違い
生成されるsrc/main.pyも両パターンで地味に異なります。主な違いを見てみましょう。
パターン1(Basic Starter)のmain.py
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from mcp_client.client import get_streamable_http_mcp_client
# Import AgentCore Gateway as Streamable HTTP MCP Client
mcp_client = get_streamable_http_mcp_client()
@app.entrypoint
async def invoke(payload, context):
# ...
agent = Agent(
model=load_model(),
system_prompt="...",
tools=[code_interpreter.code_interpreter, add_numbers] + tools
)
パターン2(Terraform/CDK)のmain.py
from bedrock_agentcore import BedrockAgentCoreApp
from bedrock_agentcore.memory.integrations.strands.config import AgentCoreMemoryConfig, RetrievalConfig
from bedrock_agentcore.memory.integrations.strands.session_manager import AgentCoreMemorySessionManager
from .mcp_client.client import get_streamable_http_mcp_client
MEMORY_ID = os.getenv("BEDROCK_AGENTCORE_MEMORY_ID")
if os.getenv("LOCAL_DEV") == "1":
# ローカル開発時はダミーのMCPクライアントを使用
from contextlib import nullcontext
from types import SimpleNamespace
strands_mcp_client = nullcontext(SimpleNamespace(list_tools_sync=lambda: []))
else:
strands_mcp_client = get_streamable_http_mcp_client()
@app.entrypoint
async def invoke(payload, context):
# Memory設定(MEMORY_IDが設定されている場合)
session_manager = None
if MEMORY_ID:
session_manager = AgentCoreMemorySessionManager(
AgentCoreMemoryConfig(
memory_id=MEMORY_ID,
session_id=session_id,
actor_id="quickstart-user",
retrieval_config={...}
),
REGION
)
agent = Agent(
model=load_model(),
session_manager=session_manager, # Memory統合
system_prompt="...",
tools=[code_interpreter.code_interpreter, add_numbers] + tools
)
MCPクライアント(Gateway連携)の違い
mcp_client/client.pyも大きく異なります。
パターン1ではサンプルのMCPエンドポイント(ExaAI)を直接使用しています。
from mcp.client.streamable_http import streamablehttp_client
from strands.tools.mcp.mcp_client import MCPClient
# ExaAIのサンプルエンドポイント(認証不要)
EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
def get_streamable_http_mcp_client() -> MCPClient:
return MCPClient(lambda: streamablehttp_client(EXAMPLE_MCP_ENDPOINT))
パターン2ではTerraformでデプロイされたAgentCore GatewayにCognito認証でアクセスします。
import os
from mcp.client.streamable_http import streamablehttp_client
from strands.tools.mcp.mcp_client import MCPClient
import requests
COGNITO_TOKEN_URL = os.getenv("COGNITO_TOKEN_URL")
COGNITO_CLIENT_ID = os.getenv("COGNITO_CLIENT_ID")
COGNITO_CLIENT_SECRET = os.getenv("COGNITO_CLIENT_SECRET")
COGNITO_SCOPE = os.getenv("COGNITO_SCOPE")
def _get_access_token():
"""Cognito OAuth トークンを取得"""
response = requests.post(
COGNITO_TOKEN_URL,
auth=(COGNITO_CLIENT_ID, COGNITO_CLIENT_SECRET),
data={"grant_type": "client_credentials", "scope": COGNITO_SCOPE},
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
return response.json()["access_token"]
def get_streamable_http_mcp_client() -> MCPClient:
gateway_url = os.getenv("GATEWAY_URL")
access_token = _get_access_token()
return MCPClient(lambda: streamablehttp_client(
gateway_url,
headers={"Authorization": f"Bearer {access_token}"}
))
主な違いのポイント
| 項目 | パターン1 | パターン2 |
|---|---|---|
| MCP Gateway | サンプル(ExaAI)を直接使用 | TerraformでデプロイしたGatewayを使用 |
| Gateway認証 | なし | Cognito OAuth(client_credentials) |
| Memory統合 | なし | AgentCoreMemorySessionManagerで統合済み |
| ローカル開発対応 | そのまま実行 | LOCAL_DEV環境変数でダミーMCPクライアント切替 |
| 必要な環境変数 | なし | GATEWAY_URL, COGNITO_*, MEMORY_ID |
パターン2はMemory機能とGateway認証が最初から組み込まれており、Terraformでリソースがデプロイされ、Cognito認証情報が環境変数で渡されることを前提としたコードになっています。
結構作り込まれていますね。本番環境でそのまま使えるかはさておき雛形として参考にするのはアリですね。
参考にしつつパターン1の方に必要なものを取り込んでいくとかもアリな気がします。
また違う機会にこの本番環境用createで作成されたリソースについて深掘りしたいですね。
今回はパターン1のシンプルな方をそのまま使って検証を行なっていきます。
agentcore dev
次にagentcore devコマンドでローカル開発サーバーを起動してみます。
createコマンドで作成されたプロジェクトディレクトリに移動して実行します。
cd neoAmber
agentcore dev
agentcore dev
🚀 Starting development server with hot reloading
Agent: neoAmber_Agent
Module: src.main:app
💡 Test your agent with: agentcore invoke --dev "Hello" in a new terminal window
ℹ️ This terminal window will be used to run the dev server
Press Ctrl+C to stop the server
Server will be available at:
• Localhost: http://localhost:8080/invocations
• 127.0.0.1: http://127.0.0.1:8080/invocations
• Local network: http://172.16.0.2:8080/invocations
warning: `VIRTUAL_ENV=/path/to/project/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
INFO: Will watch for changes in these directories: ['/path/to/project/neoAmber']
INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
INFO: Started reloader process [85374] using StatReload
INFO: Started server process [85377]
INFO: Waiting for application startup.
INFO: Application startup complete.
ローカルサーバーが起動しました!hot reloadingもサポートされているようで、
コードを変更すると自動で再読み込みしてくれます。
別のターミナルでagentcore invoke --devコマンドを実行してテストしてみます。
agentcore invoke --dev "こんにちは"
✓ Response from dev server:
こんにちは!👋
お元気ですか?何かお手伝いできることはありますか?
私はコード実行、ウェブ検索、プログラミングに関する質問への回答など、様々なことをサポートできます。お気軽にお尋ねください!
問題なくローカルで動作確認できましたね!
ただ、正直なところStrands Agentsだったら元々ローカルで動かせたので、agentcore devで特別新しいことができるようになったわけではありません。Starter Toolkitのコマンドに組み込まれて少し便利になった、という程度の変更ですね。
agentcore deploy
ローカルでの動作確認ができたので、次はagentcore deployコマンドでAWSにデプロイしてみます。
agentcore deploy
agentcore deploy
🚀 Launching Bedrock AgentCore (cloud mode - RECOMMENDED)...
• Deploy Python code directly to runtime
• No Docker required (DEFAULT behavior)
• Production-ready deployment
💡 Deployment options:
• agentcore deploy → Cloud (current)
• agentcore deploy --local → Local development
⠇ Launching Bedrock AgentCore...Launching with direct_code_deploy deployment for agent 'neoAmber_Agent'
Memory disabled - skipping memory creation
Ensuring execution role...
Getting or creating execution role for agent: neoAmber_Agent
Using AWS region: us-west-2, account ID: xxxxxxxxxxxx
Role name: AmazonBedrockAgentCoreSDKRuntime-us-west-2-xxxxxxxxxx
⠙ Launching Bedrock AgentCore...Role doesn't exist, creating new execution role: AmazonBedrockAgentCoreSDKRuntime-us-west-2-xxxxxxxxxx
Starting execution role creation process for agent: neoAmber_Agent
✓ Role creating: AmazonBedrockAgentCoreSDKRuntime-us-west-2-xxxxxxxxxx
Creating IAM role: AmazonBedrockAgentCoreSDKRuntime-us-west-2-xxxxxxxxxx
⠼ Launching Bedrock AgentCore...✓ Role created: arn:aws:iam::xxxxxxxxxxxx:role/AmazonBedrockAgentCoreSDKRuntime-us-west-2-xxxxxxxxxx
⠋ Launching Bedrock AgentCore...✓ Execution policy attached: BedrockAgentCoreRuntimeExecutionPolicy-neoAmber_Agent
Role creation complete and ready for use with Bedrock AgentCore
Execution role available: arn:aws:iam::xxxxxxxxxxxx:role/AmazonBedrockAgentCoreSDKRuntime-us-west-2-xxxxxxxxxx
Using entrypoint: main.py (relative to /path/to/project/neoAmber/src)
Creating deployment package...
📦 No cached dependencies found, will build
Building dependencies (this may take a minute)...
Resolving pyproject.toml with uv...
⠦ Launching Bedrock AgentCore...✓ Dependencies resolved with uv
Building dependencies for Linux ARM64 Runtime (manylinux2014_aarch64)
Installing dependencies with uv for aarch64-manylinux2014 (cross-compiling for Linux ARM64)...
⠴ Launching Bedrock AgentCore...✓ Dependencies installed with uv
Creating dependencies.zip...
⠼ Launching Bedrock AgentCore...✓ Dependencies cached
Packaging source code...
Creating deployment package...
⠸ Launching Bedrock AgentCore...✓ Deployment package ready: 50.16 MB
Getting or creating S3 bucket for agent: neoAmber_Agent
✅ Reusing existing S3 bucket:
bedrock-agentcore-codebuild-sources-xxxxxxxxxxxx-us-west-2
⠸ Launching Bedrock AgentCore...S3 bucket available: s3://bedrock-agentcore-codebuild-sources-xxxxxxxxxxxx-us-west-2
Uploading deployment package to S3...
Uploading to s3://bedrock-agentcore-codebuild-sources-xxxxxxxxxxxx-us-west-2/neoAmber_Agent/deployment.zip...
⠧ Launching Bedrock AgentCore...✓ Deployment package uploaded: s3://bedrock-agentcore-codebuild-sources-xxxxxxxxxxxx-us-west-2/neoAmber_Agent/deployment.zip
Deploying to Bedrock AgentCore Runtime...
OpenTelemetry instrumentation enabled (aws-opentelemetry-distro detected)
⠹ Launching Bedrock AgentCore...✅ Agent created/updated: arn:aws:bedrock-agentcore:us-west-2:xxxxxxxxxxxx:runtime/neoAmber_Agent-XXXXXXXXXX
Waiting for agent endpoint to be ready...
⠧ Launching Bedrock AgentCore...Enabling observability...
⠧ Launching Bedrock AgentCore...CloudWatch Logs resource policy already configured
⠴ Launching Bedrock AgentCore...X-Ray trace destination already configured
⠏ Launching Bedrock AgentCore...X-Ray indexing rule already configured
Transaction Search already fully configured
🔍 GenAI Observability Dashboard: https://console.aws.amazon.com/cloudwatch/home?region=us-west-2#gen-ai-observability/agent-core
✅ Deployment completed successfully - Agent: arn:aws:bedrock-agentcore:us-west-2:xxxxxxxxxxxx:runtime/neoAmber_Agent-XXXXXXXXXX
╭────────────────────────── Deployment Success ───────────────────────────╮
│ Agent Details: │
│ Agent Name: neoAmber_Agent │
│ Agent ARN: │
│ arn:aws:bedrock-agentcore:us-west-2:xxxxxxxxxxxx:runtime/neoAmber_Agent │
│ -XXXXXXXXXX │
│ Deployment Type: Direct Code Deploy │
│ │
│ 📦 Code package deployed to Bedrock AgentCore │
│ │
│ Next Steps: │
│ agentcore status │
│ agentcore invoke '{"prompt": "Hello"}' │
│ │
│ 📋 CloudWatch Logs: │
│ /aws/bedrock-agentcore/runtimes/neoAmber_Agent-XXXXXXXXXX-DEFAULT │
│ --log-stream-name-prefix "2025/12/30/[runtime-logs" │
│ /aws/bedrock-agentcore/runtimes/neoAmber_Agent-XXXXXXXXXX-DEFAULT │
│ --log-stream-names "otel-rt-logs" │
│ │
│ 🔍 GenAI Observability Dashboard: │
│ https://console.aws.amazon.com/cloudwatch/home?region=us-west-2#gen- │
│ ai-observability/agent-core │
│ │
│ ⏱️ Note: Observability data may take up to 10 minutes to appear after │
│ first launch │
│ │
│ 💡 Tail logs with: │
│ aws logs tail │
│ /aws/bedrock-agentcore/runtimes/neoAmber_Agent-XXXXXXXXXX-DEFAULT │
│ --log-stream-name-prefix "2025/12/30/[runtime-logs" --follow │
│ aws logs tail │
│ /aws/bedrock-agentcore/runtimes/neoAmber_Agent-XXXXXXXXXX-DEFAULT │
│ --log-stream-name-prefix "2025/12/30/[runtime-logs" --since 1h │
╰─────────────────────────────────────────────────────────────────────────╯
デプロイが完了しました!以前のlaunchコマンドと全く同じですね。コマンドの名前だけが変わったみたいですね。
ちなみにlaunchコマンドも変わらず使用できました。
そうなのか・・・いつか完全に名称が変わる可能性もありますね。
agentcore launch
🚀 Launching Bedrock AgentCore (cloud mode - RECOMMENDED)...
• Deploy Python code directly to runtime
• No Docker required (DEFAULT behavior)
• Production-ready deployment
💡 Deployment options:
• agentcore deploy → Cloud (current)
• agentcore deploy --local → Local development
Launching with direct_code_deploy deployment for agent 'neoAmber_Agent'
Memory disabled - skipping memory creation
Ensuring execution role...
Using execution role from config: arn:aws:iam::xxxxxxxxxxxx:role/AmazonBedrockAgentCoreSDKRuntime-us-west-2-xxxxxxxxxx
Using entrypoint: main.py (relative to /path/to/project/neoAmber/src)
Creating deployment package...
✓ Using cached dependencies (no changes detected)
Packaging source code...
Creating deployment package...
⠴ Launching Bedrock AgentCore...✓ Deployment package ready: 50.16 MB
Uploading deployment package to S3...
⠦ Launching Bedrock AgentCore...Uploading to s3://bedrock-agentcore-codebuild-sources-xxxxxxxxxxxx-us-west-2/neoAmber_Agent/deployment.zip...
⠴ Launching Bedrock AgentCore...✓ Deployment package uploaded: s3://bedrock-agentcore-codebuild-sources-xxxxxxxxxxxx-us-west-2/neoAmber_Agent/deployment.zip
Deploying to Bedrock AgentCore Runtime...
OpenTelemetry instrumentation enabled (aws-opentelemetry-distro detected)
⠇ Launching Bedrock AgentCore...⚠️ Session ID will be reset to connect to the updated agent. The previous agent remains accessible via the original session ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
✅ Agent created/updated: arn:aws:bedrock-agentcore:us-west-2:xxxxxxxxxxxx:runtime/neoAmber_Agent-XXXXXXXXXX
Waiting for agent endpoint to be ready...
⠏ Launching Bedrock AgentCore...Enabling observability...
⠋ Launching Bedrock AgentCore...CloudWatch Logs resource policy already configured
⠧ Launching Bedrock AgentCore...X-Ray trace destination already configured
⠙ Launching Bedrock AgentCore...X-Ray indexing rule already configured
Transaction Search already fully configured
🔍 GenAI Observability Dashboard: https://console.aws.amazon.com/cloudwatch/home?region=us-west-2#gen-ai-observability/agent-core
✅ Deployment completed successfully - Agent: arn:aws:bedrock-agentcore:us-west-2:xxxxxxxxxxxx:runtime/neoAmber_Agent-XXXXXXXXXX
╭────────────────────────── Deployment Success ───────────────────────────╮
│ Agent Details: │
│ Agent Name: neoAmber_Agent │
│ Agent ARN: │
│ arn:aws:bedrock-agentcore:us-west-2:xxxxxxxxxxxx:runtime/neoAmber_Agent │
│ -XXXXXXXXXX │
│ Deployment Type: Direct Code Deploy │
│ │
│ 📦 Code package deployed to Bedrock AgentCore │
│ │
│ Next Steps: │
│ agentcore status │
│ agentcore invoke '{"prompt": "Hello"}' │
│ │
│ 📋 CloudWatch Logs: │
│ /aws/bedrock-agentcore/runtimes/neoAmber_Agent-XXXXXXXXXX-DEFAULT │
│ --log-stream-name-prefix "2025/12/30/[runtime-logs" │
│ /aws/bedrock-agentcore/runtimes/neoAmber_Agent-XXXXXXXXXX-DEFAULT │
│ --log-stream-names "otel-rt-logs" │
│ │
│ 🔍 GenAI Observability Dashboard: │
│ https://console.aws.amazon.com/cloudwatch/home?region=us-west-2#gen- │
│ ai-observability/agent-core │
│ │
│ ⏱️ Note: Observability data may take up to 10 minutes to appear after │
│ first launch │
│ │
│ 💡 Tail logs with: │
│ aws logs tail │
│ /aws/bedrock-agentcore/runtimes/neoAmber_Agent-XXXXXXXXXX-DEFAULT │
│ --log-stream-name-prefix "2025/12/30/[runtime-logs" --follow │
│ aws logs tail │
│ /aws/bedrock-agentcore/runtimes/neoAmber_Agent-XXXXXXXXXX-DEFAULT │
│ --log-stream-name-prefix "2025/12/30/[runtime-logs" --since 1h │
╰─────────────────────────────────────────────────────────────────────────╯
デプロイしたエージェントをテストしてみます。
agentcore invoke "こんにちは"
こんにちは!お手伝いできることはありますか?😊
プログラミング、データ分析、計算、ウェブ検索など、様々なタスクをサポートできます。何かご質問やご依頼があれば、お気軽にお聞かせください。
╭──────────────────────────── neoAmber_Agent ─────────────────────────────╮
│ Session: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │
│ ARN: │
│ arn:aws:bedrock-agentcore:us-west-2:xxxxxxxxxxxx:runtime/neoAmber_Agent │
│ -XXXXXXXXXX │
│ Logs: aws logs tail │
│ /aws/bedrock-agentcore/runtimes/neoAmber_Agent-XXXXXXXXXX-DEFAULT │
│ --log-stream-name-prefix "2025/12/30/[runtime-logs" --follow │
│ aws logs tail │
│ /aws/bedrock-agentcore/runtimes/neoAmber_Agent-XXXXXXXXXX-DEFAULT │
│ --log-stream-name-prefix "2025/12/30/[runtime-logs" --since 1h │
│ GenAI Dashboard: │
│ https://console.aws.amazon.com/cloudwatch/home?region=us-west-2#gen-ai- │
│ observability/agent-core │
╰─────────────────────────────────────────────────────────────────────────╯
問題なくデプロイしたエージェントが動作していますね!
おわりに
Starter Toolkitの新しいコマンドを試してみました。
createコマンドの選択肢の多さにびっくりしました。色々と試してどういったテンプレートなのかもう少し深掘りしたいですね。特に本番環境用のテンプレートはもう少し検証したいと思いました。IaCのコードを提供してくれるのはありがたいですね。Memory、Gatewayなどの各種サービスの連携も実装されているのはびっくりしました。
ただ、今回追加されたコマンドがあるからといって今までのコマンドが使えなくなるわけではなさそうなので安心しました。特にcreateコマンドとconfigureコマンドは用途による棲み分けになるかなといった印象です。
Starter Toolkitもどんどん便利になってきているので、改めて何ができるか徹底的に深掘りしたいですね。
本記事が少しでも参考になりましたら幸いです。最後までご覧いただきありがとうございましたー!








