[アップデート] Amazon Bedrock AgentCore Runtimeのセッション内で動くサーバーに直接アクセスできる機能Session endpointsが追加されました!

[アップデート] Amazon Bedrock AgentCore Runtimeのセッション内で動くサーバーに直接アクセスできる機能Session endpointsが追加されました!

AgentCore Runtimeに新機能Session endpointsが追加されたのでセッション内のWebサイトをブラウザから直接プレビューできるか試してみました!
2026.11.01

はじめに

こんにちは、スーパーマーケットが大好きなコンサル部の神野です。

2026年10月30日にAWS公式ブログでAmazon Bedrock AgentCore RuntimeのSession endpointsが発表されました!セッションの中で動くサーバーに直接アクセスできるエンドポイントを提供する機能です。What's Newにはなくブログのみで紹介されるのはちょっと珍しいですね。(見逃していたらすみません・・・)

https://aws.amazon.com/blogs/machine-learning/preview-web-apps-live-as-your-coding-agent-builds-them-with-amazon-bedrock-agentcore-runtime/

公式ドキュメントにもしっかりと情報がありました!

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-session-endpoints.html

何やらClaudeのArtifactsのような体験をAgentCoreのマネージド機能を使って作れるようになったアップデートに感じました・・・!

まずアップデート内容を押さえて、その後Strands harnessで作ったエージェントにWebサイトを一式作成してもらい、できたサイトは自分のブラウザでプレビューしてこのアップデートを体験してみましょう!

主な変更点

まずどんなアップデートなんでしょうか。APIの変化から見ていきましょう!

API 変更内容
CreateAgentRuntime / UpdateAgentRuntime / GetAgentRuntime allowedPortsとprotocolConfigurationのport・pathが追加
InvokeAgentRuntime レスポンスにsessionEndpointUrlが追加

変更は大きく分けて2つで、1つはセッションの中のサーバーへ直接アクセスできるようになったこと、もう1つはエージェントの待ち受けポートとパスを変えられるようになったことです。

まずは1つ目の変更を絵にしてみました!

これまではPCからInvokeAgentRuntimeでエージェントを呼び出せてもセッション内のWebサイトには届かなかった。今回からはセッションURLでWebサイトに直接届く

これまでもエージェントの呼び出しやコマンドの実行はできましたが、セッションの中で動くWebサイトを自分のブラウザで開くことはできませんでした。今回からは許可したポートに専用のURL(セッションURL)でアクセスできます!

AIエージェントのアウトプットが簡単に確認できる手段が増えたのは嬉しいですね!

もう少し仕組みを深掘りしてみます!

セッションURLの仕組み

まずはセッションURLがどう発行されるのか仕組みを見ていきます。

セッションURLを使うにはRuntimeを作るときにアクセスを許可するポートを指定しておきます。
この設定がallowedPortsです。

指定したRuntimeでエージェントを呼び出すとレスポンスにセッションURL(sessionEndpointUrl)が入ってきます。任意のポートにアクセスしたい場合はURLの先頭に 8081-- のようにポート番号を付けて指定します。付けなければエージェントの待ち受けポートに届きます。

セッションURLの形
https://<識別子>.runtime.bedrock-agentcore.<リージョン>.on.aws/            ← エージェントの待ち受けポート
https://8081--<識別子>.runtime.bedrock-agentcore.<リージョン>.on.aws/      ← 8081番

流れを絵にするとこんな感じです。

InvokeAgentRuntimeのレスポンスでセッションURLを受け取る。先頭に8081--を付けて署名付きで送ると8081番のWebサイトにGET /index.htmlがそのまま届く。ポートを付けなければ待ち受けポートの9090番に届く

メソッドやパスはそのまま中のサーバーに届くのでアプリにあるルートを呼び出せます。待ち受けポートを含めて届け先のポートはすべてallowedPortsに登録しておきます。
使えるのは8000〜12000番で最大5件までです。

もちろんURLを知っているだけではアクセスできません。Runtimeに設定した方式での認証・認可が必要で、IAMで認証する場合はリクエストごとにAWSの認証情報で署名(SigV4)を付けます。呼び出す側には bedrock-agentcore:InvokeAgentRuntimeProxy の権限も要ります。
JWT認証の場合はBearer Tokenをつけてといった形です。

待ち受けポートとパスを変える

もう1つはエージェントが待ち受けるポートとパスを任意のものに変更できるようになりました!

これまでエージェントは8080番の /invocations で待ち受ける仕様だったのですが、このアップデートでポート9090番の /agent/invoke のように変えられます。設定するのはprotocolConfigurationのportとpathです。

こちらも絵にするとこんな感じです。

これまではInvokeAgentRuntimeが8080番のPOST /invocationsに固定で届いた。今回からはprotocolConfigurationで指定した9090番のPOST /agent/invokeに届く

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-configure-invocation.html

変わるのはエージェントを呼び出すときの届け先1か所で、呼び出し口を増やすわけではないので注意です!

パスごとにルートを分けて呼び出したいときはセッションURLを使います。2つの設定はそれぞれ単独でも使えます。今回はせっかくなので両方を組み合わせて試します!

前提

下記構成の前提で進めていきます!

項目 バージョンなど
リージョン 東京(ap-northeast-1)
Python 3.14
コンテナのベースイメージ ghcr.io/astral-sh/uv:python3.14-bookworm-slim
boto3 1.43.123
bedrock-agentcore 1.25.2
strands-harness 0.3.2(strands-agents 1.62.0)
fastapi / uvicorn 0.162.0 / 0.54.0
モデル Claude Haiku 5.5(jp.anthropic.claude-haiku-5-5)

allowedPortsとsessionEndpointUrlを扱うにはboto3 1.43.122以上が必要です。セッションURLへ署名付きでアクセスするクライアントはbedrock-agentcore 1.25.2で追加されています。

それではさっそくやってみましょう!

やってみた

今回の構成です!
Strands harnessのエージェントを9090番の /agent/invoke で待ち受けさせます。エージェントが作ったサイトは同じセッションの8081番で配信する作りにしてみます。

PCからの署名付きリクエストをRuntimeの入口が署名とallowedPortsで確認する。ポート指定なしは9090番のエージェントへ届く。8081--は8081番のWebサイトへ届く。待ち受けのない8082--は502になる。許可外の8090--は入口で403になる

allowedPortsには9090番と8081〜8083番の範囲を入れます。
8082番はあえて何も待ち受けさせず許可外の8090番と合わせてエラーの違いも確かめてみます。

セットアップ

依存関係などインストールしていきます!

セットアップ
uv init --python 3.14 agentcore-session-endpoints
cd agentcore-session-endpoints
uv add "boto3>=1.43.122" "bedrock-agentcore>=1.25.2"

# コンテナに入れるエージェント側のプロジェクト
mkdir agent && cd agent
uv init --bare --no-workspace --name session-endpoint-agent --python 3.14
uv add "strands-harness==0.3.2" fastapi uvicorn
cd ..

エージェントを用意する

今回使用するStrands harnessはシェル・ファイル操作などのツールとシステムプロンプトがそろったエージェントを create_harness() で作成できるパッケージです。サクッと何かを作らせるのによいので今回使用します!

詳しくは以前の記事で紹介しています!

https://dev.classmethod.jp/articles/strands-harness-vs-agent/

エージェントには /tmp/workspace/site にファイルを作るよう指示し、また同じプロセスで ./site を8081番で配信するサーバーも起動します。
9090番にはセッションURLから呼び出す独自ルートとして /files も足しておきます。

agent/main.py
import os
import threading
from functools import partial
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path

import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel
from strands_harness import create_harness

WORKSPACE = Path("/tmp/workspace")
SITE_DIR = WORKSPACE / "site"
SITE_DIR.mkdir(parents=True, exist_ok=True)
os.chdir(WORKSPACE)

agent = create_harness(
    model="jp.anthropic.claude-haiku-5-5",
    instructions=(
        "あなたはWebサイトを作るアシスタントです。"
        "ファイルはすべて ./site 配下に作成してください。"
        "./site はポート8081で配信済みなので、サーバーを起動する必要はありません。"
    ),
    session=False,
    memory=False,
    callback_handler=None,
)

app = FastAPI()

class InvokeRequest(BaseModel):
    prompt: str

@app.get("/ping")
def ping():
    return {"status": "Healthy"}

# protocolConfiguration.path で指定したパス
@app.post("/agent/invoke")
def invoke(request: InvokeRequest):
    result = agent(request.prompt)
    return {"response": str(result).strip()}

# セッションURLからだけ届く独自のルート
@app.get("/files")
def files():
    return {"files": sorted(str(p.relative_to(SITE_DIR)) for p in SITE_DIR.rglob("*") if p.is_file())}

def serve_site():
    handler = partial(SimpleHTTPRequestHandler, directory=str(SITE_DIR))
    ThreadingHTTPServer(("0.0.0.0", 8081), handler).serve_forever()

if __name__ == "__main__":
    threading.Thread(target=serve_site, daemon=True).start()
    uvicorn.run(app, host="0.0.0.0", port=9090)

AgentCoreのSDKにはエージェント用のサーバーを作れるBedrockAgentCoreAppが馴染みあると思いますが、使用すると受け口のパスは /invocations に固定されています。今回はパスの変更も試したいので公式ドキュメントの例と同じくFastAPIで /agent/invoke を用意しました。

デプロイする

コンテナイメージにしてデプロイします。agent/ に次のDockerfileを置きます。

agent/Dockerfile
FROM ghcr.io/astral-sh/uv:python3.14-bookworm-slim
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev
COPY main.py ./
EXPOSE 9090 8081
CMD ["uv", "run", "--no-sync", "main.py"]

AgentCore Runtimeはarm64で動くのでarm64でビルドします。できたイメージはコンテナイメージの保管場所であるAmazon ECRにプッシュします。

build_push.sh
#!/bin/sh
set -eu
REGION=ap-northeast-1
REPO=session-endpoint-demo
ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
REGISTRY=$ACCOUNT.dkr.ecr.$REGION.amazonaws.com

aws ecr describe-repositories --repository-names $REPO --region $REGION >/dev/null 2>&1 \
  || aws ecr create-repository --repository-name $REPO --region $REGION >/dev/null
aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $REGISTRY
docker buildx build --platform linux/arm64 -t $REGISTRY/$REPO:latest --push agent

ECRのイメージを指定してRuntimeを作ります。
今回のポイントはprotocolConfigurationとallowedPortsの2か所です。下記のように指定します!

deploy.py(Runtimeを作る部分)
runtime = control.create_agent_runtime(
    agentRuntimeName=NAME,
    agentRuntimeArtifact={"containerConfiguration": {"containerUri": image_uri}},
    roleArn=role_arn,
    networkConfiguration={"networkMode": "PUBLIC"},
    # エージェントの待ち受けを 9090番の /agent/invoke に変える
    protocolConfiguration={"serverProtocol": "HTTP", "port": 9090, "path": "/agent/invoke"},
    # セッションURLから届くポート
    allowedPorts=[
        {"port": 9090},
        {"portRange": {"from": 8081, "to": 8083}},
    ],
)
deploy.py の全体(実行ロールの作成を含む)
deploy.py
import json
import time

import boto3

REGION = "ap-northeast-1"
NAME = "session_endpoint_demo"
ROLE_NAME = "AgentCoreSessionEndpointDemoRole"

account_id = boto3.client("sts").get_caller_identity()["Account"]
image_uri = f"{account_id}.dkr.ecr.{REGION}.amazonaws.com/session-endpoint-demo:latest"

# 実行ロール(ECRからのイメージ取得、Bedrockのモデル呼び出し、ログ出力)
iam = boto3.client("iam")
try:
    role_arn = iam.get_role(RoleName=ROLE_NAME)["Role"]["Arn"]
except iam.exceptions.NoSuchEntityException:
    role_arn = iam.create_role(
        RoleName=ROLE_NAME,
        AssumeRolePolicyDocument=json.dumps({
            "Version": "2012-10-17",
            "Statement": [{
                "Effect": "Allow",
                "Principal": {"Service": "bedrock-agentcore.amazonaws.com"},
                "Action": "sts:AssumeRole",
                "Condition": {"StringEquals": {"aws:SourceAccount": account_id}},
            }],
        }),
    )["Role"]["Arn"]
    iam.put_role_policy(
        RoleName=ROLE_NAME,
        PolicyName="runtime",
        PolicyDocument=json.dumps({
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": ["ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer"],
                    "Resource": f"arn:aws:ecr:{REGION}:{account_id}:repository/session-endpoint-demo",
                },
                {"Effect": "Allow", "Action": "ecr:GetAuthorizationToken", "Resource": "*"},
                {
                    "Effect": "Allow",
                    "Action": ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream"],
                    "Resource": "*",
                },
                {
                    "Effect": "Allow",
                    "Action": [
                        "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents",
                        "logs:DescribeLogGroups", "logs:DescribeLogStreams",
                    ],
                    "Resource": "*",
                },
            ],
        }),
    )
    time.sleep(15)  # ロールの反映待ち

control = boto3.client("bedrock-agentcore-control", region_name=REGION)
runtime = control.create_agent_runtime(
    agentRuntimeName=NAME,
    agentRuntimeArtifact={"containerConfiguration": {"containerUri": image_uri}},
    roleArn=role_arn,
    networkConfiguration={"networkMode": "PUBLIC"},
    # エージェントの待ち受けを 9090番の /agent/invoke に変える
    protocolConfiguration={"serverProtocol": "HTTP", "port": 9090, "path": "/agent/invoke"},
    # セッションURLから届くポート
    allowedPorts=[
        {"port": 9090},
        {"portRange": {"from": 8081, "to": 8083}},
    ],
)
runtime_id = runtime["agentRuntimeId"]

while (detail := control.get_agent_runtime(agentRuntimeId=runtime_id))["status"] not in ("READY", "CREATE_FAILED"):
    time.sleep(5)

print("status:", detail["status"])
print("protocolConfiguration:", detail.get("protocolConfiguration"))
print("allowedPorts:", detail.get("allowedPorts"))

with open("runtime.json", "w") as f:
    json.dump({"arn": runtime["agentRuntimeArn"], "id": runtime_id}, f)

スクリプトを実行してデプロイします!

実行
chmod +x build_push.sh
./build_push.sh
uv run deploy.py
実行結果
status: READY
protocolConfiguration: {'serverProtocol': 'HTTP', 'port': 9090, 'path': '/agent/invoke'}
allowedPorts: [{'port': 9090}, {'portRange': {'from': 8081, 'to': 8083}}]

問題なくデプロイできてREADYになりました!GetAgentRuntimeのレスポンスにも設定したポートとパスが入っていますね。

Runtimeができたのでエージェントにサイトを作ってもらってそれをのぞいてみましょう!

サイトを一式作ってもらう

今まで通りInvokeAgentRuntimeでエージェントを呼び出してレスポンスからsessionEndpointUrlを取得します。

invoke.py(セッションURLを取り出す部分)
response = client.invoke_agent_runtime(
    agentRuntimeArn=runtime_arn,
    runtimeSessionId=session_id,
    contentType="application/json",
    payload=json.dumps({"prompt": sys.argv[1]}).encode(),
)

print("runtimeSessionId:", response["runtimeSessionId"])
print("sessionEndpointUrl:", response.get("sessionEndpointUrl"))
invoke.py の全体
invoke.py
import json
import sys
import uuid

import boto3
from botocore.config import Config

REGION = "ap-northeast-1"
runtime_arn = json.load(open("runtime.json"))["arn"]

# 引数でセッションIDを渡すと、同じセッションで続きを依頼する
session_id = sys.argv[2] if len(sys.argv) > 2 else str(uuid.uuid4())
client = boto3.client(
    "bedrock-agentcore", region_name=REGION, config=Config(read_timeout=900)
)
response = client.invoke_agent_runtime(
    agentRuntimeArn=runtime_arn,
    runtimeSessionId=session_id,
    contentType="application/json",
    payload=json.dumps({"prompt": sys.argv[1]}).encode(),
)

print("runtimeSessionId:", response["runtimeSessionId"])
print("sessionEndpointUrl:", response.get("sessionEndpointUrl"))
print(json.loads(response["response"].read())["response"])

with open("session.json", "w") as f:
    json.dump({"session_id": session_id, "url": response.get("sessionEndpointUrl")}, f)

お題は架空のカフェ「ことり珈琲」のWebサイトにして、HTML・CSS・JavaScriptの3ファイルで一式作ってもらいます!

実行
uv run invoke.py "架空のカフェ「ことり珈琲」のWebサイトを新規作成してください。index.html・style.css・script.js の3ファイル構成で、トップ・メニュー・営業時間のセクションを入れてください。"
実行結果(抜粋)
runtimeSessionId: 55f06e7e-0bb1-46b7-97bf-3f8fac1f78a9
sessionEndpointUrl: https://<識別子>.runtime.bedrock-agentcore.ap-northeast-1.on.aws
「ことり珈琲」のWebサイトを `./site` に作成しました(`index.html` / `style.css` / `script.js`)。ポート8081で配信されており、3ファイルとも 200 で取得できることを確認しています。
(構成やscript.jsの機能などの説明が続く)

1分半ほどで3ファイルを作ってくれました!
レスポンスにsessionEndpointUrlも入っていますね!このURLを使ってセッションの中のサイトにアクセスします。

また /invocations を用意していないアプリでも応答が返ってきました!
protocolConfigurationで指定した9090番の /agent/invoke にちゃんと届いていますね。

セッションURLへアクセスする

セッションURLにリクエストを送ってみます!
IAMの署名が必要ですが、その署名はbedrock-agentcoreの session_endpoint_client が付けてくれます。

次の4つのエンドポイントにリクエストを送って試してみます。

  • ポート指定なし(9090番)の /files
  • 8081番の index.html
  • 8082番(許可しているけれど何も動いていない)
  • 8090番(allowedPortsに入れていない)
check.py
import json

from bedrock_agentcore.runtime import AgentCoreRuntimeClient

session = json.load(open("session.json"))
client = AgentCoreRuntimeClient(region="ap-northeast-1")
endpoint = client.session_endpoint_client(session["url"])

# ポート指定なし = エージェントの待ち受けポート(9090)の独自ルート
files = endpoint.request("GET", "/files")
print("GET /files ->", files.status, files.json())

# 8081番 = エージェントが作ったサイト
page = endpoint.request("GET", "/index.html", port=8081)
print("GET :8081/index.html ->", page.status, page.headers.get("content-type"), len(page.data), "bytes")
print(page.text[:300])

# 許可したが何も待ち受けていないポートと、許可していないポート
for port in (8082, 8090):
    r = endpoint.request("GET", "/", port=port)
    print(f"GET :{port}/ ->", r.status, "proxy_error:", r.proxy_error)
実行結果(uv run check.py、抜粋)
GET /files -> 200 {'files': ['index.html', 'script.js', 'style.css']}
GET :8081/index.html -> 200 text/html 10197 bytes
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  ...
  <title>ことり珈琲</title>
  <link rel="stylesheet" href="style.css">
GET :8082/ -> 502 proxy_error: PortNotReachable
GET :8090/ -> 403 proxy_error: AccessDenied

/files からはエージェントが作った3ファイルの一覧が返ってきました!
8081番からは index.html が返って、8082番は何も動いていないので502になり、8090番は許可していないので403で予想通りの結果ですね!

スクリプトからは問題なく呼び出せたので次はブラウザで見てみましょう!

ブラウザでプレビューする

セッションURLはリクエストごとに署名が必要なのでブラウザでそのまま開くことはできません。そこでbedrock-agentcoreのローカル中継(open_local_endpoint)を使います。PCの8088番で受けたリクエストに署名を付けてセッションの8081番へ転送してくれます。

preview.py
import json

from bedrock_agentcore.runtime import AgentCoreRuntimeClient

session = json.load(open("session.json"))
client = AgentCoreRuntimeClient(region="ap-northeast-1")
endpoint = client.session_endpoint_client(session["url"])

# localhost:8088 へのリクエストに署名を付けて、セッションの8081番へ中継する
with endpoint.open_local_endpoint(port=8081) as local:
    print("Open", local.url)
    input("Enterで終了します")
実行
uv run preview.py

表示された http://localhost:8088 を開くと・・・

エージェントが作ったことり珈琲のサイトが自分のブラウザで表示された。script.jsによる営業状況の表示も動いている

小鳥が可愛いですね!!!

といった感想はさておき、セッションの中でエージェントが作ったサイトが自分のブラウザで表示されました!CSSやフォントだけでなく script.js の処理である営業判定も動いていて、「本日の営業は終了しました」の表示も問題なく動作しています。撮影したのが23時半だったのでちゃんと閉店後と判定されていますね!

ブラウザを操作してJavaScriptの動きも軽く確認します。メニューの「スイーツ」を押すと3品に絞り込まれました。

ブラウザでスイーツのタブを押すとメニューが3品に絞り込まれた

営業時間の表では実行した土曜日の行に「今日」の印が付いています。

営業時間の表で実行した土曜日の行に今日の印が付いた

ページ内のリンクやスクリプトも普通のサイトと同じように動きます。エージェントが作ったものを触って確かめられるのはいいですね。

同じセッションで直してもらう

最後にプレビューを開いたまま同じセッションIDで修正を頼んでみます。同じセッションに届けば同じURLのまま変更後の画面が見られるはずです。

末尾のセッションIDは初回の実行結果に出たruntimeSessionIdに置き換えてください。

実行
uv run invoke.py "夜カフェ風に、背景を濃い紺色・文字を明るい色にした配色へ変えてください。" 55f06e7e-0bb1-46b7-97bf-3f8fac1f78a9
実行結果(抜粋)
runtimeSessionId: 55f06e7e-0bb1-46b7-97bf-3f8fac1f78a9
sessionEndpointUrl: https://<識別子>.runtime.bedrock-agentcore.ap-northeast-1.on.aws
配色を夜カフェ風(濃い紺の背景・明るい文字・ランプ色のアクセント)に変更しました。変更は `style.css` のみで、`index.html` と `script.js` は変えていません。

同じセッションなのでセッションURLも1回目と同じです。ブラウザを再読み込みすると・・・

同じセッションで配色の変更を頼むと同じURLのまま夜カフェ風の配色に変わった

同じURLのまま夜カフェ風の配色に変わりました!
ローカル中継を立ち上げ直す必要もありません!

エージェントに頼んでブラウザで確かめてまた頼むという流れをそのまま繰り返せます。

後片付け

preview.py をEnterで止めてからRuntime・ECRリポジトリ・実行ロールを削除します。

cleanup.py
cleanup.py
import json

import boto3

REGION = "ap-northeast-1"
runtime_id = json.load(open("runtime.json"))["id"]

boto3.client("bedrock-agentcore-control", region_name=REGION).delete_agent_runtime(agentRuntimeId=runtime_id)
boto3.client("ecr", region_name=REGION).delete_repository(repositoryName="session-endpoint-demo", force=True)

iam = boto3.client("iam")
iam.delete_role_policy(RoleName="AgentCoreSessionEndpointDemoRole", PolicyName="runtime")
iam.delete_role(RoleName="AgentCoreSessionEndpointDemoRole")
実行
uv run cleanup.py

使いどころ

最後に使い所を振り返ってみましょう!

セッションURL

まず思い浮かぶのは今回のようにコーディングエージェントが作った画面をその場で確かめる使い方です。ClaudeやCodexでもDesktopアプリで簡単にアウトプットが見れるように、同じようなものがAgentCoreで組み込んだアプリでもできそうですね!

セッションの中で立ち上げた開発サーバーやダッシュボードも同じように開けるので、エージェントとリアルタイムにやり取りするUIにも使えそうです。

待ち受けポートとパスの変更

すでに作ってあるWebアプリやAPIサーバーをAgentCore Runtimeに載せたいときに役立ちそうです!今まではHTTPなら8080番ポートでパスが/invocations である必要があったのでそれ以外のパスやポート番号を使いたいケースに役立つのかなぁと・・・

おわりに

セッション内で動くサーバーに対して許可したポートへ署名付きでアクセスできるようになりました!コーディングエージェント系のアプリが即座にアウトプットを見せたい、またリアルタイムでUIをAIに作らせるなどのケースで使えそうだなと思いました!

エージェントのデフォルトの待ち受けポートやパスも変えられるようになりました!どうしてもデフォルトのポートやパスから変えたい!といったケースに有用そうです。

最後までご覧いただきありがとうございました!

補足 ドキュメントに書かれている細かい仕様

公式ドキュメントには今回触れなかった仕様や注意点も書かれていて、気になったものをざっとまとめておきます。

セッションURLの有効期間

セッションURLはセッションに紐づくURLで、セッションが続いている間は同じURLを使えます。

セッションの実行環境はデフォルトで15分リクエストがないか8時間たつと止まります。止まったあとでもURLにリクエストを送ると新しい実行環境が用意されてアクセス可能です。ただしメモリ上の状態やファイルは引き継がれないので、作ったファイルを残したい場合はセッションストレージを使います。

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-session-endpoints.html#runtime-session-endpoints-lifecycle

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-lifecycle-settings.html

ちなみにセッションストレージは以前の記事で試しているので必要に応じて参照ください!

https://dev.classmethod.jp/articles/bedrock-agentcore-runtime-session-storage/

デフォルトのポートとパス

protocolConfigurationを指定しない場合はプロトコルごとに次の値が使われます。
ポートだけやパスだけを変えることもできます。

HTTP以外の場合でもこの機能は対応しています!

プロトコル ポート パス
HTTP 8080 /invocations
AG-UI 8080 /invocations
MCP 8000 /mcp
A2A 9000 /

パスの変更が反映されるのはInvokeAgentRuntimeだけで、WebSocketでの呼び出しは待ち受けポートの /ws となります。

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-configure-invocation.html

アプリ側で気をつけること

セッションURLから届くリクエストのHostヘッダーには内部のホスト名が入ります。Viteなどホスト名をチェックする開発サーバーではserver.allowedHostsをtrueにするといった設定が必要です。ページ内のリンクやリダイレクトも相対URLにする必要があります。

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-session-endpoints.html#runtime-session-endpoints-how-it-works

使えない構成

Session endpointsはInstances(キャパシティプロバイダー)では使えません。またアクセスはパブリックなHTTPS経由でPrivateLinkには対応していません。

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-session-endpoints.html

エラーの見分け方

Runtime側のエラーは本文が空で X-Amzn-Bedrock-AgentCore-Runtime-Error ヘッダーに理由が入ります。今回見た502と403のほかには次のようなものがあります。

ステータス 理由 主な原因
401 AuthenticationRequired 認証情報が付いていない
404 SessionNotFound URLが違うかセッションがない
424 RuntimeClientError アプリが時間内に起動・応答しない
429 Throttled リクエストが多すぎる

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-session-endpoints.html#runtime-session-endpoints-errors

CloudTrailへの記録

セッションURLへのリクエストは InvokeAgentRuntimeProxy というデータイベントとしてCloudTrailに記録できます。データイベントはデフォルトでは記録されないので証跡かイベントデータストアで設定します。Webプレビューは画像やスクリプトごとにリクエストが出るので記録する場合は料金に気をつけましょう。

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-session-endpoints.html#runtime-session-endpoints-cloudtrail

料金

料金ページにはSession endpoints固有の項目が見当たりませんでした(2026年11月1日時点)。おそらく通常のAgentCore Runtimeの料金がかかる形だと思います。microVMでは実行環境の準備から終了までのCPUとメモリの使用量に応じて秒単位で課金されます。プレビューが終わったらセッションを止めるか後片付けまで済ませておきましょう。

https://aws.amazon.com/bedrock/agentcore/pricing/

この記事をシェアする

関連記事