AIエージェントが開発中のWebアプリをリアルタイムプレビューできるBedrock AgentCore Session endpointsを試してみた
:::note warn
この記事はAI(Codex)と一緒に作成しました。
内容は2026年11月時点の検証結果です。
:::
はじめに
2026年10月30日、AWSから以下の記事が公開されました。
> Preview web apps live as your coding agent builds them with Amazon Bedrock AgentCore runtime
AIエージェントがWebアプリを開発している最中に、
そのWebアプリをブラウザからリアルタイムにプレビューできるという内容です。
コーディングエージェントを使えば簡単にWebアプリを作れる時代になりましたが、
クラウド上で動くAIエージェントが作ったものを確認するには、
コードを取得してローカルで起動したりする手間がかかることもあります。
そこでAmazon Bedrock AgentCore RuntimeのSession endpointsという機能を使うと、
AIエージェントが動いている実行環境内のWebサーバーに、認証付きでアクセスできます。
つまり、AIエージェントがコードを編集した瞬間、その変更をブラウザで確認できるわけです。面白そうなので触ってみました。
!{348A9BEA-EF0D-4DCD-B86C-DBEFAC81422B}.png
> 赤枠がエージェントとのチャット画面、青枠がWebアプリのプレビュー画面です。
> 赤枠で相談した内容が青枠に即時反映されます。
今回はAWS公式サンプルを使って、日本向けの推論プロファイルで実際に動作を検証してみました。
実際に動かしてみた
今回やってみたことは、次の3つです。
1. AgentCore Runtime上でコーディングエージェントを動かす
2. エージェントが編集しているWebサイトをブラウザから表示する
3. 日本語で変更を指示し、Webサイトがリアルタイムに更新されることを確認する
実際には、コーヒーショップのサンプルWebサイトに対して、次の指示を送りました。
> Webサイト全体を日本語に翻訳してください。
> デザインやレイアウトは変更しないでください。
結果として、AIエージェントがindex.htmlとsrc/main.jsを編集し、
変更後のWebサイトをブラウザから確認できました。(翻訳は微妙だけど)
■変更前(英文)
!image.png
■変更後(日本語訳)
!image.png
セッション分離や認証なしアクセス、WebSocketの更新通知も気になったので、追加で検証してみました。モデルIDやRuntime更新で地味にハマったので、その対処もついでに紹介します。
Session endpointsとは?
Session endpointsは、AgentCore Runtime内で動いている
HTTPサーバーなどにアクセスできる仕組みです。
例えば、AIエージェントが同じ実行環境内でWebアプリの開発サーバーを起動していれば、
そのWebアプリを外部からプレビューできます。
通常のRuntime呼び出しとの違い
AgentCore Runtimeには、AIエージェントを呼び出すための仕組みがもともとあります。
一方、Session endpointsは、AIエージェント自身ではなく、エージェントと同じセッション内で動いている別のアプリケーションにアクセスするための機能です。
| 項目 | Runtimeの通常呼び出し | Session endpoints |
|---|---|---|
| 主な用途 | AIエージェントの実行 | セッション内のアプリへのアクセス |
| アクセス対象 | エージェントのAPI | 許可したポートのWebサーバーなど |
| 今回の用途 | Webサイトの編集を指示 | 編集中のWebサイトを表示 |
| 通信 | Runtime API | HTTP、WebSocketなど |
Session endpointsでは、あらかじめ許可したポートだけにアクセスできます。
また、URLを知っているだけで誰でもアクセスできるわけではなく、IAMなどによる認証が必要です。
今回の構成
flowchart TD
A["ローカルPCのブラウザ"] --> B["PreviewApp"]
B -->|"編集指示"| C["AgentCore Runtime API"]
C --> D["AIエージェント"]
D --> E["Amazon Bedrock<br/>Claude Haiku 5.5"]
D --> F["Webサイトのファイルを編集"]
F --> G["Vite開発サーバー<br/>Port 8090"]
G -->|"Session endpoints<br/>HTTP / WebSocket"| B
B -->|"プレビューを表示"| A
今回のサンプルでは、主に3つのポートを使用します。
| ポート | 用途 |
|---|---|
| 8080 | AIエージェントの呼び出し |
| 8090 | ViteによるWebサイトのプレビュー |
| 8081 | ステータス確認用API |
Viteはファイルの変更を検知してブラウザの表示を更新してくれるツールです。
今回の構成では、ViteのWebSocket通信もSession endpoints経由で転送されるので、
ブラウザを手動更新せずに変更内容を確認できます。
検証方法
AWS CLIの認証設定が完了していることを前提とします。
また、RuntimeやIAMロール、S3リソースを作成する権限に加え、
Runtimeの呼び出しとSession endpointsへのアクセス権限が必要です。
公式サンプルのPython依存関係は、bedrock-agentcore>=1.25.2、boto3>=1.43.122でした。
手順① 公式サンプルを取得する
まず、AWS公式のGitHubリポジトリを取得します。
(WSLのターミナルから実行しました。)
git clone https://github.com/awslabs/agentcore-samples.git
今回使用するディレクトリに移動します。
cd agentcore-samples/01-features/02-host-your-agent/01-runtime/03-advanced/16-session-endpoints
このディレクトリには、以下のようなファイルがあります。
| ファイル | 役割 |
|---|---|
| deploy.py | AgentCore Runtimeのデプロイ |
| cleanup.py | 作成したAWSリソースの削除 |
| preview_app.py | ローカルのプレビュー画面の起動 |
| session_endpoints_preview.ipynb | 公式の検証用Notebook |
| agent/app.ts | AIエージェントの実装 |
| site/ | サンプルWebサイト |
手順② Python環境を準備する
Pythonの仮想環境を作成します。
uv venv
仮想環境を有効化します。
source .venv/bin/activate
依存パッケージをインストールします。
uv pip install -r requirements.txt
これでPython側の準備は完了です。
手順③ 利用するモデルIDを確認する
公式サンプルでは、モデルIDのデフォルト値として
us.anthropic.claude-haiku-5-5が指定されています。
私は日本向け推論プロファイルを利用したかったので以下のモデルIDを使いました。
jp.anthropic.claude-haiku-5-5
なお、モデルIDと推論プロファイルのIDは別物で、一覧に表示されるモデルでも直接指定して呼べるとは限りません。利用できるモデルや推論プロファイルはリージョンやアカウントの権限によって変わるので、上記のIDがどの環境でもそのまま使えるとは限らない点だけ補足しておきます。
手順④ AgentCore Runtimeをデプロイする
公式サンプルのdeploy.pyを実行します。
日本向け推論プロファイル利用時はモデルIDを明示的に指定しましょう。
python deploy.py \
--model jp.anthropic.claude-haiku-5-5
デプロイが完了すると、RuntimeのステータスがREADYになります。
今回のサンプルは、Node.jsのアプリケーションをZIP形式でS3にアップロードし、
AgentCore Runtimeで実行する構成です。
(つまりDockerイメージやECRリポジトリを自分で準備する必要がないわけですね!)
Session endpoints用のポート設定
deploy.pyでは、次のような設定が使われています。
protocolConfiguration={
"serverProtocol": "HTTP",
"port": 8080,
"path": "/invocations"
},
allowedPorts=[
{"port": 8090},
{"port": 8081}
]
- protocolConfigurationは、AIエージェント本体の呼び出し先を設定しています。
- allowedPortsは、Session endpoints経由でアクセスを許可するポートです。
今回はWebサイトのプレビュー用に8090、ステータス確認用に8081を指定しています。
(allowedPortsを設定するだけでWebサーバーが起動するわけではありません)
手順⑤ プレビュー画面を起動する
Runtimeのデプロイが完了したら、プレビュー画面を起動します。
今回は次のPythonコードを実行しました。
python - <<'PY'
import time
from preview_app import PreviewApp
app = PreviewApp().start()
print(f"プレビューURL: {app.url}", flush=True)
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
finally:
app.stop()
print("セッションを終了しました")
PY
成功すると、プレビューURLが表示されます。
プレビューURL: http://localhost:8087
ブラウザからこのURLを開きます。
すると最初にお見せした、
左側にAIエージェントとのチャット画面、右側にコーヒーショップのサンプルWebサイト
が表示されます。
!image.png
右側のWebサイトはローカルPC上で動いているわけではなく、
AgentCore Runtimeのセッション内で動いていて、Session endpointsを通じて
ローカルブラウザに表示されています。
内部では何が起きているのか?
PreviewAppの起動処理を見てみると、こうなっています。
answer = self.invoke({"prompt": ""})
started = json.loads(answer["response"].read())
self.endpoint = self.client.session_endpoint_client(
session_endpoint_url(answer)
)
self.local = self.endpoint.open_local_endpoint(
port=self.config["preview_port"],
local_port=self.proxy_port
).start()
まずInvokeAgentRuntimeでセッションを起動し、
レスポンスからSession endpointのURLを取得して、ローカル側に接続口を作っています。
このローカル側の接続口がAWS認証情報を付けてリクエストを転送してくれるので、
ブラウザ自身がAWSのSigV4署名を実装する必要はありません。地味に便利な仕組みです。
手順⑥ AIエージェントに日本語で変更を指示する
いよいよWebサイトを変更してみます。
左側のチャット欄に、以下の指示を入力しました。
!{E42D5922-5C0B-4331-B6B9-9410A8750ACA}.png
するとコードを触っているログが表示され、
最終的には、変更が完了したことを示すメッセージが表示されました。
実際に、Webサイト内の英語が日本語に変更され、ブラウザ側にも反映されました。
!{CEE37FE4-6060-4EFC-9117-6FF7F0CD7AC5}.png
AIエージェントがコードを編集し、
Webサイトの変更内容をちゃんと確認できるところまで成功しました。
なぜリアルタイムに反映されるのか?
流れはこんな感じです。
flowchart TD
A["ユーザーが変更を指示"] --> B["AIエージェントがコードを編集"]
B --> C["ファイルを保存"]
C --> D["Viteが変更を検知"]
D --> E["WebSocketでブラウザに通知"]
E --> F["プレビュー画面が更新"]
Session endpointsは、通常のHTTPリクエストだけでなく
WebSocket通信も転送できるので、Viteのホットリロード機能をそのまま使えます。
エージェントがファイルを触るたびに、Webサイトの変更をブラウザ側で確認できる、というわけです。
(実際のWebSocket通信については、後述の「追加で気になったことを検証」で詳しく紹介します。)
手順⑦ 後片付けをする
プレビューを実行しているターミナルでCtrl + Cを押し、ローカルのプレビューとプロキシを停止します。
続いて、公式サンプルに含まれるクリーンアップスクリプトを実行します。
python cleanup.py
このスクリプトで、サンプルが作ったRuntime、S3上のコード、IAMロールなどが削除されます。
ただしS3バケット自体やCloudWatch Logsなどが残る場合があるので、他の用途で使っていないか確認してから整理してください。
追加で気になったことを検証
公式サンプルを動かしてみると、認証やセッション分離、WebSocket通信など、内部の仕組みも気になってきました。そこで、いくつか追加で検証してみました。
①認証なしでアクセスするとHTTP 403が返る
AWS側のSession endpoint URLに、認証署名なしのcurlでアクセスしてみました。
read -r -p "Session endpoint URL: " ENDPOINT_URL
curl -sS -o /dev/null \
-w 'HTTP Status: %{http_code}\n' \
--max-time 15 \
"${ENDPOINT_URL%/}/"
HTTP Status: 403
ちゃんと403で弾かれました。一方、AWS SDKを使うPreviewApp経由ではアクセスできています。
(http://localhost:8088はローカルのPreviewAppなので、こっちが開けるのは当然です。Session endpoint自体が匿名公開されているわけではありません。403の詳細理由やIAMロール違いまでは追っていませんが、「認証が必要」という説明どおりの挙動でした。)
②複数セッションはちゃんと独立していた
同じAgentCore Runtimeで2つのセッションを同時起動し、変更が混ざらないか確認しました。
ターミナルAとBで、それぞれ以下のコードを実行します。事前に同じサンプルディレクトリへ移動し、仮想環境を有効化しておきます。
ターミナルA:
python - <<'PY'
import time
from preview_app import PreviewApp
app = PreviewApp(ui_port=8087, proxy_port=8091).start()
try:
print(app.session_id, app.url, flush=True)
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
finally:
app.stop()
PY
ターミナルB:
python - <<'PY'
import time
from preview_app import PreviewApp
app = PreviewApp(ui_port=8088, proxy_port=8092).start()
try:
print(app.session_id, app.url, flush=True)
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
finally:
app.stop()
PY
ブラウザでhttp://localhost:8087とhttp://localhost:8088を開き、それぞれ次の指示を送ります。
- Session A:Webサイトの背景色を赤色に変更
- Session B:Webサイトの背景色を青色に変更
!image.png
結果、Session Aは赤、Session Bは青になり、お互いの変更は混ざりませんでした。同じRuntime上でもセッションごとに異なる編集結果が保持されていました(ファイルシステムの内部的な隔離方式や、IAMユーザー間の権限周りまでは今回は検証していません)。
③WebSocketでViteの更新通知がちゃんと転送された
Session endpointsが本当にWebSocket通信も転送してくれるのか気になったので、開発サーバーをブラウザで開いてEdgeの開発者ツールで「ネットワーク」→「Socket」を見てみました。
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Protocol: vite-hmr
101 Switching ProtocolsはWebSocketへの切り替え成功を示すレスポンスで、vite-hmrはViteのホットリロードのサブプロトコルです。ちゃんとつながっていますね。
「メッセージ」タブを開いた状態で、AIエージェントに「Webサイトのメインタイトルの文字色だけを緑色に変更してください」と指示してみると、まず接続完了のメッセージが来て、
!image.png
その後、こんな更新通知が届きました(主要項目を抜粋)。
{
"type": "update",
"updates": [
{
"type": "css-update",
"path": "/src/style.css?direct",
"acceptedPath": "/src/style.css?direct",
"timestamp": 1793593126711
}
]
}
css-updateは、ViteがCSSの変更を検知してブラウザへ送る更新通知です(ページ全体を再読み込みするfull-reloadとは別物)。
flowchart TD
A["ユーザーが日本語で変更を指示"] --> B["AIエージェントがCSSを編集"]
B --> C["Viteが変更を検知"]
C --> D["WebSocketでcss-updateを送信"]
D --> E["Session endpointsが通信を転送"]
E --> F["ローカルプロキシ経由でブラウザが受信"]
ファイル変更の検知と更新通知はVite側の仕事で、Session endpointsは
そのWebSocket通信を転送する役割を担っています。そのおかげでAIがCSSを編集した直後に
ブラウザ側へちゃんと通知が届くところまで確認できました
(今回確認できたのはCSSの更新だけなので、HTMLやJSの変更も必ず再読み込みなしで反映される、と断定はできません)。
④プレビューを止めるとどうなるか
PreviewAppをCtrl + Cで止めると、ローカルのプレビュー画面にはアクセスできなくなりました。新しいセッションを起動しても、前の編集内容は引き継がれません。
(あくまでローカルのPreviewAppとプロキシを止めた結果の観察です。AWS側のセッションがその瞬間に終了したかどうかまでは確認していません。)
ハマったポイント
モデルIDを後から変更するとSession endpointが取得できなくなった
手順どおりに進めるだけなら踏まなくて済む話ですが、
せっかくハマったので記録しておきます。
今回、モデルIDを変更する際に地味にハマりました。
最初はデフォルトのモデルIDでデプロイしてしまったので、
Runtimeの環境変数を後から更新しました。モデルIDの変更自体は無事成功しました。
{
"Status": "READY",
"Environment": {
"MODEL_ID": "jp.anthropic.claude-haiku-5-5"
}
}
ところが、その後プレビューを起動すると、次のエラーが出ました。
AttributeError:
'NoneType' object has no attribute 'rstrip'
エラーが発生した箇所はこちら。
self.endpoint = self.client.session_endpoint_client(
session_endpoint_url(answer)
)
つまり、Session endpointのURLが取れていなかったわけです。
調べてみると、
今回のRuntime更新処理では既存の設定を取得して更新APIにそのまま渡していたのですが、
get_agent_runtime()のレスポンスにはallowedPortsが含まれておらず、
更新リクエストでもallowedPortsを指定していませんでした。
更新のタイミングでSession endpoints用のポート設定が引き継がれずに消えてしまうのかもしれません(勘ですがallowedPortsを明示して再更新したら直ったので…)。
Boto3からupdate_agent_runtime()を呼び出し、必要なポートを明示的に指定したところ、解消しました。
import boto3
client = boto3.client(
"bedrock-agentcore-control",
region_name="ap-northeast-1"
)
runtime_id = "YOUR_RUNTIME_ID"
current = client.get_agent_runtime(
agentRuntimeId=runtime_id
)
params = {
"agentRuntimeId": runtime_id,
"agentRuntimeArtifact": current["agentRuntimeArtifact"],
"roleArn": current["roleArn"],
"networkConfiguration": current["networkConfiguration"],
"protocolConfiguration": current["protocolConfiguration"],
"lifecycleConfiguration": current["lifecycleConfiguration"],
"environmentVariables": {
**current.get("environmentVariables", {}),
"MODEL_ID": "jp.anthropic.claude-haiku-5-5"
},
"allowedPorts": [
{"port": 8090},
{"port": 8081}
]
}
result = client.update_agent_runtime(**params)
print(result["status"])
これでRuntimeが新しいバージョンに更新され、
再度PreviewAppを起動したら正常にSession endpointsが使えるようになりました。
使いどころと注意点
嬉しかったポイント
今回触ってみていいなと感じたのは、
1. AIエージェントが作ったWebアプリの変更を、その実行環境のまま確認できる
1. AIエージェントとWebアプリ(成果物)を同期する仕組みを別途用意しなくてよい
1. Webサイトに限らず管理画面や開発用APIなどSession endpointsが使える対象なら同じ仕組みを応用できる
1. セッション単位でアクセス先が分離されるため複数ユーザーが同時に使う構成にも展開できそう
使う際の注意点
今回触ってみて気をつけたいと感じたのは、
1. Session endpointsはあくまで開発中の確認用で、Webサイトを一般公開するホスティングとは別物という点(公開するならAmplify Hostingなどが必要)
1. AIエージェントが編集したファイルはRuntimeのセッション内にあるため、セッション終了や実行環境の置き換えで失われうる点(長期保存したいならS3などへの保存を検討)
1. AgentCore RuntimeやBedrockの呼び出しには料金が発生するため、検証後は不要なRuntimeやリソースを削除する必要がある
まとめ
今回は、Amazon Bedrock AgentCore RuntimeのSession endpointsを使って、
AIエージェントが開発しているWebアプリをリアルタイムにプレビューする機能を触ってみました。
変更指示、コード編集、ブラウザへ反映までを一連の流れで確認できました。
AIエージェントはコードの生成だけでなく、構築・実行・テストへと担当領域を
どんどん広げているので、こういう仕組みは重要になっていきそうです。
個人的には、PoC環境の構築に使えそうだなと感じました。
参考資料
- AWS公式ブログ:Preview web apps live as your coding agent builds them with Amazon Bedrock AgentCore runtime
- AWS公式GitHub:agentcore-samples
- 今回使用したサンプル:16-session-endpoints
- Amazon Bedrock AgentCore ドキュメント
1 like
Mentions
AIエージェントが開発中のWebアプリをリアルタイムプレビューできるBedrock AgentCore Session endpointsを試してみた :::note warn この記事はAI(Codex)と一緒に作成しました。 内容は2026年11月時点の検証結果です。 ::: はじめに 2026年10月30日、AWSから以下の記事が公開されました。 > Preview web apps live as your coding agent builds them with Amazon Bedrock AgentCore runtime AIエージェントがWebアプリを開発している最中に、 そのWebアプリをブラウザからリアルタイムにプレビューできるという内容です。 コーディングエージェントを使えば簡単にWebアプリを作れる時代になりましたが、 クラウド上で動くAIエージェントが作ったものを確認するには、 コードを取得してローカルで起動したりする手間がかかることもあります。 そこでAmazon Bedrock AgentCore RuntimeのSession endpointsという機能を使うと、 AIエージェントが動いている実行環境内のWebサーバーに、認証付きでアクセスできます。 つまり、AIエージェントがコードを編集した瞬間、その変更をブラウザで確認できるわけです。面白そうなので触ってみました。 !{348A9BEA-EF0D-4DCD-B86C-DBEFAC81422B}.png > 赤枠がエージェントとのチャット画面、青枠がWebアプリのプレビュー画面です。 > 赤枠で相談した内容が青枠に即時反映されます。 今回はAWS公式サンプルを使って、日本向けの推論プロファイルで実際に動作を検証してみました。 実際に動かしてみた 今回やってみたことは、次の3つです。 1. AgentCore Runtime上でコーディングエージェントを動かす 2. エージェントが編集しているWebサイトをブラウザから表示する 3. 日本語で変更を指示し、Webサイトがリアルタイムに更新されることを確認する 実際には、コーヒーショップのサンプルWebサイトに対して、次の指示を送りました。 > Webサイト全体を日本語に翻訳してください。 > デザインやレイアウトは変更しないでください。 結果として、AIエージェントがindex.htmlとsrc/main.jsを編集し、 変更後のWebサイトをブラウザから確認できました。(翻訳は微妙だけど) ■変更前(英文) !image.png ■変更後(日本語訳) !image.png セッション分離や認証なしアクセス、WebSocketの更新通知も気になったので、追加で検証してみました。モデルIDやRuntime更新で地味にハマったので、その対処もついでに紹介します。 Session endpointsとは? Session endpointsは、AgentCore Runtime内で動いている HTTPサーバーなどにアクセスできる仕組みです。 例えば、AIエージェントが同じ実行環境内でWebアプリの開発サーバーを起動していれば、 そのWebアプリを外部からプレビューできます。 通常のRuntime呼び出しとの違い AgentCore Runtimeには、AIエージェントを呼び出すための仕組みがもともとあります。 一方、Session endpointsは、AIエージェント自身ではなく、エージェントと同じセッション内で動いている別のアプリケーションにアクセスするための機能です。 | 項目 | Runtimeの通常呼び出し | Session endpoints | |---|---|---| | 主な用途 | AIエージェントの実行 | セッション内のアプリへのアクセス | | アクセス対象 | エージェントのAPI | 許可したポートのWebサーバーなど | | 今回の用途 | Webサイトの編集を指示 | 編集中のWebサイトを表示 | | 通信 | Runtime API | HTTP、WebSocketなど | Session endpointsでは、あらかじめ許可したポートだけにアクセスできます。 また、URLを知っているだけで誰でもアクセスできるわけではなく、IAMなどによる認証が必要です。 今回の構成 flowchart TD A["ローカルPCのブラウザ"] --> B["PreviewApp"] B -->|"編集指示"| C["AgentCore Runtime API"] C --> D["AIエージェント"] D --> E["Amazon Bedrock<br/>Claude Haiku 5.5"] D --> F["Webサイトのファイルを編集"] F --> G["Vite開発サーバー<br/>Port 8090"] G -->|"Session endpoints<br/>HTTP / WebSocket"| B B -->|"プレビューを表示"| A 今回のサンプルでは、主に3つのポートを使用します。 | ポート | 用途 | |---|---| | 8080 | AIエージェントの呼び出し | | 8090 | ViteによるWebサイトのプレビュー | | 8081 | ステータス確認用API | Viteはファイルの変更を検知してブラウザの表示を更新してくれるツールです。 今回の構成では、ViteのWebSocket通信もSession endpoints経由で転送されるので、 ブラウザを手動更新せずに変更内容を確認できます。 検証方法 AWS CLIの認証設定が完了していることを前提とします。 また、RuntimeやIAMロール、S3リソースを作成する権限に加え、 Runtimeの呼び出しとSession endpointsへのアクセス権限が必要です。 公式サンプルのPython依存関係は、bedrock-agentcore>=1.25.2、boto3>=1.43.122でした。 手順① 公式サンプルを取得する まず、AWS公式のGitHubリポジトリを取得します。 (WSLのターミナルから実行しました。) git clone https://github.com/awslabs/agentcore-samples.git 今回使用するディレクトリに移動します。 cd agentcore-samples/01-features/02-host-your-agent/01-runtime/03-advanced/16-session-endpoints このディレクトリには、以下のようなファイルがあります。 | ファイル | 役割 | |---|---| | deploy.py | AgentCore Runtimeのデプロイ | | cleanup.py | 作成したAWSリソースの削除 | | preview_app.py | ローカルのプレビュー画面の起動 | | session_endpoints_preview.ipynb | 公式の検証用Notebook | | agent/app.ts | AIエージェントの実装 | | site/ | サンプルWebサイト | 手順② Python環境を準備する Pythonの仮想環境を作成します。 uv venv 仮想環境を有効化します。 source .venv/bin/activate 依存パッケージをインストールします。 uv pip install -r requirements.txt これでPython側の準備は完了です。 手順③ 利用するモデルIDを確認する 公式サンプルでは、モデルIDのデフォルト値として us.anthropic.claude-haiku-5-5が指定されています。 私は日本向け推論プロファイルを利用したかったので以下のモデルIDを使いました。 jp.anthropic.claude-haiku-5-5 なお、モデルIDと推論プロファイルのIDは別物で、一覧に表示されるモデルでも直接指定して呼べるとは限りません。利用できるモデルや推論プロファイルはリージョンやアカウントの権限によって変わるので、上記のIDがどの環境でもそのまま使えるとは限らない点だけ補足しておきます。 手順④ AgentCore Runtimeをデプロイする 公式サンプルのdeploy.pyを実行します。 日本向け推論プロファイル利用時はモデルIDを明示的に指定しましょう。 python deploy.py \ --model jp.anthropic.claude-haiku-5-5 デプロイが完了すると、RuntimeのステータスがREADYになります。 今回のサンプルは、Node.jsのアプリケーションをZIP形式でS3にアップロードし、 AgentCore Runtimeで実行する構成です。 (つまりDockerイメージやECRリポジトリを自分で準備する必要がないわけですね!) Session endpoints用のポート設定 deploy.pyでは、次のような設定が使われています。 protocolConfiguration={ "serverProtocol": "HTTP", "port": 8080, "path": "/invocations" }, allowedPorts=[ {"port": 8090}, {"port": 8081} ] - protocolConfigurationは、AIエージェント本体の呼び出し先を設定しています。 - allowedPortsは、Session endpoints経由でアクセスを許可するポートです。 今回はWebサイトのプレビュー用に8090、ステータス確認用に8081を指定しています。 (allowedPortsを設定するだけでWebサーバーが起動するわけではありません) 手順⑤ プレビュー画面を起動する Runtimeのデプロイが完了したら、プレビュー画面を起動します。 今回は次のPythonコードを実行しました。 python - <<'PY' import time from preview_app import PreviewApp app = PreviewApp().start() print(f"プレビューURL: {app.url}", flush=True) try: while True: time.sleep(1) except KeyboardInterrupt: pass finally: app.stop() print("セッションを終了しました") PY 成功すると、プレビューURLが表示されます。 プレビューURL: http://localhost:8087 ブラウザからこのURLを開きます。 すると最初にお見せした、 左側にAIエージェントとのチャット画面、右側にコーヒーショップのサンプルWebサイト が表示されます。 !image.png 右側のWebサイトはローカルPC上で動いているわけではなく、 AgentCore Runtimeのセッション内で動いていて、Session endpointsを通じて ローカルブラウザに表示されています。 内部では何が起きているのか? PreviewAppの起動処理を見てみると、こうなっています。 answer = self.invoke({"prompt": ""}) started = json.loads(answer["response"].read()) self.endpoint = self.client.session_endpoint_client( session_endpoint_url(answer) ) self.local = self.endpoint.open_local_endpoint( port=self.config["preview_port"], local_port=self.proxy_port ).start() まずInvokeAgentRuntimeでセッションを起動し、 レスポンスからSession endpointのURLを取得して、ローカル側に接続口を作っています。 このローカル側の接続口がAWS認証情報を付けてリクエストを転送してくれるので、 ブラウザ自身がAWSのSigV4署名を実装する必要はありません。地味に便利な仕組みです。 手順⑥ AIエージェントに日本語で変更を指示する いよいよWebサイトを変更してみます。 左側のチャット欄に、以下の指示を入力しました。 !{E42D5922-5C0B-4331-B6B9-9410A8750ACA}.png するとコードを触っているログが表示され、 最終的には、変更が完了したことを示すメッセージが表示されました。 実際に、Webサイト内の英語が日本語に変更され、ブラウザ側にも反映されました。 !{CEE37FE4-6060-4EFC-9117-6FF7F0CD7AC5}.png AIエージェントがコードを編集し、 Webサイトの変更内容をちゃんと確認できるところまで成功しました。 なぜリアルタイムに反映されるのか? 流れはこんな感じです。 flowchart TD A["ユーザーが変更を指示"] --> B["AIエージェントがコードを編集"] B --> C["ファイルを保存"] C --> D["Viteが変更を検知"] D --> E["WebSocketでブラウザに通知"] E --> F["プレビュー画面が更新"] Session endpointsは、通常のHTTPリクエストだけでなく WebSocket通信も転送できるので、Viteのホットリロード機能をそのまま使えます。 エージェントがファイルを触るたびに、Webサイトの変更をブラウザ側で確認できる、というわけです。 (実際のWebSocket通信については、後述の「追加で気になったことを検証」で詳しく紹介します。) 手順⑦ 後片付けをする プレビューを実行しているターミナルでCtrl + Cを押し、ローカルのプレビューとプロキシを停止します。 続いて、公式サンプルに含まれるクリーンアップスクリプトを実行します。 python cleanup.py このスクリプトで、サンプルが作ったRuntime、S3上のコード、IAMロールなどが削除されます。 ただしS3バケット自体やCloudWatch Logsなどが残る場合があるので、他の用途で使っていないか確認してから整理してください。 追加で気になったことを検証 公式サンプルを動かしてみると、認証やセッション分離、WebSocket通信など、内部の仕組みも気になってきました。そこで、いくつか追加で検証してみました。 ①認証なしでアクセスするとHTTP 403が返る AWS側のSession endpoint URLに、認証署名なしのcurlでアクセスしてみました。 read -r -p "Session endpoint URL: " ENDPOINT_URL curl -sS -o /dev/null \ -w 'HTTP Status: %{http_code}\n' \ --max-time 15 \ "${ENDPOINT_URL%/}/" HTTP Status: 403 ちゃんと403で弾かれました。一方、AWS SDKを使うPreviewApp経由ではアクセスできています。 (http://localhost:8088はローカルのPreviewAppなので、こっちが開けるのは当然です。Session endpoint自体が匿名公開されているわけではありません。403の詳細理由やIAMロール違いまでは追っていませんが、「認証が必要」という説明どおりの挙動でした。) ②複数セッションはちゃんと独立していた 同じAgentCore Runtimeで2つのセッションを同時起動し、変更が混ざらないか確認しました。 ターミナルAとBで、それぞれ以下のコードを実行します。事前に同じサンプルディレクトリへ移動し、仮想環境を有効化しておきます。 ターミナルA: python - <<'PY' import time from preview_app import PreviewApp app = PreviewApp(ui_port=8087, proxy_port=8091).start() try: print(app.session_id, app.url, flush=True) while True: time.sleep(1) except KeyboardInterrupt: pass finally: app.stop() PY ターミナルB: python - <<'PY' import time from preview_app import PreviewApp app = PreviewApp(ui_port=8088, proxy_port=8092).start() try: print(app.session_id, app.url, flush=True) while True: time.sleep(1) except KeyboardInterrupt: pass finally: app.stop() PY ブラウザでhttp://localhost:8087とhttp://localhost:8088を開き、それぞれ次の指示を送ります。 - Session A:Webサイトの背景色を赤色に変更 - Session B:Webサイトの背景色を青色に変更 !image.png 結果、Session Aは赤、Session Bは青になり、お互いの変更は混ざりませんでした。同じRuntime上でもセッションごとに異なる編集結果が保持されていました(ファイルシステムの内部的な隔離方式や、IAMユーザー間の権限周りまでは今回は検証していません)。 ③WebSocketでViteの更新通知がちゃんと転送された Session endpointsが本当にWebSocket通信も転送してくれるのか気になったので、開発サーバーをブラウザで開いてEdgeの開発者ツールで「ネットワーク」→「Socket」を見てみました。 HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: websocket Sec-WebSocket-Protocol: vite-hmr 101 Switching ProtocolsはWebSocketへの切り替え成功を示すレスポンスで、vite-hmrはViteのホットリロードのサブプロトコルです。ちゃんとつながっていますね。 「メッセージ」タブを開いた状態で、AIエージェントに「Webサイトのメインタイトルの文字色だけを緑色に変更してください」と指示してみると、まず接続完了のメッセージが来て、 !image.png その後、こんな更新通知が届きました(主要項目を抜粋)。 { "type": "update", "updates": [ { "type": "css-update", "path": "/src/style.css?direct", "acceptedPath": "/src/style.css?direct", "timestamp": 1793593126711 } ] } css-updateは、ViteがCSSの変更を検知してブラウザへ送る更新通知です(ページ全体を再読み込みするfull-reloadとは別物)。 flowchart TD A["ユーザーが日本語で変更を指示"] --> B["AIエージェントがCSSを編集"] B --> C["Viteが変更を検知"] C --> D["WebSocketでcss-updateを送信"] D --> E["Session endpointsが通信を転送"] E --> F["ローカルプロキシ経由でブラウザが受信"] ファイル変更の検知と更新通知はVite側の仕事で、Session endpointsは そのWebSocket通信を転送する役割を担っています。そのおかげでAIがCSSを編集した直後に ブラウザ側へちゃんと通知が届くところまで確認できました (今回確認できたのはCSSの更新だけなので、HTMLやJSの変更も必ず再読み込みなしで反映される、と断定はできません)。 ④プレビューを止めるとどうなるか PreviewAppをCtrl + Cで止めると、ローカルのプレビュー画面にはアクセスできなくなりました。新しいセッションを起動しても、前の編集内容は引き継がれません。 (あくまでローカルのPreviewAppとプロキシを止めた結果の観察です。AWS側のセッションがその瞬間に終了したかどうかまでは確認していません。) ハマったポイント モデルIDを後から変更するとSession endpointが取得できなくなった 手順どおりに進めるだけなら踏まなくて済む話ですが、 せっかくハマったので記録しておきます。 今回、モデルIDを変更する際に地味にハマりました。 最初はデフォルトのモデルIDでデプロイしてしまったので、 Runtimeの環境変数を後から更新しました。モデルIDの変更自体は無事成功しました。 { "Status": "READY", "Environment": { "MODEL_ID": "jp.anthropic.claude-haiku-5-5" } } ところが、その後プレビューを起動すると、次のエラーが出ました。 AttributeError: 'NoneType' object has no attribute 'rstrip' エラーが発生した箇所はこちら。 self.endpoint = self.client.session_endpoint_client( session_endpoint_url(answer) ) つまり、Session endpointのURLが取れていなかったわけです。 調べてみると、 今回のRuntime更新処理では既存の設定を取得して更新APIにそのまま渡していたのですが、 get_agent_runtime()のレスポンスにはallowedPortsが含まれておらず、 更新リクエストでもallowedPortsを指定していませんでした。 更新のタイミングでSession endpoints用のポート設定が引き継がれずに消えてしまうのかもしれません(勘ですがallowedPortsを明示して再更新したら直ったので…)。 Boto3からupdate_agent_runtime()を呼び出し、必要なポートを明示的に指定したところ、解消しました。 import boto3 client = boto3.client( "bedrock-agentcore-control", region_name="ap-northeast-1" ) runtime_id = "YOUR_RUNTIME_ID" current = client.get_agent_runtime( agentRuntimeId=runtime_id ) params = { "agentRuntimeId": runtime_id, "agentRuntimeArtifact": current["agentRuntimeArtifact"], "roleArn": current["roleArn"], "networkConfiguration": current["networkConfiguration"], "protocolConfiguration": current["protocolConfiguration"], "lifecycleConfiguration": current["lifecycleConfiguration"], "environmentVariables": { **current.get("environmentVariables", {}), "MODEL_ID": "jp.anthropic.claude-haiku-5-5" }, "allowedPorts": [ {"port": 8090}, {"port": 8081} ] } result = client.update_agent_runtime(**params) print(result["status"]) これでRuntimeが新しいバージョンに更新され、 再度PreviewAppを起動したら正常にSession endpointsが使えるようになりました。 使いどころと注意点 嬉しかったポイント 今回触ってみていいなと感じたのは、 1. AIエージェントが作ったWebアプリの変更を、その実行環境のまま確認できる 1. AIエージェントとWebアプリ(成果物)を同期する仕組みを別途用意しなくてよい 1. Webサイトに限らず管理画面や開発用APIなどSession endpointsが使える対象なら同じ仕組みを応用できる 1. セッション単位でアクセス先が分離されるため複数ユーザーが同時に使う構成にも展開できそう 使う際の注意点 今回触ってみて気をつけたいと感じたのは、 1. Session endpointsはあくまで開発中の確認用で、Webサイトを一般公開するホスティングとは別物という点(公開するならAmplify Hostingなどが必要) 1. AIエージェントが編集したファイルはRuntimeのセッション内にあるため、セッション終了や実行環境の置き換えで失われうる点(長期保存したいならS3などへの保存を検討) 1. AgentCore RuntimeやBedrockの呼び出しには料金が発生するため、検証後は不要なRuntimeやリソースを削除する必要がある まとめ 今回は、Amazon Bedrock AgentCore RuntimeのSession endpointsを使って、 AIエージェントが開発しているWebアプリをリアルタイムにプレビューする機能を触ってみました。 変更指示、コード編集、ブラウザへ反映までを一連の流れで確認できました。 AIエージェントはコードの生成だけでなく、構築・実行・テストへと担当領域を どんどん広げているので、こういう仕組みは重要になっていきそうです。 個人的には、PoC環境の構築に使えそうだなと感じました。 参考資料 - AWS公式ブログ:Preview web apps live as your coding agent builds them with Amazon Bedrock AgentCore runtime - AWS公式GitHub:agentcore-samples - 今回使用したサンプル:16-session-endpoints - Amazon Bedrock AgentCore ドキュメント