![[アップデート] Amazon Bedrock AgentCore Runtime に Session Storage が追加されました](https://images.ctfassets.net/ct0aopd36mqt/7M0d5bjsd0K4Et30cVFvB6/5b2095750cc8bf73f04f63ed0d4b3546/AgentCore2.png?w=3840&fm=webp)
[アップデート] Amazon Bedrock AgentCore Runtime に Session Storage が追加されました
はじめに
こんにちは、スーパーマーケットのライフが好きなコンサル部の神野です。
2026年3月24日に Amazon Bedrock AgentCore Control Plane の API が更新され、AgentCore Runtime に Session Storageを構成する filesystemConfigurations パラメータが追加されました。
今までの AgentCore Runtime ではセッションを停止するとファイルシステムの状態がすべて消えていましたが、この機能によりセッションの Stop/Resume をまたいでファイルを保持できるようになっています。
今回は実際にセッションを止めて再開しても本当にファイルが残っているのかを試してみます!
今回の API 変更の概要
今回の変更点のうち、この記事では次の 3 つの API を見ていきます。
| API | 変更内容 |
|---|---|
| CreateAgentRuntime | filesystemConfigurations パラメータが追加 |
| UpdateAgentRuntime | filesystemConfigurations パラメータが追加 |
| GetAgentRuntime | レスポンスに filesystemConfigurations が追加 |
メインは filesystemConfigurations です。この記事ではこちらを中心に試していきます。
今までの仕様
まず変更前の挙動を整理します。
AgentCore Runtime では、各セッションが専用の microVM 上で動作します。CPU、メモリ、ファイルシステムがセッションごとに分離される VM レベルの隔離環境です。
ただし、この環境は一時的で、最大 8 時間で破棄されていました。
- セッション中にファイルシステムへ書き込んだデータ(ソースコード、依存パッケージ、ビルド成果物など)は、セッション終了とともに消える
- セッションを停止(Stop)して再開(Resume)すると、新しい microVM が立ち上がりクリーンなファイルシステムが割り当てられる
- セッション間で状態を引き継ぐには、AgentCore Memory や S3、DynamoDB など外部ストレージに明示的に保存する必要があった
これを解消するアップデートがSession Storage機能になります。
Session Storage の仕組み
今回の filesystemConfigurations によるセッションストレージは以下のように動作します。
- AgentCore Runtime 作成時に
filesystemConfigurationsでマウントパスを指定 - セッション起動時にそのパスに永続ディレクトリがマウントされる(初回は空)
- エージェントがファイルを書き込むと、非同期でサービス側のストレージに複製される
- セッション停止時に未永続化データがフラッシュされ、次回の Resume 時に同じ状態が復元される
エージェント側は /mnt/workspace のような普通のディレクトリとして読み書きするだけで、永続化の仕組みは AgentCore Runtime がすべて管理してくれます。シンプルで良きですね。
公式ドキュメントに詳細な仕様が記載されています。いつの間に追加されたんだ・・・
前提
使用環境
- リージョン: us-east-1
- Python: 3.12
- uv(パッケージ管理)
- bedrock-agentcore 1.4.7
- bedrock-agentcore-starter-toolkit 0.3.3
- strands-agents 1.33.0 / strands-agents-tools 0.2.23
- boto3 1.42.75
Session Storage は東京リージョン(ap-northeast-1)でも利用可能です。
事前準備
今回は Starter Toolkit CLI(bedrock-agentcore-starter-toolkit)を使ってデプロイします。
デプロイするだけならこちらのほうがシンプルなので使用します。
uv init coding-agent
uv add bedrock-agentcore-starter-toolkit strands-agents strands-agents-tools bedrock-agentcore
実装
AWS公式ドキュメントの使い方を参考にStrands Agentsで実装してみました。
エージェントの作成
Session Storage を活用したエージェントを作成していきます。
import os
os.environ["BYPASS_TOOL_CONSENT"] = "true"
from strands import Agent
from strands.session import FileSessionManager
from strands.models import BedrockModel
from strands_tools import file_read, file_write, shell
from bedrock_agentcore.runtime import BedrockAgentCoreApp
app = BedrockAgentCoreApp()
WORKSPACE = "/mnt/workspace"
model = BedrockModel(model_id="us.anthropic.claude-sonnet-4-20250514-v1:0")
tools = [file_read, file_write, shell]
@app.entrypoint
def handle_request(payload):
session_id = payload.get("session_id", "default")
session_manager = FileSessionManager(
session_id=session_id,
storage_dir=f"{WORKSPACE}/.sessions"
)
agent = Agent(
model=model,
tools=tools,
session_manager=session_manager,
system_prompt="あなたはコーディングアシスタントです。プロジェクトファイルは /mnt/workspace にあります。日本語で応答してください。"
)
response = agent(payload.get("prompt"))
return {"response": response.message["content"][0]["text"]}
if __name__ == "__main__":
app.run()
FileSessionManager で会話履歴を /mnt/workspace/.sessions/ に保存するようにしています。Session Storage によりこのディレクトリも永続化されるため、セッションを再開した際にエージェントが前回の会話内容を覚えている状態を作れます。
/mnt/workspace は後ほど filesystemConfigurations で指定するマウントパスと一致させています。エージェントがこのディレクトリ配下に書き込んだファイルがすべて永続化の対象になります。
エージェント自体の処理はシンプルで、マウントしたパスにファイルを書き込むコーディングアシスタントのイメージです。
デプロイ
Starter Toolkit CLI で configure → deploy するだけです。
設定も基本変更せず、そのまま進めていきます。
agentcore configure
# 基本デフォルトの設定で対話形式で進めていく
agentcore deploy
deployが成功したら、ARNを控えておきます。
✓ Agent 'coding-agent' deployed successfully
Runtime ARN: arn:aws:bedrock-agentcore:us-east-1:123456789012:agent-runtime/abc123def
Endpoint ARN: arn:aws:bedrock-agentcore:us-east-1:123456789012:agent-runtime-endpoint/xyz789
Session Storage の有効化
デプロイした Runtime に対して filesystemConfigurations を追加します。
現時点では Starter Toolkit からの直接指定に対応していなさそうなので、boto3 で設定します。
agentcore deploy の出力に表示された Runtime ARN から Runtime ID(abc123def の部分)を指定してください。
import boto3
RUNTIME_ID = "abc123def" # agentcore deploy で取得した Runtime ID に置き換えてください
client = boto3.client("bedrock-agentcore-control", region_name="us-east-1")
# 既存の設定を取得(UpdateAgentRuntime は artifact / roleArn / networkConfiguration が必須)
current = client.get_agent_runtime(agentRuntimeId=RUNTIME_ID)
response = client.update_agent_runtime(
agentRuntimeId=RUNTIME_ID,
agentRuntimeArtifact=current["agentRuntimeArtifact"],
roleArn=current["roleArn"],
networkConfiguration=current["networkConfiguration"],
filesystemConfigurations=[
{
"sessionStorage": {
"mountPath": "/mnt/workspace"
}
}
]
)
print(f"Status: {response['status']}")
Status: UPDATING
mountPath は /mnt 配下に 1 階層のサブディレクトリを指定します(例: /mnt/workspace、/mnt/data)。
GetAgentRuntime で確認してみます。
import boto3, json
RUNTIME_ID = "abc123def" # 同じ Runtime ID
client = boto3.client("bedrock-agentcore-control", region_name="us-east-1")
response = client.get_agent_runtime(agentRuntimeId=RUNTIME_ID)
print(json.dumps(response["filesystemConfigurations"], indent=2))
[
{
"sessionStorage": {
"mountPath": "/mnt/workspace"
}
}
]
filesystemConfigurations が返ってきていますね! Session Storage が有効化されました。
動作確認
ここからが本題です。
セッションを起動してファイルを作成し、セッションを停止して再開した後にファイルが残っているかを確認します。
最初の呼び出し — ファイルを作成
import boto3
import json
client = boto3.client("bedrock-agentcore", region_name="us-east-1")
# agentcore deploy の出力に表示された Runtime ARN に置き換えてください
agent_arn = "arn:aws:bedrock-agentcore:us-east-1:123456789012:agent-runtime/abc123def"
session_id = "session-storage-test-001-jinno-yudai" # 33文字以上が必要
def invoke(prompt):
resp = client.invoke_agent_runtime(
agentRuntimeArn=agent_arn,
runtimeSessionId=session_id,
payload=json.dumps({
"prompt": prompt,
"session_id": "conv-001"
}).encode()
)
return json.loads(b"".join(resp["response"]))["response"]
result = invoke(
"/mnt/workspace に calculator.py を作成してください。"
"add, subtract, multiply の3つの関数を実装してください。"
"作成後、/mnt/workspace のファイル一覧を表示してください。"
)
print(result)
calculator.pyファイルを正常に作成しました!
作成したファイルの詳細:
- ファイル名: calculator.py
- 場所: /mnt/workspace/calculator.py
- 実装した関数:
1. add(a, b) - 2つの数値の足し算
2. subtract(a, b) - 2つの数値の引き算
3. multiply(a, b) - 2つの数値の掛け算
現在の/mnt/workspaceディレクトリの内容:
- calculator.py (892バイト)
- .sessions/ ディレクトリ
/mnt/workspace/calculator.py が作成されましたね!
実際に作られたかどうかを確認したいですよね。
エージェントが作ったファイルを直接確認する
エージェントがファイルを作りましたと応答していますが、直接ファイルシステムを見て確認してみます。直近追加された InvokeAgentRuntimeCommand API を使うと、LLM を介さずにセッション内でシェルコマンドを直接実行できます。
同じセッションのコンテナ上で動作するため、Session Storage のマウント先にもアクセスできます。
import boto3
import sys
client = boto3.client("bedrock-agentcore", region_name="us-east-1")
agent_arn = "arn:aws:bedrock-agentcore:us-east-1:123456789012:agent-runtime/abc123def"
session_id = "session-storage-test-001-jinno-yudai"
def run_command(command):
response = client.invoke_agent_runtime_command(
agentRuntimeArn=agent_arn,
runtimeSessionId=session_id,
contentType="application/json",
accept="application/vnd.amazon.eventstream",
body={
"command": f'/bin/bash -c "{command}"',
"timeout": 60
}
)
for event in response.get("stream", []):
if "chunk" in event:
chunk = event["chunk"]
if "contentDelta" in chunk:
delta = chunk["contentDelta"]
if delta.get("stdout"):
print(delta["stdout"], end="")
if "contentStop" in chunk:
print(f"--- exit code: {chunk['contentStop'].get('exitCode')} ---")
run_command("ls -la /mnt/workspace")
run_command("cat /mnt/workspace/calculator.py")
コマンドを実行して結果を確認してみます。
=== ls -la /mnt/workspace ===
total 5
drwxr-xr-x 3 root root 0 Mar 25 06:04 .
drwxr-xr-x 1 root root 4096 Mar 25 06:04 ..
drwxr-xr-x 3 root root 0 Mar 25 06:04 .sessions
-rw-r--r-- 1 root root 892 Mar 25 06:04 calculator.py
--- exit code: 0 ---
=== cat /mnt/workspace/calculator.py ===
def add(a, b):
"""
2つの数値を足し算します
Args:
a (float): 第一の数値
b (float): 第二の数値
Returns:
float: a + b の結果
"""
return a + b
def subtract(a, b):
"""
2つの数値を引き算します
Args:
a (float): 第一の数値
b (float): 第二の数値
Returns:
float: a - b の結果
"""
return a - b
def multiply(a, b):
"""
2つの数値を掛け算します
Args:
a (float): 第一の数値
b (float): 第二の数値
Returns:
float: a * b の結果
"""
return a * b
if __name__ == "__main__":
# テスト用のサンプルコード
print("Calculator Test:")
print(f"5 + 3 = {add(5, 3)}")
print(f"10 - 4 = {subtract(10, 4)}")
print(f"6 * 7 = {multiply(6, 7)}")
--- exit code: 0 ---
LLM の応答ではなく、実際に Python ファイルが /mnt/workspace に書き込まれていることがわかりました!
こういった時に直近のコマンド実行のアップデートが役立ってびっくりです。
セッションの停止
ここでセッションを停止します。従来であれば、この時点でファイルシステムの中身は消えてしまうところです。
client.stop_runtime_session(
agentRuntimeArn=agent_arn,
runtimeSessionId=session_id
)
print("Session stopped.")
Session stopped.
セッション再開後にファイルが残っているか直接確認する
しばらく時間を置いてから、同じ session_id で再度 InvokeAgentRuntimeCommand を実行します。新しい microVM が立ち上がりますが、Session Storage によりファイルシステムの状態が復元されるはずです。先ほどの verify_with_command.py をそのまま使います。
=== ls -la /mnt/workspace ===
total 5
drwxr-xr-x 3 root root 0 Mar 25 06:04 .
drwxr-xr-x 1 root root 4096 Mar 25 06:05 ..
drwxr-xr-x 3 root root 0 Mar 25 06:04 .sessions
-rw-r--r-- 1 root root 892 Mar 25 06:04 calculator.py
--- exit code: 0 ---
=== cat /mnt/workspace/calculator.py ===
def add(a, b):
"""
2つの数値を足し算します
Args:
a (float): 第一の数値
b (float): 第二の数値
Returns:
float: a + b の結果
"""
return a + b
def subtract(a, b):
"""
2つの数値を引き算します
...(省略)
"""
return a - b
def multiply(a, b):
"""
2つの数値を掛け算します
...(省略)
"""
return a * b
if __name__ == "__main__":
# テスト用のサンプルコード
print("Calculator Test:")
print(f"5 + 3 = {add(5, 3)}")
print(f"10 - 4 = {subtract(10, 4)}")
print(f"6 * 7 = {multiply(6, 7)}")
--- exit code: 0 ---
おおお、ちゃんとファイルが残っていますね!!
前回の続きから作業を再開
会話履歴も FileSessionManager 経由で /mnt/workspace/.sessions/ に保存されているので、エージェントは前回の文脈を覚えています。そのまま続きの作業を依頼してみます。
result = invoke(
"先ほど作成した calculator に divide 関数を追加してください。"
"また、test_calculator.py というテストスクリプトも作成してください。"
)
print(result)
完了しました!以下の作業を行いました:
1. calculator.py の更新
- divide関数を追加: 除算機能を実装
- ゼロ除算エラー処理: 適切なエラーハンドリングを追加
2. test_calculator.py の作成
- 包括的なテストスイート: unittestフレームワークを使用
- テストケース:
- 基本的な四則演算(add, subtract, multiply, divide)
- ゼロ除算のエラーハンドリング
- 負の数の計算
- 小数点の計算
- 大きな数値の計算
テスト結果: すべてのテストが成功 - 7つのテストケースすべてが通過
現在のファイル構成:
/mnt/workspace/
├── calculator.py (1,489 bytes) - 四則演算関数
└── test_calculator.py (3,758 bytes) - テストスイート
パッケージの再インストールもファイルの再生成も不要で、エージェントが中断したところからすぐに作業を継続できています。先ほど作成した calculatorという指示にもちゃんと応えてくれているので、FileSessionManager による会話履歴の引き継ぎも効いていますね。
おまけ:Session Storage を無効化するとどうなるか
逆に Session Storage を外したらどうなるのかも試してみました。UpdateAgentRuntime で filesystemConfigurations を空配列にします。
response = client.update_agent_runtime(
agentRuntimeId=RUNTIME_ID,
agentRuntimeArtifact=current["agentRuntimeArtifact"],
roleArn=current["roleArn"],
networkConfiguration=current["networkConfiguration"],
filesystemConfigurations=[]
)
更新後に GetAgentRuntime を確認すると、filesystemConfigurations キー自体がレスポンスから消えました。空配列で更新すれば無効化できるようです。
この状態で新しいセッションを起動してファイルを作成し、Stop → Resume してみます。
botocore.errorfactory.RuntimeClientError: An error occurred (RuntimeClientError)
when calling the InvokeAgentRuntime operation:
"errorType": "PermissionError",
"errorMessage": "[Errno 13] Permission denied: '/mnt/workspace'"
今回のエージェントは /mnt/workspace を前提に実装しているため、Session Storage を無効化した状態では書き込みに失敗しました。当たり前ですが予想通りの結果ですね。
色々と動作確認できたところで改めて仕様を確認してみます。
ファイルシステムの仕様
Session Storage で提供されるファイルシステムの仕様も整理しておきます。
標準的な Linux ファイルシステムとして動作し、ls、cat、mkdir、git、npm、pip、cargo などのツールがそのまま使えます。
| 区分 | 内容 |
|---|---|
| サポート | 通常ファイル、ディレクトリ、シンボリックリンク、read/write/rename/delete/chmod/chown/stat/readdir |
| 非サポート | ハードリンク、デバイスファイル/FIFO/UNIX ソケット、拡張属性(xattr)、fallocate、セッション間のファイルロック |
git や npm といった一般的な開発ツールは問題なく動作します。
ストレージの上限
セッションあたりの上限は以下のとおりです。すべて調整不可となっています。
| 制限項目 | 値 | 説明 |
|---|---|---|
| 最大ストレージサイズ | 1 GB | セッションあたりの合計ストレージサイズ |
| 最大ファイルシステムメタデータ | 約 50 MB | 約 100,000〜200,000 ファイルに相当 |
| 最大ディレクトリ階層 | 200 階層 | ネストできるディレクトリの深さ |
| 最大ファイル名長 | 255 バイト | 単一ファイル名の最大長 |
| 最大シンボリックリンクターゲット長 | 4,095 バイト | シンボリックリンク先パスの最大長 |
大きなリポジトリを丸ごとクローンもしくは大きいデータを扱う使い方だと1GBの上限に注意が必要ですね。
ストレージのライフサイクル
セッションデータがクリアされる条件は以下の 2 つです。
- セッションが 14 日間呼び出されなかった場合
- Agent Runtime のバージョンが更新された場合(更新後の起動ではクリーンなファイルシステムが割り当てられる)
無限に保持されるわけではないんですね。また、Runtime のバージョン更新でリセットされる点は要注意です。エージェントのコードを更新してデプロイし直すと、既存セッションのストレージもクリアされます。
おわりに
これまでセッション停止のたびにファイルシステムがクリアされていたのが、filesystemConfigurations パラメータでセッションをまたいだファイルの永続化ができるようになりました。
チェックポイントとしてのファイル利用や、中間生成物をファイルに出力するなど色々と活用シーンがありそうで嬉しいアップデートですね。現時点ではプレビュー機能なので、一般提供されて欲しいなと思っています!
料金体系は Preview のため未公開のようです。今後どのような課金モデルになるか気になるところですね。(探したのですが見つかりませんでした)
本記事が少しでも参考になりましたら幸いです。最後までご覧いただきありがとうございました!










