[アップデート]AWS Agent Registryが一般提供開始されました!

[アップデート]AWS Agent Registryが一般提供開始されました!

AWS Agent RegistryがGA(一般提供)になりました!HTTPSエンドポイント登録やOrganizations自動検出など、プレビューから進化しています!AIエージェントを統制したいエンプラの希望になって欲しいですね。
2026.09.16

はじめに

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

2026年8月31日、エージェントやMCPサーバー、スキルをカタログとして管理できる「AWS Agent Registry」がGA(一般提供)になりました!

https://aws.amazon.com/blogs/machine-learning/manage-agents-tools-and-skills-at-scale-with-aws-agent-registry/

4月のプレビュー記事では「HTTPSエンドポイントなど他のプロトコルでも登録できると嬉しい」と書いていたのですが、GAでまさにHTTPSエンドポイントのエージェントを登録できるようになりました!これまではA2AのAgent Cardを用意する必要があったので、待望のアップデートです。さらにOrganizations配下のAgentCore RuntimeやGatewayを自動検出する機能も加わり、アカウントごとのエージェント棚卸しの手間も解消されそうな予感ですね。本格的にRegistryらしい機能が備わってきました!

https://dev.classmethod.jp/articles/aws-agent-registry-preview/

プレビューから何が変わった?

プレビュー版からの差分を、公式ドキュメントやAPIの変更履歴をもとに整理してみました。

項目 プレビュー GA時点
エージェントの記述形式 A2AのAgent Card HTTP/AG-UI形式を追加
リソースの登録 登録対象の情報やURLを指定 Organizations配下のRuntime/Gatewayを自動検出する方法を追加
Gatewayの分類 専用のレコード種別なし 自動検出用のGATEWAYを追加
検出元の情報 なし provenanceで元リソースのARN・種別を保持
利用者向けの取得API 検索のみ 承認済みレコードの一覧・詳細の一括取得を追加
RegistryのMCPツール 検索の1ツール 検索・一覧・一括取得の3ツール
暗号化 AWS所有キー カスタマーマネージドKMSキーを選択可能
SDK・IAMの名前空間 bedrock-agentcore Registry専用のagent-registry

おお、結構変わりましたね!Org機能の追加やプレビュー時と名前空間が違うのはかなりびっくりしました。なお、承認フローやMCP経由での検索機能などは、プレビュー版の使い勝手を引き継いでいます。

今回は自動検出やHTTPSの登録を試してみたいと思います!

RuntimeとGatewayを自動で登録する

早速1つめとして、Organizations配下のAgentCore RuntimeやGatewayの自動検出を試してみます!

有効化時点の既存リソースだけでなく、後から作成されたリソースも自動で登録されます。接続先が変わればレコードに反映され、元リソースを削除すればレコードも一緒に消えるので、リソースの変化にしっかり追従してくれます。

今回は管理アカウントにRegistryを作成し、自動検出を有効にしました。
AWSは最小権限の観点で委任管理者の利用を推奨していますが、管理アカウント自身で組織スコープのRegistryを作成可能で、必須ではありません。

管理アカウントにRegistryを作成し、メンバーアカウントのRuntimeとGatewayを自動検出する今回の構成

検出されたレコードにはprovenance(由来)が付与されるので、元のリソースARNからどのアカウントの何のリソースかを追跡できます。

RuntimeはAGENT、GatewayはGATEWAYとして登録されます。
自動承認を無効にしておけば、公開前に管理者のレビューを挟んでガバナンスを効かせる運用も可能です。

メンバーアカウントのRuntimeとGatewayを自動検出し、管理アカウントのRegistryへ集約して承認する構成

自動検出のスコープは現時点で ORGANIZATION のみとなっており、Organizationsと連携せず自アカウント単体でRegistryを運用する場合は、Runtimeも手動で登録が必要です。

とはいえ1アカウントで完結しているなら、AgentCore RuntimeやGatewayの一覧画面を見れば何があるかは把握できますし、数が少ないうちは手で登録していけばなんとかなりそうです。これが10を超えるアカウントに散らばってくると、組織全体で何が動いているかを追うのはさすがに厳しいので、そこが自動検出の出番でしょうかね。

この機能を使うには、信頼されたアクセスとサービスリンクロールの準備が必要です。自動検出の対象は同一リージョン内に限られ、組織・リージョンごとに有効化できるレジストリは1つとなっているので留意しておきましょう。

このあたりの制約は、レジストリの作成画面にもそのまま書かれています。管理アカウントでも委任管理者でもないアカウントで開くと、前提条件を満たしていない旨の警告が出ました。

自動検出のレジストリは1つだけ、管理アカウントか委任管理者が前提

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/registry-organizations.html

まずは設定からやってみましょうか!

コンソールでOrganizations連携を設定する

自動検出はコンソールから設定できます。
まず、管理アカウントでAWS Agent Registryを開き、左メニューの「Settings」から「AWS Organizations の設定」の「編集」へ進みます。

左メニューのSettingsからAWS Organizationsの設定の編集へ進む

「信頼できるアクセスを有効にする」をオンにし、委任管理者の欄は空のまま保存しました。画面の案内では委任管理を「日常的な運用に管理アカウントを使用する代わりに、メンバーアカウントにレジストリ設定の所有権を委任します」と説明していて、欄も「推奨」となっていますが、今回はシンプルに2アカウントで進めます。

Organizations統合の設定画面。委任管理者は推奨だが未指定のまま保存できる

有効にすると下記のように表示されました!

管理アカウントで信頼されたアクセスを有効にし、委任管理者は指定しない

同じ管理アカウントで、Registryの作成画面で「自動検出」を有効にします。

管理アカウントで組織を対象とする自動検出を有効にする

今回は公開前にレビューを挟みたいので、自動承認は無効にしています。

既存リソースの初回検出には最大20分かかると公式ドキュメントにあったのでしばらく待ってみたところ、一覧に24件のレコードが表示されました!

狙いどおり、メンバーアカウントのRuntimeとGatewayがしっかりドラフト状態で表示されていますね。

組織内のRuntimeとGatewayが24件自動検出され、ドラフトとして登録された

試しにGatewayの1レコードを開くと、「Provenance」に検出元GatewayのARNやリソース種別が入っていて、プロトコルがMCP、認証方式がAWS IAMであることも確認できました!

Provenanceから検出元GatewayのARNとリソース種別を確認する

検出されたドラフトの承認も、この画面から進められます。レコードを選んで「更新ステータス」から「承認用に送信」を選びます。

ドラフトのレコードを選び、更新ステータスから承認用に送信する

承認待ちになったレコードは、同じメニューから「承認」「拒否」「非推奨」を選べます。

承認待ちのレコードは承認・拒否・非推奨から選べる

承認するときは理由も記録できました。承認履歴のコメントとして使えそうです。

承認時に理由を記録できる

こんな感じで承認プロセスを進めていくことができます!厳密には管理者と利用者で権限分離したり、通知を飛ばしたりなど別途作り込み入ると思います。

CLIでも同じ設定を行えます。管理アカウントで設定する手順を以下にまとめます。

CLIでの自動検出の設定・確認・後片付け

以下は公式ドキュメントに沿った手順です。

管理アカウントのAWS CLIプロファイル名を org-management とした例を示します。対象リージョンに既存の自動検出用Registryがないことを確認しておきます。

管理アカウントで信頼されたアクセスを有効にし、サービスリンクロールを作成します。すでに設定済みの操作は省いてください。

管理アカウントでの設定
aws organizations enable-aws-service-access \
  --service-principal agent-registry.amazonaws.com \
  --profile org-management

aws iam create-service-linked-role \
  --aws-service-name agent-registry.amazonaws.com \
  --profile org-management

同じ管理アカウントで、組織を対象とする自動検出を有効にしてRegistryを作成します。

管理アカウントでの作成
aws agent-registry-control create-registry \
  --name registry-ga-autodetection \
  --discovery-configuration '{"authorizerType":"AWS_IAM"}' \
  --approval-configuration '{"autoApprovalRules":[]}' \
  --auto-detection-configuration '{"scope":"ORGANIZATION","enabled":true}' \
  --region us-east-1 \
  --profile org-management

作成結果のRegistry ARNを環境変数に入れて状態を確認します。

自動検出の状態とレコードの確認
export REGISTRY_ARN='<作成結果のregistryArn>'

aws agent-registry-control get-registry \
  --registry-id "$REGISTRY_ARN" \
  --query '{registryStatus:status,autoDetection:autoDetection}' \
  --region us-east-1 --profile org-management

aws agent-registry-control list-registry-records \
  --registry-id "$REGISTRY_ARN" \
  --region us-east-1 --profile org-management

Registry本体の状態が READY、自動検出の状態が ACTIVE になっているかを確認します。有効化の設定が true でも、自動検出が実際に稼働しているとは限らないためです。

メンバーアカウントの同じリージョンにRuntimeやGatewayがあれば、そのリソースがレコード一覧に登録される想定です。レコードの詳細取得API(get-registry-record)では、自動検出で作られたことを示す createdByAutoDetection と、元のARNを保持する provenance を確認します。

検出元の確認
aws agent-registry-control get-registry-record \
  --registry-id "$REGISTRY_ARN" \
  --record-id '<一覧に表示されたレコードID>' \
  --query '{recordType:recordType,status:status,autoDetected:createdByAutoDetection,provenance:provenance}' \
  --region us-east-1 --profile org-management

検証用Registryを削除する際は、先に自動検出を無効にします。

自動検出を停止する
aws agent-registry-control update-registry \
  --registry-id "$REGISTRY_ARN" \
  --auto-detection-configuration '{"optionalValue":{"scope":"ORGANIZATION","enabled":false}}' \
  --region us-east-1 --profile org-management

get-registry でRegistryが READY に戻り、自動検出が INACTIVE になったことを確認したら、一覧の各レコードを削除します。レコードが0件になってからRegistry本体を削除してください。

レコードとRegistryの削除
# 一覧にあるレコードごとに実行
aws agent-registry-control delete-registry-record \
  --registry-id "$REGISTRY_ARN" \
  --record-id '<削除するレコードID>' \
  --region us-east-1 --profile org-management

aws agent-registry-control delete-registry \
  --registry-id "$REGISTRY_ARN" \
  --region us-east-1 --profile org-management

検証で新しく有効にした信頼されたアクセスも、利用を終える場合は管理アカウントで解除します。既存の組織設定を利用した場合は、その設定を維持してください。

今回追加したOrganizations設定の解除
aws organizations disable-aws-service-access \
  --service-principal agent-registry.amazonaws.com \
  --profile org-management

アカウントが増えるほどありがたい機能ですね!

続いて、GAで追加されたHTTPSエンドポイントの登録も試してみます。

HTTPSエンドポイントを登録してみる

AgentCore RuntimeへデプロイしたエージェントをHTTP形式でレジストリに手動登録して、承認後にレジストリから接続先URLを取得し、計算を依頼するところまで試します。

Organizationsの自動検出とは別の、自アカウント内での検証となります!

項目
検証日・リージョン 2026年9月15日・16日・us-east-1
実行環境 Python 3.14.6、uv 0.9.26、Node.js 26.7.0
SDK(ローカル) boto3 / botocore 1.43.89
Runtime AgentCore CLI 0.27.1(@aws/agentcore)で作成、Python 3.14
モデル global.anthropic.claude-sonnet-4-5-20250929-v1:0
Registryの設定 IAM認証・手動承認

今回作るエージェントは、AgentCore CLIでサクッと作ってレジストリに登録する形とします。

RuntimeのURLをRegistryに登録し、承認後に取得したURLへクライアントからリクエストを送る構成

まずはuvで作業ディレクトリと環境を用意します。

環境のセットアップ
mkdir registry-ga-lab
cd registry-ga-lab
uv init --bare --python 3.14
uv add boto3==1.43.89 botocore==1.43.89
mkdir scripts

計算エージェントを作る

エージェント本体はAgentCore CLIに任せます。npmでインストールします。

AgentCore CLIのインストール
npm install -g @aws/agentcore

プロジェクトを作成します。

対話形式のウィザードでも進められますが、今回は手早く済ませたいのでパラメーターを指定して実行します。
プロトコルはHTTP、フレームワークはStrands Agents、モデルプロバイダーはBedrockを選択しています。

プロジェクトの作成
agentcore create --project-name registrygalab --name CalculatorAgent \
  --framework Strands --model-provider Bedrock --protocol HTTP \
  --memory none --build CodeZip --language Python --defaults

作成が完了したらディレクトリを移動して、デプロイします。

デプロイ
cd registrygalab
agentcore deploy

内部でCDKが動いて、Runtime・実行ロール・ロググループがまとめて作られます。
完了するとRuntime ARNが表示されます!

実行結果(抜粋)
✓ Deployed to 'default' (stack: AgentCore-registrygalab-default)
Outputs:
  ApplicationAgentCalculatorAgentRuntimeArnOutput...: arn:aws:bedrock-agentcore:us-east-1:<アカウントID>:runtime/registrygalab_CalculatorAgent-XXXXXXXXXX
  ApplicationAgentCalculatorAgentRoleArnOutput...: arn:aws:iam::<アカウントID>:role/AgentCore-registrygalab-d-ApplicationAgentCalculato-XXXXXXXXXXXX

そのままAgentCore CLIから呼び出して動作を確かめます。

動作確認
agentcore invoke '{"prompt": "What is 2 + 3?"}'
実行結果
The answer is **5**.

問題なく動いていますね!

表示されたRuntime ARNを環境変数に入れて、Registryへの登録に進みます。

Runtime ARNの設定
export AGENT_RUNTIME_ARN='<表示されたRuntime ARN>'

Registryの検証コードを用意する

次のコードを scripts/registry_lab.py として保存してください。
これ1本で一連の操作をまかないます。作成したレジストリやレコードのIDは .local/registry-state.json に保存し、後片付けにも使います。

scripts/registry_lab.py(完全版)
scripts/registry_lab.py
"""Disposable AWS Agent Registry GA lab; run with uv run scripts/registry_lab.py."""
import argparse
import json
import os
from pathlib import Path
import time
import uuid
import urllib.request
from urllib.parse import quote

import boto3
from botocore.exceptions import ClientError
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest

ROOT = Path(__file__).resolve().parents[1]
STATE_PATH = ROOT / '.local/registry-state.json'
EVENTS_PATH = ROOT / '.local/registry-events.jsonl'
SESSION = boto3.Session(region_name='us-east-1')
CONTROL = SESSION.client('agent-registry-control')
DISCOVERY = SESSION.client('agent-registry')
STATE = json.loads(STATE_PATH.read_text()) if STATE_PATH.exists() else {}

def save():
    STATE_PATH.parent.mkdir(mode=0o700, exist_ok=True)
    fd = os.open(STATE_PATH, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
    with os.fdopen(fd, 'w') as stream:
        json.dump(STATE, stream, indent=2, default=str)

def event(name, **values):
    row = {'event': name, **values}
    line = json.dumps(row, ensure_ascii=False, default=str)
    print(line, flush=True)
    with EVENTS_PATH.open('a') as stream:
        stream.write(line + '\n')

def wait_record(record_id, desired='DRAFT'):
    for _ in range(150):
        result = CONTROL.get_registry_record(registryId=STATE['registryId'], recordId=record_id)
        if result['status'] == desired:
            return result
        if result['status'].endswith('FAILED'):
            raise RuntimeError(result.get('statusReason', result['status']))
        time.sleep(4)
    raise TimeoutError(f'Record did not reach {desired}')

def create_registry():
    if 'registryId' not in STATE:
        result = CONTROL.create_registry(
            name='registry-ga-blog-' + uuid.uuid4().hex[:8],
            description='Disposable Agent Registry GA verification',
            discoveryConfiguration={'authorizerType': 'AWS_IAM'},
            approvalConfiguration={'autoApprovalRules': []},
            tags={'Project': 'registry-ga-blog'},
        )
        STATE.update(registryId=result['registryArn'], records={})
        save()
        event('registry_created', http_status=result['ResponseMetadata']['HTTPStatusCode'])
    for attempt in range(150):
        result = CONTROL.get_registry(registryId=STATE['registryId'])
        if result['status'] == 'READY':
            event('registry_ready', status=result['status'], autoDetection=result.get('autoDetection'))
            return
        if result['status'].endswith('FAILED'):
            raise RuntimeError(result.get('statusReason', result['status']))
        if attempt % 8 == 0:
            event('registry_wait', status=result['status'])
        time.sleep(4)
    raise TimeoutError('Registry not ready')

def runtime_url():
    arn = os.environ['AGENT_RUNTIME_ARN']
    region = arn.split(':')[3]
    return f'https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{quote(arn, safe="")}/invocations?qualifier=DEFAULT'

def create_records():
    for kind in ('http',):
        if kind in STATE['records']:
            continue
        result = CONTROL.create_registry_record(
            registryId=STATE['registryId'], name='calculation-' + kind + '-agent',
            displayName='Calculation ' + kind.upper() + ' Agent',
            description='Adds two numbers using the add_numbers tool. Hosted on AgentCore Runtime. '
                        'POST JSON with a prompt string; returns a text/event-stream response. '
                        'Authentication: AWS IAM (SigV4). Owner: demo team.',
            recordType='AGENT', recordVersion='1.0.0',
            descriptors={kind: {'source': {'fromUrl': {'url': runtime_url()}}}},
            tags={'Project': 'registry-ga-blog'},
        )
        record_id = result['recordArn'].rsplit('/', 1)[-1]
        STATE['records'][kind] = record_id
        save()
        event('record_created', kind=kind, status=result['status'])
        record = wait_record(record_id)
        event('record_ready', kind=kind, status=record['status'], recordType=record['recordType'],
              descriptors=record['descriptors'], createdByAutoDetection=record.get('createdByAutoDetection'))

def custom():
    definition = {
        'endpoint': runtime_url(),
        'authentication': {'type': 'AWS_IAM', 'signingService': 'bedrock-agentcore'},
        'request': {'method': 'POST', 'contentType': 'application/json',
                    'example': {'prompt': 'Use add_numbers to calculate 2 + 3.'}},
        'response': {'contentType': 'text/event-stream'},
        'owner': 'demo team',
    }
    result = CONTROL.create_registry_record(
        registryId=STATE['registryId'], name='calculation-custom-agent',
        displayName='Calculation Custom Agent',
        description='Adds two numbers. Connection instructions for application developers.',
        recordType='AGENT', recordVersion='1.0.0',
        descriptors={'custom': {'data': json.dumps(definition)}},
    )
    rid = result['recordArn'].rsplit('/', 1)[-1]
    STATE['records']['custom'] = rid
    save()
    wait_record(rid)
    CONTROL.submit_registry_record_for_approval(registryId=STATE['registryId'], recordId=rid)
    wait_record(rid, 'PENDING_APPROVAL')
    CONTROL.update_registry_record_status(registryId=STATE['registryId'], recordId=rid,
        status='APPROVED', statusReason='Reviewed the example connection instructions.')
    wait_record(rid, 'APPROVED')
    event('custom_approved', recordType='AGENT', descriptor='custom')

def snapshot(label):
    registry_id = STATE['registryId']
    managed = CONTROL.list_registry_records(registryId=registry_id)['registryRecords']
    discovered = DISCOVERY.list_discoverable_registry_records(registryId=registry_id)['registryRecords']
    def summary(records):
        return [{key: record.get(key) for key in ('name', 'status', 'recordType', 'description')} for record in records]
    event('snapshot', label=label, managed=summary(managed), discovered=summary(discovered))

def approve():
    record_id = STATE['records']['http']
    current = CONTROL.get_registry_record(registryId=STATE['registryId'], recordId=record_id)
    if current['status'] == 'DRAFT':
        result = CONTROL.submit_registry_record_for_approval(registryId=STATE['registryId'], recordId=record_id)
        event('submitted', status=result['status'])
        wait_record(record_id, 'PENDING_APPROVAL')
    if current['status'] != 'APPROVED':
        result = CONTROL.update_registry_record_status(
            registryId=STATE['registryId'], recordId=record_id,
            status='APPROVED', statusReason='Reviewed the disposable example metadata.',
        )
        event('approved', status=result['status'])
        wait_record(record_id, 'APPROVED')

def revise():
    CONTROL.update_registry_record(
        registryId=STATE['registryId'], recordId=STATE['records']['http'],
        description={'optionalValue': 'Revised draft: add_numbers accepts two integers.'},
    )
    result = wait_record(STATE['records']['http'])
    event('revised', status=result['status'], description=result['description'])

def batch():
    result = DISCOVERY.batch_get_discoverable_registry_record(entries=[{
        'registryId': STATE['registryId'], 'recordIds': list(STATE['records'].values()),
    }])
    event('batch_get', http_status=result['ResponseMetadata']['HTTPStatusCode'],
          records=[{'name': r['name'], 'descriptors': r['descriptors']} for r in result['registryRecords']],
          errors=[{'kind': next(k for k, v in STATE['records'].items() if v == e['recordId'].rsplit('/', 1)[-1]),
                   'errorCode': e['errorCode']} for e in result['errors']])

def mcp():
    registry_id = STATE['registryId'].rsplit('/', 1)[-1]
    url = f'https://agent-registry.us-east-1.api.aws/registry/{registry_id}/mcp'
    headers = {'Content-Type': 'application/json', 'Accept': 'application/json, text/event-stream'}
    def request(method, params, number):
        body = {'jsonrpc': '2.0', 'method': method, 'params': params}
        if number is not None:
            body['id'] = number
        payload = json.dumps(body)
        signed = AWSRequest(method='POST', url=url, data=payload, headers=headers)
        SigV4Auth(SESSION.get_credentials().get_frozen_credentials(), 'agent-registry', 'us-east-1').add_auth(signed)
        req = urllib.request.Request(url, data=payload.encode(), headers=dict(signed.headers.items()), method='POST')
        with urllib.request.urlopen(req, timeout=60) as response:
            if response.headers.get('Mcp-Session-Id'):
                headers['Mcp-Session-Id'] = response.headers['Mcp-Session-Id']
            raw = response.read().decode()
            if not raw:
                return None
            if raw.startswith('event:') or raw.startswith('data:'):
                raw = next(line[5:].strip() for line in raw.splitlines() if line.startswith('data:'))
            result = json.loads(raw)
            if 'error' in result:
                raise RuntimeError(result['error'])
            if number is None:
                return result
            return result['result']
    result = request('initialize', {'protocolVersion': '2025-11-25', 'capabilities': {},
                                   'clientInfo': {'name': 'registry-ga-blog', 'version': '1.0.0'}}, 1)
    headers['MCP-Protocol-Version'] = result['protocolVersion']
    event('mcp_initialized', protocolVersion=result['protocolVersion'])
    request('notifications/initialized', {}, None)
    result = request('tools/list', {}, 2)
    event('mcp_tools', tools=result['tools'])
    result = request('tools/call', {'name': 'list_discoverable_registry_records', 'arguments': {}}, 3)
    if result.get('isError'):
        raise RuntimeError(result)
    event('mcp_list_called', result=result)
    result = request('tools/call', {'name': 'search_discoverable_registry_records',
        'arguments': {'searchQuery': 'add two numbers calculation', 'maxResults': 5}}, 4)
    if result.get('isError'):
        raise RuntimeError(result)
    event('mcp_search_called', result=result)
    result = request('tools/call', {'name': 'batch_get_discoverable_registry_record',
        'arguments': {'recordIds': list(STATE['records'].values())}}, 5)
    if result.get('isError'):
        raise RuntimeError(result)
    event('mcp_batch_called', result=result)

def invoke():
    result = DISCOVERY.batch_get_discoverable_registry_record(entries=[{
        'registryId': STATE['registryId'], 'recordIds': [STATE['records']['http']],
    }])
    url = result['registryRecords'][0]['descriptors']['http']['source']['fromUrl']['url']
    assert url == runtime_url(), 'Unexpected invocation endpoint'
    payload = json.dumps({'prompt': 'Use only add_numbers to calculate 2 + 3. Reply with the result.'})
    headers = {'Content-Type': 'application/json', 'Accept': 'text/event-stream',
               'X-Amzn-Bedrock-AgentCore-Runtime-Session-Id': str(uuid.uuid4())}
    signed = AWSRequest(method='POST', url=url, data=payload, headers=headers)
    SigV4Auth(SESSION.get_credentials().get_frozen_credentials(), 'bedrock-agentcore', SESSION.region_name).add_auth(signed)
    req = urllib.request.Request(url, data=payload.encode(), headers=dict(signed.headers.items()), method='POST')
    with urllib.request.urlopen(req, timeout=180) as response:
        raw = response.read().decode()
        (ROOT / '.local/runtime-response.txt').write_text(raw)
        text = ''.join(json.loads(line[6:]).get('event', {}).get('contentBlockDelta', {})
                       .get('delta', {}).get('text', '')
                       for line in raw.splitlines() if line.startswith('data: '))
        event('runtime_invoked', http_status=response.status,
              content_type=response.headers.get('Content-Type'), response_text=text)

def cleanup():
    if 'registryId' not in STATE:
        return
    for kind, record_id in list(STATE['records'].items()):
        try:
            CONTROL.delete_registry_record(registryId=STATE['registryId'], recordId=record_id)
        except ClientError as exc:
            if exc.response['Error']['Code'] != 'ResourceNotFoundException':
                raise
        event('record_deleted', kind=kind)
        del STATE['records'][kind]
        save()
    CONTROL.delete_registry(registryId=STATE['registryId'])
    for _ in range(60):
        try:
            CONTROL.get_registry(registryId=STATE['registryId'])
        except ClientError as exc:
            if exc.response['Error']['Code'] == 'ResourceNotFoundException':
                event('registry_deleted')
                STATE.clear()
                save()
                return
            raise
        time.sleep(2)
    raise TimeoutError('Registry deletion not complete')

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('action', choices=['create', 'snapshot', 'approve', 'revise', 'batch', 'mcp', 'invoke', 'custom', 'cleanup'])
    parser.add_argument('--label', default='manual')
    args = parser.parse_args()
    if args.action == 'create':
        create_registry()
        create_records()
    elif args.action == 'snapshot':
        snapshot(args.label)
    else:
        globals()[args.action]()

初めてRegistryを作成するアカウントでは、サービスリンクロールの作成権限も必要なので注意です。(Adminなどの強い権限であれば気にならないとは思いますが・・・!)

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/registry-iam-permissions.html

作ったAIエージェントをレジストリに登録してみます!

HTTP形式にURLを指定する

レコードには、接続方法を書いたデータが記述子(descriptor、聴き慣れない日本語ですよね・・・)として入ります。中身は形式ごとに違い、A2AならAgent Card、MCPならサーバーの接続情報、今回のHTTP形式なら接続先のURLです。利用者はカタログでレコードを見つけたあと、この記述子を頼りに接続します。

今回はレコード種別を AGENT にし、記述子に http を指定します。登録部分は次のようになっています。

scripts/registry_lab.py(登録部分の抜粋)
from urllib.parse import quote

arn = os.environ['AGENT_RUNTIME_ARN']
region = arn.split(':')[3]
url = (
    f'https://bedrock-agentcore.{region}.amazonaws.com/'
    f'runtimes/{quote(arn, safe="")}/invocations?qualifier=DEFAULT'
)
result = CONTROL.create_registry_record(
    registryId=STATE['registryId'],
    name='calculation-http-agent',
    displayName='Calculation HTTP Agent',
    description='Adds two numbers using the add_numbers tool. Hosted on AgentCore Runtime. '
                'POST JSON with a prompt string; returns a text/event-stream response. '
                'Authentication: AWS IAM (SigV4). Owner: demo team.',
    recordType='AGENT',
    recordVersion='1.0.0',
    descriptors={'http': {'source': {'fromUrl': {'url': url}}}},
)

AgentCore Runtimeで発行されるURLを指定して登録する形となります!

レジストリとレコードの作成
uv run scripts/registry_lab.py create
実行結果
{"event": "registry_created", "http_status": 202}
{"event": "registry_wait", "status": "CREATING"}
{"event": "registry_wait", "status": "CREATING"}
{"event": "registry_ready", "status": "READY", "autoDetection": null}
{"event": "record_created", "kind": "http", "status": "CREATING"}
{"event": "record_ready", "kind": "http", "status": "DRAFT", "recordType": "AGENT", "createdByAutoDetection": null}

実行すると、レジストリが READY になり、レコード calculation-http-agentDRAFT で登録されます!

承認するまで利用者側には未承認のレコードは見えない

利用者向けのAPIにはagent-registryクライアントを使います。管理用のagent-registry-controlとはクライアントが分かれている点がポイントです。登録したレコードがいつ利用者から見えるようになるのか、承認の前後で1ステップずつ確かめていきます。

管理用の一覧と利用者向けの一覧を1回ずつ呼び出して記録します。

scripts/registry_lab.py(snapshotの抜粋)
managed = CONTROL.list_registry_records(registryId=registry_id)['registryRecords']
discovered = DISCOVERY.list_discoverable_registry_records(registryId=registry_id)['registryRecords']

まず、承認前の状態を取得してきます。

承認前の状態を記録
uv run scripts/registry_lab.py snapshot --label before-approval
実行結果(承認前)
snapshot --label before-approval
{
  "event": "snapshot",
  "label": "before-approval",
  "managed": [
    {
      "name": "calculation-http-agent",
      "status": "DRAFT",
      "recordType": "AGENT",
      "description": "Adds two numbers using the add_numbers tool. Hosted on AgentCore Runtime. POST JSON with a prompt string; returns a text/event-stream response. Authentication: AWS IAM (SigV4). Owner: demo team."
    }
  ],
  "discovered": []
}

管理用の一覧(managed)にはDRAFTで1件入っていますが、利用者向けの一覧(discovered)は空です。利用者向けの検索API(search_discoverable_registry_records)も同じで、承認前に実行したときは0件でした。一覧も検索も、ヒットするのは承認済みのレコードだけです。

次に承認を実施します。
作成者が承認依頼を行い、ステータスをPENDING_APPROVAL(承認待ち)にしてから、管理者がステータスをAPPROVED(承認)へ更新する、2段階で進めるイメージです。

scripts/registry_lab.py(approveの抜粋)
CONTROL.submit_registry_record_for_approval(registryId=STATE['registryId'], recordId=record_id)
wait_record(record_id, 'PENDING_APPROVAL')
CONTROL.update_registry_record_status(
    registryId=STATE['registryId'], recordId=record_id,
    status='APPROVED', statusReason='Reviewed the disposable example metadata.',
)
レコードの承認
uv run scripts/registry_lab.py approve
approveの実行結果
{"event": "submitted", "status": "PENDING_APPROVAL"}
{"event": "approved", "status": "APPROVED"}

承認したので、もう一度一覧を取ってみて状態を確認してみましょうか。

承認後の状態を確認
uv run scripts/registry_lab.py snapshot --label after-approval
実行結果(承認後)
snapshot --label after-approval
{
  "event": "snapshot",
  "label": "after-approval",
  "managed": [
    {
      "name": "calculation-http-agent",
      "status": "APPROVED",
      "recordType": "AGENT",
      "description": "Adds two numbers using the add_numbers tool. Hosted on AgentCore Runtime. POST JSON with a prompt string; returns a text/event-stream response. Authentication: AWS IAM (SigV4). Owner: demo team."
    }
  ],
  "discovered": [
    {
      "name": "calculation-http-agent",
      "status": "APPROVED",
      "recordType": "AGENT",
      "description": "Adds two numbers using the add_numbers tool. Hosted on AgentCore Runtime. POST JSON with a prompt string; returns a text/event-stream response. Authentication: AWS IAM (SigV4). Owner: demo team."
    }
  ]
}

利用者向けの一覧にも、APPROVEDで1件現れましたね!

この状態で、承認済みレコードの説明文を書き換えた場合の挙動も確認してみます。
update_registry_recordで、optionalValueに新しい説明文を指定して更新します。

scripts/registry_lab.py(reviseの抜粋)
CONTROL.update_registry_record(
    registryId=STATE['registryId'], recordId=STATE['records']['http'],
    description={'optionalValue': 'Revised draft: add_numbers accepts two integers.'},
)
説明文の更新
uv run scripts/registry_lab.py revise
reviseの実行結果
{"event": "revised", "status": "DRAFT", "description": "Revised draft: add_numbers accepts two integers."}

更新した時点で、管理側のステータスはAPPROVEDからDRAFTに戻りました。この状態で管理側と利用者側の見え方を比べてみます。

更新後の状態を確認
uv run scripts/registry_lab.py snapshot --label after-revision
実行結果(説明文の更新後)
snapshot --label after-revision
{
  "event": "snapshot",
  "label": "after-revision",
  "managed": [
    {
      "name": "calculation-http-agent",
      "status": "DRAFT",
      "recordType": "AGENT",
      "description": "Revised draft: add_numbers accepts two integers."
    }
  ],
  "discovered": [
    {
      "name": "calculation-http-agent",
      "status": "APPROVED",
      "recordType": "AGENT",
      "description": "Adds two numbers using the add_numbers tool. Hosted on AgentCore Runtime. POST JSON with a prompt string; returns a text/event-stream response. Authentication: AWS IAM (SigV4). Owner: demo team."
    }
  ]
}
見え方 管理用の一覧 利用者向けの一覧・検索
ステータス DRAFT APPROVED
説明文 更新後の新しい説明 承認済みの古い説明

管理側では更新後の内容が反映されて再レビュー待ちになる一方、利用者側には承認済みの古い説明がそのまま公開され続けます。

再レビュー中でも公開中の情報は消えず、カタログとしては常に承認済みのレコードが表示される仕組みで安心ですね!

MCPにも対応している

レジストリはAPIだけでなく、MCPにも対応しています。プレビュー時よりも対応しているツールが増えていますね!

ツール 返却される情報
list_discoverable_registry_records ID、名前、表示名、説明、種別、バージョン、承認状態、記述子の種類。URLなどの記述子本文は含まれない
search_discoverable_registry_records 検索に一致したレコード。今回は説明とHTTP記述子のURLも含まれる
batch_get_discoverable_registry_record 指定したIDの詳細。HTTP記述子のURLを取得できた

3つとも利用者向けのツールなので、SDKのときと同じく、返ってくるのは承認済みのレコードだけです。

MCPのスクリプトも用意しているので、実行してみます。

実行コマンド
uv run scripts/registry_lab.py mcp

それぞれのリクエストと応答は次のとおりです。応答は content[].text に入っているJSON文字列を整形し、IDは置換しています。

list_discoverable_registry_records
リクエスト
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "list_discoverable_registry_records",
    "arguments": {}
  }
}
応答
{
  "registryRecords": [
    {
      "recordArn": "arn:aws:agent-registry:us-east-1:<ACCOUNT_ID>:registry/<REGISTRY_ID>/record/<RECORD_ID>",
      "recordId": "<RECORD_ID>",
      "name": "calculation-http-agent",
      "displayName": "Calculation HTTP Agent",
      "description": "Adds two numbers using the add_numbers tool. Hosted on AgentCore Runtime. POST JSON with a prompt string; returns a text/event-stream response. Authentication: AWS IAM (SigV4). Owner: demo team.",
      "recordType": "AGENT",
      "recordVersion": "1.0.0",
      "status": "APPROVED",
      "createdAt": "2026-09-15T04:48:58.608183099Z",
      "updatedAt": "2026-09-15T04:49:56.904363846Z",
      "descriptorTypes": [
        "http"
      ]
    }
  ]
}

descriptorTypes で記述子の種類は分かりますが、URLなどの本文は含まれません。

search_discoverable_registry_records
リクエスト
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "search_discoverable_registry_records",
    "arguments": {
      "searchQuery": "add two numbers calculation",
      "maxResults": 5
    }
  }
}
応答
[
  {
    "recordId": "<RECORD_ID>",
    "name": "calculation-http-agent",
    "displayName": "Calculation HTTP Agent",
    "description": "Adds two numbers using the add_numbers tool. Hosted on AgentCore Runtime. POST JSON with a prompt string; returns a text/event-stream response. Authentication: AWS IAM (SigV4). Owner: demo team.",
    "recordType": "AGENT",
    "descriptors": {
      "mcpServer": null,
      "a2aAgentCard": null,
      "agentSkillsDefinition": null,
      "custom": null,
      "http": {
        "source": {
          "fromUrl": {
            "url": "https://bedrock-agentcore.us-east-1.amazonaws.com/runtimes/arn%3Aaws%3Abedrock-agentcore%3Aus-east-1%3A<ACCOUNT_ID>%3Aruntime%2F<RUNTIME_ID>/invocations?qualifier=DEFAULT"
          }
        }
      },
      "agui": null
    },
    "recordVersion": "1.0.0",
    "status": "APPROVED"
  }
]

一覧と違い、記述子の本文まで返ります。未使用の記述子は null で並びます。

batch_get_discoverable_registry_record
リクエスト
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "batch_get_discoverable_registry_record",
    "arguments": {
      "recordIds": ["<RECORD_ID>"]
    }
  }
}
応答
{
  "registryRecords": [
    {
      "registryArn": "arn:aws:agent-registry:us-east-1:<ACCOUNT_ID>:registry/<REGISTRY_ID>",
      "recordArn": "arn:aws:agent-registry:us-east-1:<ACCOUNT_ID>:registry/<REGISTRY_ID>/record/<RECORD_ID>",
      "recordId": "<RECORD_ID>",
      "name": "calculation-http-agent",
      "description": "Adds two numbers using the add_numbers tool. Hosted on AgentCore Runtime. POST JSON with a prompt string; returns a text/event-stream response. Authentication: AWS IAM (SigV4). Owner: demo team.",
      "displayName": "Calculation HTTP Agent",
      "recordType": "AGENT",
      "descriptors": {
        "mcpServer": null,
        "a2aAgentCard": null,
        "agentSkillsDefinition": null,
        "custom": null,
        "http": {
          "source": {
            "fromUrl": {
              "url": "https://bedrock-agentcore.us-east-1.amazonaws.com/runtimes/arn%3Aaws%3Abedrock-agentcore%3Aus-east-1%3A<ACCOUNT_ID>%3Aruntime%2F<RUNTIME_ID>/invocations?qualifier=DEFAULT"
            }
          }
        },
        "agui": null
      },
      "recordVersion": "1.0.0",
      "status": "APPROVED",
      "createdAt": "2026-09-15T04:48:58.608183099Z",
      "updatedAt": "2026-09-15T04:49:05.596253649Z"
    }
  ],
  "errors": []
}

指定したIDのレコードが registryRecords に入り、記述子の本文まで返ります。

HTTP記述子から分かるのは接続先URLなどです。今回の用途・入力形式・認証方式・管理担当は、登録時に説明文へ記載しました。こうした情報があると、利用者が候補を選び、呼び出し方を確認しやすくなります。

利用者Agent側の使い方としては、次の図のように、一覧や検索で候補を絞り込み、選んだレコードだけ一括取得で記述子まで取り出す、という2段構えになります。一覧はURLなどの本文を返さないぶん応答が軽いので、候補選びと接続情報の取得を使い分けられます。

利用者AgentがRegistryの一覧から候補を選び、選んだレコードの詳細を一括取得する流れ

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/registry-mcp-endpoint.html

取得したURLへアプリから接続する

通常のアプリでもSDKからカタログを検索・取得できるので、今回は一括取得したHTTP記述子のURLへ、PythonからIAM認証(SigV4署名)付きでPOSTしてみます。

scripts/registry_lab.py(invokeの抜粋)
result = DISCOVERY.batch_get_discoverable_registry_record(entries=[{
    'registryId': STATE['registryId'], 'recordIds': [STATE['records']['http']],
}])
url = result['registryRecords'][0]['descriptors']['http']['source']['fromUrl']['url']
payload = json.dumps({'prompt': 'Use only add_numbers to calculate 2 + 3. Reply with the result.'})
headers = {'Content-Type': 'application/json', 'Accept': 'text/event-stream',
           'X-Amzn-Bedrock-AgentCore-Runtime-Session-Id': str(uuid.uuid4())}
signed = AWSRequest(method='POST', url=url, data=payload, headers=headers)
SigV4Auth(SESSION.get_credentials().get_frozen_credentials(), 'bedrock-agentcore', SESSION.region_name).add_auth(signed)
Runtimeを呼び出す
uv run scripts/registry_lab.py invoke
実行結果の抜粋
{
  "http_status": 200,
  "content_type": "text/event-stream; charset=utf-8",
  "response_text": "The result is **5**."
}

Registryから接続先を取得し、Runtime上の add_numbers を使った計算結果が返りました!エージェントが動的に候補を探す用途に加え、業務アプリから既存のエージェントを呼び出すときにも使えそうですね!

コンソールの登録画面も確認する

ここまではSDKで登録してきましたが、コンソールの登録画面も見ておきます。Registryの詳細から「レコードを作成」を開き、「ソース」と「手動で定義」の両方でエージェントを選択してみましたが、HTTP形式の選択肢は表示されませんでした。手動定義では、次の3種類が表示されています。

エージェントの記述子にHTTPの選択肢は表示されなかった

HTTP形式そのものは選べませんが、タイプ「エージェント」+記述子「カスタム」なら、接続先URLや認証方式を独自のJSONとして登録できます。

ただし、これは今回SDKで登録したHTTP記述子とは別形式のレコードです。ややこしいですね・・・

違いを整理すると次のようになります。

観点 HTTP記述子 カスタム記述子
登録方法 SDK・CLI(コンソールに選択肢なし) コンソール・SDKの両方
記述子の中身 接続先URLのみ(構造は固定) 自由なJSON文字列
取得時の返り方 http.source.fromUrl.url にURLが入る custom.data に文字列のまま入る
利用側の実装 URLをそのまま接続先に使える JSONを解釈して接続情報を取り出す

Registryはカスタム記述子の中身を解釈しないので、項目の決め方と読み方は利用側とそろえておく必要があります。そこを許容できるなら、コンソールから登録する場合の選択肢になります。

AgentCore Runtimeをカスタム記述子で載せるなら、たとえば次のようなJSONになります。項目名はスキーマのない自由定義で、今回の検証用に決めたものです。この内容をSDK(descriptors={'custom': {'data': ...}})で登録し、承認からMCPでの取得まで可能です。

カスタム記述子のJSON例(AgentCore Runtime)
カスタム記述子の定義
{
  "endpoint": "https://bedrock-agentcore.us-east-1.amazonaws.com/runtimes/<URLエンコードしたRuntime ARN>/invocations?qualifier=DEFAULT",
  "authentication": {
    "type": "AWS_IAM",
    "signingService": "bedrock-agentcore"
  },
  "request": {
    "method": "POST",
    "contentType": "application/json",
    "example": {"prompt": "Use add_numbers to calculate 2 + 3."}
  },
  "response": {"contentType": "text/event-stream"},
  "owner": "demo team"
}

呼び出し先URLや署名サービス名、入出力の形式をまとめて定義しておけば、利用側はこのJSONをパースして接続処理を組み立てられます。

SDKやCLIだけでなく・・・コンソールでも同じようにRuntimeを簡単に登録できるようになると・・・嬉しいですね・・・!(もし私の見落としで、コンソールからも登録できるようなら教えてください・・・!)
それか自アカウント内だけ検出できるようになるとかでも・・・!

暗号化とイベント通知

セキュリティ面では、カスタマーマネージドKMSキーに対応しました。descriptorや検索インデックスを自前のKMSキーで暗号化できます。このキーはレジストリ作成時に指定します。作成後の変更はできません。名前や説明といったメタデータについては、従来どおりAWS所有キーで暗号化されます。

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/registry-data-encryption.html

また、EventBridgeの通知イベントも拡充されました。承認・拒否・非推奨化(Deprecated)などのステータス変更を通知できます。

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/registry-faq.html#registry-faq-eventbridge-notifications

プレビューから使っている人は移行が必要

プレビュー版から触っていた方は注意が必要で、bedrock-agentcore 名前空間の Registry は 2026年9月17日に読み書きができなくなる予定です。データの自動移行は行われないため、新しいレジストリへ手動で移す必要があります。

前回の記事で書いたコードからも、主に以下の指定が変わっています。

変更箇所
管理用クライアント bedrock-agentcore-control agent-registry-control
利用者向けクライアント bedrock-agentcore agent-registry
検索メソッド search_registry_records() search_discoverable_registry_records()
Registry用IAMアクション bedrock-agentcore: agent-registry:
descriptorの本文 inlineContent data

descriptorの構造やRegistry本体のARN、MCPの接続先も変わっています。移行時は、クライアント名と合わせて確認してください。

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/registry-faq.html

エージェントの動的な利用にもつなげる

A2A形式のRuntimeもOrganizationsの自動検出対象です。
登録内容を確認・補足して承認すれば、以前試した、Registryで接続先を探してStrands AgentsからA2Aで呼び出す構成にもつなげられそうです!勝手にA2Aで幅広く色々なエージェントと繋がっていく未来は面白そうですね・・・!
精度とのトレードオフになりますし、頻繁に繋がりまくってもレイテンシーとか気になるので悩ましいポイントも多くありそうですが・・・!

https://dev.classmethod.jp/articles/aws-agent-registry-dynamic-a2a-strands-agents/

動的な利用はA2Aに限らず、HTTP形式のレコードでも同じように扱えます!
今回のサンプルのようにカタログからURLを取得して呼び出す処理をアプリに入れておけば、社内のカタログアプリからエージェントを探してそのまま試す、といった使い方ができそうですね。
また、エージェント側が実行時にRegistryを検索して、見つけた相手をHTTPSのAPIとしてツールで呼び出したい場面でも使えそうです!

組織でどう使うか

今回試したようにOrganizations連携で自動検出を有効にすると、組織内の同一リージョンのRuntime・Gatewayが登録され、それ以外の環境で動くエージェントも、HTTPSエンドポイントを手動登録して同じカタログに載せられます。

実行基盤に応じて登録し、Registryで取得した接続情報を使って既存エージェントを呼び出す例

たとえば、営業アプリからサポートチームの注文確認エージェントを呼び出したいケースを考えてみます。
開発者がRegistryで承認済みの候補を検索し、接続先と入出力仕様を確認して、営業アプリに呼び出し処理を実装します。実行時は、そのエージェントが求める認証・権限で接続します。既存の注文確認処理を使えるので、別チームで作り直す手間を減らせそうです!またコミュニケーションのきっかけになって、カタログに載っているエージェントの作り方とかも聞いたりなどもしやすくなるのかなーとか思いました。

AWS Organizationsを使っているなら、エージェント管理用のメンバーアカウントを委任管理者にして、Registryで情報を集約・承認する構成が良さそうに思えますね!管理用アカウントのRegistryをAWS RAMで各チームのアカウントへ共有すれば、各チームが共通のカタログからエージェントを探せます!以下はRAM共有を使う構成のイメージです。

管理用アカウントのRegistryをAWS RAMで営業チームへ共有し、サポートチームのエージェントを利用する運用例

クロスアカウント共有の詳しい仕様は公式ドキュメントもあわせて確認してみてください。
今回は試していないので、また別の記事で検証したいですね!

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/registry-cross-account-sharing.html

後片付け

最後に、今回作成したレコードとレジストリを削除しておきます。

レコードとレジストリの削除
uv run scripts/registry_lab.py cleanup
実行結果
{"event": "record_deleted", "kind": "http"}
{"event": "registry_deleted"}

レコードが残っているとレジストリを削除できないため、先にレコードをすべて削除してからレジストリ本体を削除します。

scripts/registry_lab.py(cleanupの抜粋)
for kind, record_id in list(STATE['records'].items()):
    CONTROL.delete_registry_record(registryId=STATE['registryId'], recordId=record_id)
CONTROL.delete_registry(registryId=STATE['registryId'])

Runtime側はAgentCore CLIで片付けます。agentcore remove all はプロジェクトの定義を空にするコマンドなので、そのあとに agentcore deploy を実行して、空の状態をAWSへ反映させます。

Runtimeの削除
cd registrygalab
agentcore remove all -y
agentcore deploy

CloudFormationスタックごと消えるので、Runtimeと一緒に実行ロールやロググループも削除されます。

おわりに

前回のプレビュー記事で気になっていたHTTPS URLの登録を試せて、Organizationsの自動検出も確認できました!

AWS RAMによるアカウント間共有のほか、カスタマーマネージドKMSキーによる暗号化、EventBridgeと連携した承認通知など、まだ試したい機能がいろいろありますし、Registryの運用も腰を据えて考えてみたいですね!今回はエージェントのカタログにフォーカスしていますが、スキルやMCPも管理できますからね。実際の運用イメージなどこれからブログもどしどし書いていければと思います!!(エンプラの希望の星になって欲しいです)

本記事が少しでも参考になりましたら幸いです。最後までご覧いただきありがとうございました!

この記事をシェアする

関連記事