[アップデート] Amazon Bedrock AgentCore Runtimeでzipファイルによるコードデプロイがサポートされました
はじめに
こんにちは、スーパーマーケットが好きなコンサルティング部の神野です。
Amazon Bedrock AgentCore Runtimeでzipファイルによるコードデプロイもサポートされました!!
今まではECRにコンテナイメージをプッシュしてURLを指定して作成する形だったので、今回新しく直接zipやテンプレートから作成も対応した形となります。より簡単にAIエージェントが展開できるようになりましたね。
早速試してみたいと思います!!
コンソール画面から作成してみる
Amazon Bedrock AgentCoreの画面から作成を進めていきます。
エージェントランタイム > ホストエージェントボタンを選択します。

すると今までとは異なった見慣れない画面が表示されました。Source typeが増えています。

ここが今回追加されたアップデートになります。S3を介してソースコードをアップロードできるようになりました。
S3 Source の場合は 3つの選択肢から選ぶ形となります。
- Start with a template
- テンプレートを作成 & テンプレートのソースコードを格納するS3バケットも作成してすぐにRuntimeが使えるようになります
- もちろん既存のS3バケットを指定でも問題ないです
- テンプレートを作成 & テンプレートのソースコードを格納するS3バケットも作成してすぐにRuntimeが使えるようになります
- Upload to S3
- 既存のAIエージェントのコードが存在すればファイルアップロードしてRuntimeが使えるようになります
- Agent entry pointでエージェントのエントリーポイントファイルを指定して使用することができます
- 既存のAIエージェントのコードが存在すればファイルアップロードしてRuntimeが使えるようになります
- Choose from an existing S3 bucket
- すでにS3バケットに処理ファイルをアップロード済みであればこちらを選択して、指定のS3 URIを指定します。
今回はStart with a templateとUpload to S3でZipアップロードを試してみたいと思います。
Start with a template
S3 ConfigurationにStart with a templateを選択して進めていきます。特に何も変更せず、そのままホストエージェントボタンを選択します。

ちなみにテンプレートはStrands agents 、Otel agent 、Streaming agentが選択可能ですが、全部Strands Agentsのテンプレートが表示されていました。またStrandsとOtelはテンプレートの中身が同じで、Streamingはストリーミングで返信できるような作りになっていました。StrandsとOtelの違いは・・・??となりましたがそれぞれダウンロードしてrequirements.txtを確認したら、aws_opentelemetry_distroが含まれているかいないかの違いでした。Otel agentだとaws_opentelemetry_distroが含まれていて、トレースできるようになっているんですね。
今回はStreamを選択しました。
Strands、Otel agentのテンプレート
from bedrock_agentcore import BedrockAgentCoreApp
from strands import Agent
app = BedrockAgentCoreApp()
agent = Agent()
@app.entrypoint
def invoke(payload):
"""Your AI agent function"""
user_message = payload.get("prompt", "Hello! How can I help you today?")
result = agent(user_message)
return {"result": result.message}
if __name__ == "__main__":
app.run()
Streaming agentのテンプレート
from strands import Agent
from bedrock_agentcore import BedrockAgentCoreApp
app = BedrockAgentCoreApp()
agent = Agent()
@app.entrypoint
async def agent_invocation(payload):
"""Handler for agent invocation"""
user_message = payload.get(
"prompt", "No prompt found in input, please guide customer to create a json payload with prompt key"
)
stream = agent.stream_async(user_message)
async for event in stream:
print(event)
yield (event)
if __name__ == "__main__":
app.run()
ホストエージェントボタンを選択すると下記のようなバナーが出てしばらく待ちます。

正常にデプロイできたらテストエンドポイントを試してみます。

下記プロンプトを入れて、実行 ボタンを押してみます。
{"prompt":"こんにちは"}

問題なく結果が返ってきました!テンプレートから作成してすぐ実行できるのはお手軽ですね。
テンプレートが作ったzipファイルもS3からダウンロードして解凍して中身を確認すると、main.pyと依存関係のパッケージが入った状態でした。下記のような感じです。

なのでこのテンプレートを更新したいとなるとダウンロードしてmain.pyの中身を修正して、再度アップロードを試してみます。
システムプロンプトにキザなセリフで返信してと入れます。
from strands import Agent
from bedrock_agentcore import BedrockAgentCoreApp
app = BedrockAgentCoreApp()
# システムプロンプトを追加
agent = Agent(system_prompt="ユーザーからの質問に対しては必ずキザに返信してください。")
@app.entrypoint
async def agent_invocation(payload):
"""Handler for agent invocation"""
user_message = payload.get(
"prompt",
"No prompt found in input, please guide customer to create a json payload with prompt key",
)
stream = agent.stream_async(user_message)
async for event in stream:
print(event)
yield (event)
if __name__ == "__main__":
app.run()
修正したものを、依存関係含めて再度zip化してアップロードします。
zip -r xxx-stream_agent xxx-stream_agent_v2

アップロードが完了したら、ホスティングをアップデートボタンを選択します。

選択後はChoose from an existing S3 bucketが選択されているので、先ほどアップロードしたzipファイルのS3 URIを指定します。

そしてホストエージェントボタンを選択します。バージョンが新しいものに切り替わったらテストエンドポイントを選択します。(めちゃくちゃスクリーンショット上のバージョンが進んでいますが、zip化した際に階層が深くなってしまいエラーになってしまっていたためです)

再度こんにちはと挨拶してみます。

めちゃくちゃキザなセリフが返ってきましたね。テンプレートから作成した場合はこう言ったステップで更新するだと理解しました。オブジェクトバージョンも指定できたので、ファイル名も変えなくても同ファイルでアップロードしてバージョンを更新してデプロイって手法も取れそうですね。
次は自分でエージェントを作成して、zip化して作成してみます。
Upload to S3
まずは使用したライブラリなどの前提です。
- Python
- 3.13
- uv
- 0.6.12
uvについては、Pythonのパッケージ管理を行えるツールです。
インストールしていない方で今回使用する場合は、公式ドキュメントを参照してインストールしてください。
プロジェクトのセットアップ
それでは早速エージェントを作成していきます。まずはプロジェクトを初期化します。
uv init agentcore-zip --python 3.13
cd agentcore-zip
次に必要なパッケージをインストールします。Strands AgentsとAgentCoreのSDKですね。
uv add bedrock-agentcore strands-agents
エントリーポイントになるmain.pyを作成します。今回はシンプルにユーザーの質問に答えるストリーミングエージェントを作成してみます。
from strands import Agent
from bedrock_agentcore import BedrockAgentCoreApp
app = BedrockAgentCoreApp(debug=True)
agent = Agent(
system_prompt="あなたは親切で丁寧なアシスタントです。ユーザーの質問に分かりやすく答えてください。"
)
@app.entrypoint
async def agent_invocation(payload):
"""Handler for agent invocation"""
user_message = payload.get(
"prompt",
"No prompt found in input, please guide customer to create a json payload with prompt key",
)
app.logger.info(f"User message: {user_message}")
stream = agent.stream_async(user_message)
async for event in stream:
print(event)
yield (event)
if __name__ == "__main__":
app.run()
ローカルでテストしてみる
デプロイする前に、ローカルで動作確認してみましょう。
uv run main.py
別のターミナルを開いて、curlでテストしてみます。
curl -X POST http://localhost:8080/invocations \
-H "Content-Type: application/json" \
-d '{"prompt": "こんにちは!"}'
下記のように問題なくレスポンスが返ってきたら、Ctrl+Cでエージェントを停止します。

依存関係パッケージング
依存関係をzip化したいのですが、今回ここが重要なポイントになります。
Amazon Bedrock AgentCore RuntimeはARM64アーキテクチャで動作しているため、依存関係も必ずARM64向けにビルドする必要があります。x86_64向けにビルドされたパッケージをアップロードすると、デプロイ時やランタイム実行時にエラーが発生してしまいます。
より詳しい注意点などは公式ドキュメントにも記載があるので、必要に応じてご参照ください。
まずは依存関係をダウンロードするためのディレクトリを作成します。
mkdir deployment_package
次に、uvを使用してARM64向けに依存関係をインストールします。--python-platformオプションでARM64向けのパッケージを指定しています。
uv pip install \
--python-platform aarch64-manylinux2014 \
--python-version 3.13 \
--target=deployment_package \
--only-binary=:all: \
-r pyproject.toml
これで関連するパッケージはダウンロードできたので、エントリーポイントであるmain.pyもdeployment_packageディレクトリ内に移動してからzip化します。
# ファイルコピー
cp main.py deployment_package/
# zip化
cd deployment_package
zip -r ../deployment_package.zip .
cd ..
これで準備完了です!!コンソール上からアップロードしてみます。
ファイルアップロード
今回はS3 ConfigurationにUpload to S3を選択します。
選択した後は、zip化したパッケージをアップロードして、エントリーポイントにmain.pyを指定します。

ホストランタイムボタンを押して、デプロイが完了したらテストエンドポイントを押して試してみます。

こんにちはと挨拶して試してみます。

問題なく実行できました!パッケージ化してデプロイする方法の流れも理解できましたね。
パッケージ化するところが若干ハマりそうかつ、更新するたびに同じ作業するならシェルで自動化とか工夫する余地もあるかなと感じました。
Starter Toolkitによる直接デプロイ
今までコンソール上でデプロイしていましたが、Starter Toolkitでもzipアップロード対応しています。
前述したデプロイのためのパッケージ化対応しなくてよくなるのでしょうか。
まずパッケージにbedrock-agentcore-starter-toolkitを追加してagentcoreコマンドを使えるようにします。
uv add bedrock-agentcore-starter-toolkit
configureコマンドで、デプロイの設定を進めていきます。エージェント名は適当にsample_zip_starter_agentとします。
agentcore configure -e main.py -n sample_zip_starter_agent
対話が進みます。今回はZipで直接デプロイするので1. Direct Code Deploy (recommended)を選択します。
直接デプロイを推奨しているんですね。
S3のバケットやIAM Roleなどは既存のリソースを指定しなければ自動で作成される形になります。
自動で作成されるのは良きです。
基本的にデフォルトの設定で進めていきます。
agentcore configure -e main.py -n sample_zip_starter_agent
Configuring Bedrock AgentCore...
✓ Using file: main.py
🔍 Detected dependency file: pyproject.toml
Press Enter to use this file, or type a different path (use Tab for autocomplete):
Path or Press Enter to use detected dependency file: pyproject.toml
✓ Using requirements file: pyproject.toml
🚀 Deployment Configuration
Select deployment type:
1. Direct Code Deploy (recommended) - Python only, no Docker required
2. Container - For custom runtimes or complex dependencies
Choice [1]: 1
Select Python runtime version:
1. PYTHON_3_10
2. PYTHON_3_11
3. PYTHON_3_12
4. PYTHON_3_13
Choice [4]: 4
✓ Deployment type: Direct Code Deploy (python.3.13)
🔐 Execution Role
Press Enter to auto-create execution role, or provide execution role ARN/name to use existing
Execution role ARN/name (or press Enter to auto-create):
✓ Will auto-create execution role
🏗️ S3 Bucket
Press Enter to auto-create S3 bucket, or provide S3 URI/path to use existing
S3 URI/path (or press Enter to auto-create):
✓ Will auto-create S3 bucket
🔐 Authorization Configuration
By default, Bedrock AgentCore uses IAM authorization.
Configure OAuth authorizer instead? (yes/no) [no]:
✓ Using default IAM authorization
🔒 Request Header Allowlist
Configure which request headers are allowed to pass through to your agent.
Common headers: Authorization, X-Amzn-Bedrock-AgentCore-Runtime-Custom-*
Configure request header allowlist? (yes/no) [no]:
✓ Using default request header configuration
Configuring BedrockAgentCore agent: sample_zip_starter_agent
Memory Configuration
Tip: Use --disable-memory flag to skip memory entirely
No region configured yet
Options:
• Press Enter to create new memory
• Type 's' to skip memory setup
Your choice: s
✓ Skipping memory configuration
Memory disabled by user choice
Network mode: PUBLIC
Setting 'sample_zip_starter_agent' as default agent
╭─────────────────────────────────────────── Configuration Success ────────────────────────────────────────────╮
│ Agent Details │
│ Agent Name: sample_zip_starter_agent │
│ Deployment: direct_code_deploy │
│ Region: us-west-2 │
│ Account: xxx │
│ Runtime: python3.13 │
│ │
│ Configuration │
│ Execution Role: Auto-create │
│ ECR Repository: N/A │
│ Network Mode: Public │
│ S3 Bucket: Auto-create │
│ Authorization: IAM (default) │
│ │
│ │
│ Memory: Disabled │
│ │
│ │
│ 📄 Config saved to: /Users/xxx/agentcore-zip/.bedrock_agentcore.yaml │
│ │
│ Next Steps: │
│ agentcore launch │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
今までのStarter toolkitと同じく完了すると、.bedrock_agentcore.yamlが作成されるのでlaunchを実行して、デプロイします。
agentcore launch
デプロイが完了したら早速、agentcore invokeコマンドを実行してみます。
agentcore invoke '{"prompt": "Hello"}'
{"init_event_loop": true}
{"start": true}
{"start_event_loop": true}
{"event": {"messageStart": {"role": "assistant"}}}
{"event": {"contentBlockDelta": {"delta": {"text": "こんにちは"}, "contentBlockIndex": 0}}}
{'data': 'こんにちは', 'delta': {'text': 'こんにちは'}, 'agent': <strands.agent.agent.Agent object at
0xffffa2c3b4d0>, 'event_loop_cycle_id': UUID('1a1b3ba0-9292-45b3-b039-22fccbdc25d3'), 'request_state': {},
'event_loop_cycle_trace': <strands.telemetry.metrics.Trace object at 0xffffa1e83770>, 'event_loop_cycle_span':
NonRecordingSpan(SpanContext(trace_id=0x00000000000000000000000000000000, span_id=0x0000000000000000,
trace_flags=0x00, trace_state=[], is_remote=False))}{"event": {"contentBlockDelta": {"delta": {"text": "!お元気ですか?"}, "contentBlockIndex": 0}}}
{'data': '!お元気ですか?', 'delta': {'text': '!お元気ですか?'}, 'agent': <strands.agent.agent.Agent object
at 0xffffa2c3b4d0>, 'event_loop_cycle_id': UUID('1a1b3ba0-9292-45b3-b039-22fccbdc25d3'), 'request_state': {},
'event_loop_cycle_trace': <strands.telemetry.metrics.Trace object at 0xffffa1e83770>, 'event_loop_cycle_span':
NonRecordingSpan(SpanContext(trace_id=0x00000000000000000000000000000000, span_id=0x0000000000000000,
trace_flags=0x00, trace_state=[], is_remote=False))}{"event": {"contentBlockDelta": {"delta": {"text": "何かお手伝い"}, "contentBlockIndex": 0}}}
{'data': '何かお手伝い', 'delta': {'text': '何かお手伝い'}, 'agent': <strands.agent.agent.Agent object at
0xffffa2c3b4d0>, 'event_loop_cycle_id': UUID('1a1b3ba0-9292-45b3-b039-22fccbdc25d3'), 'request_state': {},
'event_loop_cycle_trace': <strands.telemetry.metrics.Trace object at 0xffffa1e83770>, 'event_loop_cycle_span':
NonRecordingSpan(SpanContext(trace_id=0x00000000000000000000000000000000, span_id=0x0000000000000000,
trace_flags=0x00, trace_state=[], is_remote=False))}{"event": {"contentBlockDelta": {"delta": {"text": "できることがあれば、お"}, "contentBlockIndex": 0}}}
{'data': 'できることがあれば、お', 'delta': {'text': 'できることがあれば、お'}, 'agent':
<strands.agent.agent.Agent object at 0xffffa2c3b4d0>, 'event_loop_cycle_id':
UUID('1a1b3ba0-9292-45b3-b039-22fccbdc25d3'), 'request_state': {}, 'event_loop_cycle_trace':
<strands.telemetry.metrics.Trace object at 0xffffa1e83770>, 'event_loop_cycle_span':
NonRecordingSpan(SpanContext(trace_id=0x00000000000000000000000000000000, span_id=0x0000000000000000,
trace_flags=0x00, trace_state=[], is_remote=False))}{"event": {"contentBlockDelta": {"delta": {"text": "気軽にお聞か"}, "contentBlockIndex": 0}}}
{'data': '気軽にお聞か', 'delta': {'text': '気軽にお聞か'}, 'agent': <strands.agent.agent.Agent object at
0xffffa2c3b4d0>, 'event_loop_cycle_id': UUID('1a1b3ba0-9292-45b3-b039-22fccbdc25d3'), 'request_state': {},
'event_loop_cycle_trace': <strands.telemetry.metrics.Trace object at 0xffffa1e83770>, 'event_loop_cycle_span':
NonRecordingSpan(SpanContext(trace_id=0x00000000000000000000000000000000, span_id=0x0000000000000000,
trace_flags=0x00, trace_state=[], is_remote=False))}{"event": {"contentBlockDelta": {"delta": {"text": "せください。どのような質問や"}, "contentBlockIndex": 0}}}
{'data': 'せください。どのような質問や', 'delta': {'text': 'せください。どのような質問や'}, 'agent':
<strands.agent.agent.Agent object at 0xffffa2c3b4d0>, 'event_loop_cycle_id':
UUID('1a1b3ba0-9292-45b3-b039-22fccbdc25d3'), 'request_state': {}, 'event_loop_cycle_trace':
<strands.telemetry.metrics.Trace object at 0xffffa1e83770>, 'event_loop_cycle_span':
NonRecordingSpan(SpanContext(trace_id=0x00000000000000000000000000000000, span_id=0x0000000000000000,
trace_flags=0x00, trace_state=[], is_remote=False))}{"event": {"contentBlockDelta": {"delta": {"text": "お話をされたいですか?"}, "contentBlockIndex": 0}}}
{'data': 'お話をされたいですか?', 'delta': {'text': 'お話をされたいですか?'}, 'agent':
<strands.agent.agent.Agent object at 0xffffa2c3b4d0>, 'event_loop_cycle_id':
UUID('1a1b3ba0-9292-45b3-b039-22fccbdc25d3'), 'request_state': {}, 'event_loop_cycle_trace':
<strands.telemetry.metrics.Trace object at 0xffffa1e83770>, 'event_loop_cycle_span':
NonRecordingSpan(SpanContext(trace_id=0x00000000000000000000000000000000, span_id=0x0000000000000000,
trace_flags=0x00, trace_state=[], is_remote=False))}{"event": {"contentBlockStop": {"contentBlockIndex": 0}}}
{"event": {"messageStop": {"stopReason": "end_turn"}}}
{"event": {"metadata": {"usage": {"inputTokens": 47, "outputTokens": 57, "totalTokens": 104}, "metrics":
{"latencyMs": 5478}}}}
{"message": {"role": "assistant", "content": [{"text":
"こんにちは!お元気ですか?何かお手伝いできることがあれば、お気軽にお聞かせください。どのような質問やお話をされ
たいですか?"}]}}
{'result': AgentResult(stop_reason='end_turn', message={'role': 'assistant', 'content': [{'text':
'こんにちは!お元気ですか?何かお手伝いできることがあれば、お気軽にお聞かせください。どのような質問やお話をされ
たいですか?'}]}, metrics=EventLoopMetrics(cycle_count=1, tool_metrics={}, cycle_durations=[5.5013792514801025],
traces=[<strands.telemetry.metrics.Trace object at 0xffffa1e83770>], accumulated_usage={'inputTokens': 47,
'outputTokens': 57, 'totalTokens': 104}, a
レスポンスが問題なく返ってきました!!自分でzip化するのは若干手間に感じたので、Starter Toolkit経由では依存関係を読み取って自動でzipアップロードしてくれて、お手軽でしたね。コンソール上よりも簡単に感じました。
おわりに
今回はzipファイルアップロードによるデプロイを試してみました!
テンプレートから作成はサクッと作って、コードを一部直したい時だけとか便利そうですね。
zipアップロードも便利だなと思ったのですが、コンソール上からアップロードする際はARM64のパッケージを使用する必要があるとかは注意点かと思います。依存関係を自動でパッケージングしてくれるStarter Toolkitの方がお手軽に感じますね。
本記事が少しでも参考になりましたら幸いです!最後までご覧いただきありがとうございましたー!!
補足
途中でも紹介しましたが、下記公式ブログが参考になる箇所が多いなと思ったので再度共有です。
具体的にはDirect code deployment conceptsと書いてある部分ですね。
- AgentCoreの責任共有モデルの考え方
- コンテナとZipデプロイの比較選択
- サポートされる言語・OSアーキテクチャ
- etc・・・
特にZipアップロードかコンテナ化の選択のガイドラインは参考になると思ったので、ぜひご活用いただければと思います。
Container vs direct code deployment comparisonより引用
Our general guidance is
If the size of the deployment package exceeds 250MB, and you have existing container CI/CD pipelines, and you need highly specialized dependencies and packaging, then container based deployments is a good option to choose.
If the size of the deployment package is small, the code and package is not complex to build and uses common frameworks and languages, and you need rapid prototyping and iteration, then direct code deployment would be the option.
There can also be a hybrid option where developers use the direct code deployment to quickly experiment and prototype agents and then switch to container based deployments (for the above reasons) to develop, test and deploy to production.








