Amazon Bedrock AgentCore のランタイムを使うと、開発した AI エージェントを簡単にクラウド環境へデプロイできます。
デフォルトでは AWS が管理するネットワーク内で動作するのですが、閉域ネットワークの VPC で動作できるようにするにはどうすればいいか検証してみました。
前提条件
今回の検証で使う Agent のフレームワークは Strands Agents SDK とします。
AgentCore CLI でプロジェクトを作成し、networkMode を「VPC」に設定してデプロイします。
デプロイする VPC
networkMode に VPC を指定するためには、事前に VPC、サブネット、セキュリティグループが必要です。今回の検証は東京リージョンで行うのですが、AgentCore ランタイムが VPC で動作する AZ はリージョンごとに決められており、東京リージョンでは以下の AZ にサブネットを作成する必要があります。
- apne1-az1
- apne1-az2
- apne1-az4
検証に使う VPC、サブネット、セキュリティグループの ID は、後で AgentCore CLI のパラメーターに指定するのでメモしておきましょう。
AgentCore ランタイムのデプロイ方法
AgentCore ランタイムのデプロイ方法は、S3 バケットを使う「直接コードデプロイ」と、ECR リポジトリを使う「コンテナイメージ利用」から選べます。
今回検証した結果、閉域ネットワークの VPC にランタイムをデプロイする場合、直接コードデプロイを選ぶことが望ましいと分かりました。
理由は、networkMode を VPC にしてプロジェクトを作成した場合、コンテナイメージ利用方式ではコンテナイメージのビルドが VPC 内の CodeBuild で行われるためです。
プロジェクトを作成する時に生成された Dockerfile は public.ecr.aws からベースイメージを pull するように書かれており、また、PyPI のパッケージへの依存もありました。
閉域の VPC ではこれらのリソースに到達できないため、コンテナイメージ利用方式ではイメージのビルドで失敗します。
それでは具体的な検証手順を見ていきます。
VPC エンドポイントの作成
AWS のドキュメントによると、AgentCore ランタイムを VPC で動かすのに最低限必要な VPC エンドポイントは以下のとおりです。
- Amazon ECR Requirements :
- Docker endpoint: com.amazonaws.region.ecr.dkr
- ECR API endpoint: com.amazonaws.region.ecr.api
- Amazon S3 Requirements :
- Gateway endpoint for ECR docker layer storage: com.amazonaws.region.s3
- CloudWatch Requirements :
- Logs endpoint: com.amazonaws.region.logs
上記に加え、作成する AI エージェントで使う VPC エンドポイントの作成が必要です。今回は以下のように VPC エンドポイントを作成しました。
| サービス | 種別 | 用途 |
|---|---|---|
| ecr.dkr | Interface | コンテナイメージの取得(直接コードデプロイのみの場合は不要な可能性が高い) |
| ecr.api | Interface | コンテナイメージの取得(直接コードデプロイのみの場合は不要な可能性が高い) |
| s3 | Gateway | ランタイムのコード取得 |
| logs | Interface | CloudWatch Logs |
| bedrock-runtime | Interface | モデル推論 |
| bedrock-agentcore | Interface | VPC 内から InvokeAgentRuntime を呼ぶ場合のみ |
AgentCore ランタイムで AI エージェントを作成
今回の検証用に、Claude Code を使って、DynamoDB に登録したドキュメントをソースに質疑応答に(Q&A)対応する簡単なエージェントを QaAgent という名前で開発しました。
AgentCore プロジェクトのひな形を出力
AgentCore CLI で以下のとおり networkMode を VPC に設定したプロジェクトのひな形を作成します。
--build には CodeZip を、--network-mode には VPC を指定します。
$ agentcore create --project-name QaAgent --name QaAgent \
--framework Strands \
--model-provider Bedrock \
--build CodeZip \
--memory none \
--network-mode VPC \
--subnets <サブネット ID> \
--security-groups <セキュリティグループ ID>
AI エージェントが呼び出すツールを実装
app/QaAgent ディレクトリに tools ディレクトリを作成し、documents.py を新規作成します。
import os
import boto3
from boto3.dynamodb.conditions import Attr
from strands import tool
TABLE_NAME = os.environ.get("DOCS_TABLE_NAME", "qa-documents")
_table = None
def _get_table():
global _table
if _table is None:
_table = boto3.resource("dynamodb").Table(TABLE_NAME)
return _table
@tool
def search_documents(keyword: str) -> str:
"""社内ドキュメントをキーワードで検索し、該当する文書の一覧を返す。
Args:
keyword: 検索キーワード。タイトル・本文・カテゴリを対象に部分一致で探す。
"""
resp = _get_table().scan(
FilterExpression=Attr("title").contains(keyword)
| Attr("content").contains(keyword)
| Attr("category").contains(keyword)
)
items = resp.get("Items", [])
if not items:
return f"キーワード「{keyword}」に該当するドキュメントはありませんでした。"
lines = [f"{len(items)} 件見つかりました:"]
for item in items:
lines.append(
f"- docId={item['docId']} / {item.get('title', '(no title)')} "
f"[{item.get('category', '未分類')}]"
)
return "\n".join(lines)
@tool
def get_document(doc_id: str) -> str:
"""指定した docId の社内ドキュメント本文を取得する。"""
item = _get_table().get_item(Key={"docId": doc_id}).get("Item")
if not item:
return f"docId={doc_id} のドキュメントは見つかりませんでした。"
return (
f"タイトル: {item.get('title', '(no title)')}\n"
f"カテゴリ: {item.get('category', '未分類')}\n"
f"---\n{item.get('content', '')}"
)
@tool
def list_documents() -> str:
"""社内ドキュメントの一覧(docId とタイトル)を全件返す。"""
items = _get_table().scan(ProjectionExpression="docId, title, category").get("Items", [])
if not items:
return "登録されているドキュメントはありません。"
lines = [f"全 {len(items)} 件:"]
for item in sorted(items, key=lambda x: x["docId"]):
lines.append(f"- docId={item['docId']} / {item.get('title', '(no title)')}")
return "\n".join(lines)
main.py の処理を変更
app/QaAgent/main.py の処理を一部変更します。
+ from tools.documents import get_document, list_documents, search_documents
DEFAULT_SYSTEM_PROMPT = """
+ あなたは社内ドキュメント検索アシスタントです。日本語で回答してください。
+
+ ## 進め方
+ 1. 質問に答えるため、まず search_documents でキーワード検索する。
+ どんな資料があるか分からない場合は list_documents で一覧を確認する。
+ 2. 該当しそうな docId が見つかったら get_document で本文を取得する。
+ 3. 取得した本文だけを根拠に回答する。
+
+ ## 厳守事項
+ - ドキュメントに書かれていないことは推測で答えず、「社内ドキュメントには記載がありません」と伝える。
+ - 回答の末尾に、根拠にしたドキュメントの docId とタイトルを必ず明記する。
"""
# Define a collection of tools used by the model
- tools = []
+ tools = [search_documents, get_document, list_documents]
DynamoDB の VPC エンドポイント作成とドキュメントの格納
閉域ネットワーク対応と直接関係しない工程のため、詳細は割愛しますが、AI エージェントから参照する DynamoDB のテーブルを qa-documents という名前で作成します。
aws dynamodb create-table --region ap-northeast-1 \
--table-name qa-documents \
--attribute-definitions AttributeName=docId,AttributeType=S \
--key-schema AttributeName=docId,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
category、content、title という項目を追加し、AI エージェントに答えさせたい適当な内容を登録しました。
また、閉域 VPC からアクセスできるように VPC エンドポイント(Gateway 型)も併せて作成します。
| サービス | 種別 | 用途 |
|---|---|---|
| dynamodb | Gateway | AI エージェントから参照(閉域ネットワーク対応には直接関係なし) |
AWS サービスの実行ロールの設定
上記の DynamoDB に AI エージェントがアクセスするためには、IAM ロールに実行権限を追加する必要があります。
CDK のコードに設定しますので、agentcore/cdk/lib/cdk-stack.ts を以下のとおり修正します。
this.application = new AgentCoreApplication(this, 'Application', appProps as any);
+ for (const env of this.application.environments.values()) {
+ env.runtime.role.addToPrincipalPolicy(
+ new iam.PolicyStatement({
+ actions: ['dynamodb:GetItem', 'dynamodb:Query', 'dynamodb:Scan'],
+ resources: [`arn:aws:dynamodb:${this.region}:${this.account}:table/${tableName}`],
+ })
+ );
+ }
AI エージェントのデプロイ
ローカルで動作することが確認できたら、実際に AWS の VPC へデプロイします。
agentcore validate
agentcore deploy -y
閉域ネットワークでの動作検証
AI エージェントをデプロイした VPC のサブネットに、検証用の EC2 インスタンスを立てて、EC2 インスタンスから AI エージェントにアクセスできるか確認します。
閉域ネットワークの EC2 インスタンスは EC2 Instance Connect のエンドポイント経由でリモート接続しました。
EC2 インスタンスには bedrock-agentcore:InvokeAgentRuntime の実行権限のある IAM ロールをアタッチしています。
--runtime-session-id は 33 文字以上の文字を設定する必要があります。また、プロンプトは blob 形式で与えなければならないので、プロンプトの JSON を一旦ファイルに出力し、fileb:// で指定しています。
$ printf '{"prompt":"閉域ネットワークについて教えて"}' > /tmp/payload.json
$ aws bedrock-agentcore invoke-agent-runtime \
--region ap-northeast-1 \
--agent-runtime-arn <AgentCore ランタイムの ARN> \
--runtime-session-id $(uuidgen) \
--payload fileb:///tmp/payload.json output.json
レスポンスの statusCode が 200 になっています。
レスポンスの中身を見てみます。少し見づらいですが、回答文が分割されているだけで、DynamoDB の内容をもとに AI エージェントが回答を作成していることが分かります。
これでインターネット接続できない閉域ネットワークの VPC でも AgentCore ランタイムをデプロイし、正常に動作することが確認できました。
コンテナイメージ利用方式でデプロイできないか検証
直接コードデプロイ方式だけではなく、コンテナイメージ利用方式でも AgentCore ランタイムをデプロイできないかを検証してみました。
結論としては、一部セキュリティ上の懸念がある手順であれば一応可能であることが分かりました。
コンテナイメージ利用方式で AgentCore プロジェクトのひな形を作成
コンテナイメージ利用方式で AgentCore プロジェクトのひな形を作成します。直接コードデプロイ方式との違いは、--build を Container に変更し、--vpc-id オプションを追加して VPC ID を指定することです。
$ agentcore create --project-name TestAgent --name TestAgent \
--framework Strands \
--model-provider Bedrock \
--build Container \
--memory none \
--network-mode VPC \
--subnets <サブネット ID> \
--security-groups <セキュリティグループ ID> \
--vpc-id <VPC ID>
public.ecr.aws からの ECR プルスルーキャッシュの作成
先述したとおり、コンテナイメージ利用方式で networkMode を VPC にした場合、コンテナイメージのビルドが VPC 内の CodeBuild で行われるため、ビルドにインターネット接続の必要なリソースがある場合は失敗してしまいます。
先ほど作成したひな形に出力される Dockerfile は public.ecr.aws からベースイメージを pull するようになっているので、そのままデプロイするとビルドで失敗します。
そこで、ECR プルスルーキャッシュを事前に設定し、public.ecr.aws のイメージをプライベートリポジトリ側にキャッシュしておくことで、閉域ネットワークからも VPC エンドポイント経由でベースイメージを pull できるようにします。
アップストリームレジストリを「ECR Public」に設定します。
キャッシュリポジトリプレフィックスは「ecr-public」とします。
「レジストリ URI」が「public.ecr.aws」になっていることを確認し、プルスルーキャッシュを作成します。
PyPI をミラーする CodeArtifact の作成
同様に、ひな形のイメージビルドでは boto3 や strands-agents などの Python ライブラリが必要なため、PyPI への接続が発生します。
CodeArtifact に PyPI をミラーするプライベートリポジトリを作成すれば、VPC エンドポイント経由で PyPI のライブラリを取得できるようになります。
プライベートリポジトリを作成するドメインを作成します。
「パブリックアップストリームレジストリ」を「pypi-store」に設定したプライベートリポジトリを作成します。
先ほど作成したドメインを設定します。
マネジメントコンソールのリポジトリの画面から「接続手順の表示」を開くと、リポジトリへの接続 URL が確認できるのでメモしておきます。
追加の VPC エンドポイントを作成
ECR への VPC エンドポイントは作成済みなので、CodeBuild と CodeArtifact への VPC エンドポイントを作成します。
| サービス | 種別 | 用途 |
|---|---|---|
| codebuild | Interface | イメージビルド |
| codeartifact.api | Interface | PyPI をミラーしたリポジトリへのアクセス |
| codeartifact.repositories | Interface | PyPI をミラーしたリポジトリへのアクセス |
Dockerfile の変更
public.ecr.aws と PyPI の閉域ネットワーク対応を反映するよう、AgentCore CLI で作成された Dockerfile を修正します。
CodeArtifact のリポジトリを使うには短期の資格情報が必要になるため、ENV には資格情報を残さないようにします。ただし、ビルド引数として渡した値はイメージビルドの履歴に残ってしまうため、セキュリティ上のリスクがあることに十分留意してください。
- FROM public.ecr.aws/docker/library/python:3.12-slim-trixie
+ ARG BASE_IMAGE=public.ecr.aws/docker/library/python:3.12-slim-trixie
+ FROM ${BASE_IMAGE}
- ARG UV_DEFAULT_INDEX
- ARG UV_INDEX
+ # CodeArtifact の認証情報を ENV に残さないようにする。
+ ARG PIP_INDEX_URL
+ ARG UV_INDEX_CODEARTIFACT_USERNAME
+ ARG UV_INDEX_CODEARTIFACT_PASSWORD
- RUN pip install --no-cache-dir uv
+ RUN PIP_INDEX_URL="${PIP_INDEX_URL}" pip install --no-cache-dir uv
ENV UV_SYSTEM_PYTHON=1 \
UV_COMPILE_BYTECODE=1 \
UV_NO_PROGRESS=1 \
PYTHONUNBUFFERED=1 \
DOCKER_CONTAINER=1 \
- UV_DEFAULT_INDEX=${UV_DEFAULT_INDEX} \
- UV_INDEX=${UV_INDEX} \
PATH="/app/.venv/bin:$PATH"
COPY pyproject.toml uv.lock ./
- RUN uv sync --frozen --no-dev --no-install-project
+ RUN UV_INDEX_CODEARTIFACT_USERNAME="${UV_INDEX_CODEARTIFACT_USERNAME}" \
+ UV_INDEX_CODEARTIFACT_PASSWORD="${UV_INDEX_CODEARTIFACT_PASSWORD}" \
+ uv sync --frozen --no-dev --no-install-project
COPY --chown=bedrock_agentcore:bedrock_agentcore . .
- RUN uv sync --frozen --no-dev
+ RUN UV_INDEX_CODEARTIFACT_USERNAME="${UV_INDEX_CODEARTIFACT_USERNAME}" \
+ UV_INDEX_CODEARTIFACT_PASSWORD="${UV_INDEX_CODEARTIFACT_PASSWORD}" \
+ uv sync --frozen --no-dev
また、Dockerfile に BASE_IMAGE で URL を渡すため、agentcore/agentcore.json に BASE_IMAGE を定義します。
+ "customDockerBuildArgs": {
+ "BASE_IMAGE": "<AWS アカウント ID>.dkr.ecr.ap-northeast-1.amazonaws.com/ecr-public/docker/library/python:3.12-slim-trixie"
+ }
uv.lock の参照先 URL を CodeArtifact のリポジトリへ変更
Dockerfile で RUN している uv sync --frozen は、uv.lock に書かれた URL からライブラリを取得しようとするため、そのままではやはりイメージビルドに失敗してしまいます。
uv lock を再実行する必要がありますが、uv.lock ファイルに CodeArtifact の短期の資格情報が書き込まれるのを防ぐため、資格情報を環境変数から渡すようにします。
app/TestAgent/pyproject.toml に以下のとおり追記します。url に指定する URL は CodeArtifact でリポジトリを作成した際に接続手順の表示で確認した URL です。
+ [[tool.uv.index]]
+ name = "codeartifact"
+ url = "https://test02-dev-codeartifact-domain-agentcore-<AWS アカウント ID>.d.codeartifact.ap-northeast-1.amazonaws.com/pypi/pypi-store/simple/"
+ default = true
以下のとおり資格情報を環境変数 UV_INDEX_CODEARTIFACT_USERNAME と UV_INDEX_CODEARTIFACT_PASSWORD に設定し、uv lock を再実行します。
$ cd app/TestAgent
$ export UV_INDEX_CODEARTIFACT_USERNAME=aws
$ export UV_INDEX_CODEARTIFACT_PASSWORD=$(aws codeartifact get-authorization-token \
--domain test02-dev-codeartifact-domain-agentcore --query authorizationToken --output text)
$ uv lock
CodeBuild での docker build に CodeArtifact の資格情報を渡す
uv lock は手元の環境で実行しているため、環境変数で CodeArtifact の短期の資格情報を渡すことができました。しかし、実際のデプロイ時は CodeBuild でイメージビルドが行われるため、環境変数に資格情報を設定しても CodeBuild 側へ渡せません。
そのため、今回の検証では agentcore/agentcore.json の customDockerBuildArgs に CodeArtifact の資格情報を設定するしか方法が見つかりませんでした。
しかし、そのまま agentcore/agentcore.json に CodeArtifact の資格情報を書いてしまうと、短期の資格情報とはいえセキュリティ上の懸念があります。
そこで、AgentCore ランタイムをデプロイするタイミングのみ、スクリプトで一時的に CodeArtifact の資格情報を agentcore/agentcore.json へ書き込むことにしました。(スクリプトは Claude Code が作ってくれました。)
この方法は完璧でなく、例えば途中でイメージビルドが失敗した場合や、スクリプトのプロセスを中止した場合などに、ファイルへ資格情報が書かれたままになるリスクがありますので、十分に注意が必要です。
#!/usr/bin/env python3
from __future__ import annotations
import json
import os
import signal
import subprocess
import sys
from pathlib import Path
from types import FrameType
import boto3
DOMAIN = "test02-dev-codeartifact-domain-agentcore"
REPO = "pypi-store"
CONFIG = Path("agentcore/agentcore.json")
DEFAULT_PROFILE = "<AgentCore ランタイムのデプロイを行う権限を持つプロファイル名>"
DEFAULT_REGION = "ap-northeast-1"
USERNAME_KEY = "UV_INDEX_CODEARTIFACT_USERNAME"
PASSWORD_KEY = "UV_INDEX_CODEARTIFACT_PASSWORD"
INDEX_URL_KEY = "PIP_INDEX_URL"
def log(message: str) -> None:
print(message, flush=True)
def fail(message: str) -> None:
print(f"error: {message}", file=sys.stderr, flush=True)
raise SystemExit(1)
def inject(original_text: str, index_url: str, token: str) -> str:
"""Return the config text with credentials added to every runtime."""
config = json.loads(original_text)
runtimes = config.get("runtimes", [])
if not runtimes:
fail(f"{CONFIG} declares no runtimes")
for runtime in runtimes:
runtime.setdefault("customDockerBuildArgs", {}).update(
{
INDEX_URL_KEY: index_url,
USERNAME_KEY: "aws",
PASSWORD_KEY: token,
}
)
return json.dumps(config, indent=2, ensure_ascii=False) + "\n"
def fetch_credentials(session: boto3.Session) -> tuple[str, str]:
"""Return (index_url, token) for the CodeArtifact pypi repository."""
client = session.client("codeartifact")
token = client.get_authorization_token(domain=DOMAIN)["authorizationToken"]
endpoint = client.get_repository_endpoint(
domain=DOMAIN, repository=REPO, format="pypi"
)["repositoryEndpoint"]
host_path = endpoint.removeprefix("https://")
log(f" index host: {host_path}")
return f"https://aws:{token}@{host_path}simple/", token
def install_signal_handlers() -> None:
"""Turn SIGTERM/SIGHUP into SystemExit so the finally block still runs.
SIGINT は KeyboardInterruptを発生させ、正常にスタックの巻き戻し(unwind)が行われます。
一方、SIGKILL は捕捉できません。SIGKILL でプロセスが終了させられた場合は、
このスクリプトを再実行するか、設定ファイルに対して `git checkout` を行うことで
トークンを削除してください。
"""
def handler(signum: int, _frame: FrameType | None) -> None:
raise SystemExit(128 + signum)
for sig in (signal.SIGTERM, signal.SIGHUP):
signal.signal(sig, handler)
def main() -> int:
install_signal_handlers()
profile = os.environ.get("AWS_PROFILE") or DEFAULT_PROFILE
region = os.environ.get("AWS_REGION") or DEFAULT_REGION
os.environ["AWS_PROFILE"] = profile
os.environ["AWS_REGION"] = region
os.chdir(Path(__file__).resolve().parent.parent)
if not CONFIG.is_file():
fail(f"{CONFIG} not found (run from a checkout of this repository)")
session = boto3.Session(profile_name=profile, region_name=region)
original_text = CONFIG.read_text(encoding="utf-8")
log("== fetching CodeArtifact token ==")
index_url, token = fetch_credentials(session)
try:
CONFIG.write_text(inject(original_text, index_url, token), encoding="utf-8")
log("== injected token, deploying ==")
result = subprocess.run(["agentcore", "deploy", "-y"])
except FileNotFoundError:
fail("`agentcore` not found on PATH")
finally:
CONFIG.write_text(original_text, encoding="utf-8")
log(f"== stripped CodeArtifact token from {CONFIG} ==")
return result.returncode
if __name__ == "__main__":
raise SystemExit(main())
CodeBuild 実行ロールにプルスルーキャッシュからの pull に必要な権限を追加
CodeBuild でイメージビルド時に pull するベースイメージを public.ecr.aws からのプルスルーキャッシュに変更しているため、AgentCore CLI で作成したひな形の CDK に定義されている IAM ロールの権限だけではプルスルーキャッシュ経由の pull ができません。
そこで、agentcore/cdk/lib/cdk-stack.ts に以下のとおり IAM ロールの権限を追記します。
- import { AgentCoreApplication } from '@aws/agentcore-cdk';
+ import { AgentCoreApplication, ContainerBuildProject } from '@aws/agentcore-cdk';
this.application = new AgentCoreApplication(this, 'Application', appProps as any);
for (const env of this.application.environments.values()) {
+ const agent = env.agent as {
+ build?: string;
+ networkMode?: string;
+ networkConfig?: { vpcId?: string; subnets: string[]; securityGroups: string[] };
+ };
+ if (agent.build !== 'Container' || agent.networkMode !== 'VPC' || !agent.networkConfig?.vpcId) {
+ continue;
+ }
+ const buildProject = ContainerBuildProject.getOrCreate(this, {
+ vpcId: agent.networkConfig.vpcId,
+ subnets: agent.networkConfig.subnets,
+ securityGroups: agent.networkConfig.securityGroups,
+ });
+ buildProject.role.addToPrincipalPolicy(
+ new iam.PolicyStatement({
+ actions: [
+ 'ecr:CreateRepository',
+ 'ecr:BatchImportUpstreamImage',
+ 'ecr:BatchGetImage',
+ 'ecr:GetDownloadUrlForLayer',
+ 'ecr:DescribeImages',
+ ],
+ resources: [`arn:aws:ecr:${this.region}:${this.account}:repository/ecr-public/*`],
+ })
+ );
コンテナイメージ利用方式でのデプロイ
Python スクリプトから AgentCore ランタイムのデプロイを実行します。
$ ./scripts/deploy_closed_container.py
デプロイに成功したら、直接コードデプロイ方式の時と同様に、閉域 VPC 内の EC2 インスタンスから実行し、正常に応答が返れば成功です。
まとめ
AgentCore ランタイムはインターネット接続できない閉域ネットワークの VPC にデプロイし、閉域ネットワーク内に完結する形で動作させることができました。
デプロイ方式は、直接コードデプロイ方式であれば特に問題ありません。
コンテナイメージ利用方式でも、イメージビルドにインターネット接続が必要になる依存(ベースイメージと PyPI)を ECR プルスルーキャッシュと CodeArtifact へ置き換えれば、デプロイ自体は可能でした。ただし、CodeArtifact の資格情報がイメージビルド履歴に残るというセキュリティ上の懸念があります。
閉域ネットワークでデプロイする場合は直接コードデプロイ方式が楽ですが、ファイルサイズ等の制限からコンテナイメージ利用方式を選ばなければならない場合もあるかと思います。
例えば「Amazon Bedrock AgentCore 実践入門」(SB クリエイティブ、2026)291 ページには、以下の記載がありました。
デプロイ方法は「コンテナ」と「直接コードデプロイ」の 2 種類が選べますが、ここでは「コンテナ」を選択しています。本ハンズオンで使用する Strands Agents のブラウザツール(AgentCoreBrowser クラス)は、内部的に Playwright ライブラリを使用しており、Playwright に含まれる Node.js ドライバーには実行権限が必要です。ところが、「直接コードデプロイ」ではコードが ZIP 圧縮されてデプロイされるため、展開時に実行権限が失われてしまいます。コンテナデプロイであれば Docker イメージのビルド時に正しい権限のままインストールされるため、この問題を回避できます。
閉域ネットワークでは他にも AI エージェントからインターネット上のツールを使えないなどの課題がありますが、実現できる要件を見極めながら活用できるとよいと思います。











