AgentCore Observabilityをクロスアカウントで試してみた

AgentCore Observabilityをクロスアカウントで試してみた

AgentCore Observabilityのクロスアカウントオブザーバビリティを試してみました!
2026.07.11

はじめに

こんにちは、ドライブ練習中のコンサル部の神野(じんの)です。
久しぶりに高速道路に乗って緊張しました。

さて話は変わって、AgentCore Observabilityをみなさん使っていますか?
AIエージェントの動きが可視化されて便利ですよね。可視化する情報を1つのアカウントに集約したいといったケースはないでしょうか・・・?

そんな中、AgentCore ObservabilityがCloudWatchのクロスアカウントオブザーバビリティに対応していることを公式ドキュメントで見つけました。
モニタリングアカウントを1つ用意すれば、複数のソースアカウントにデプロイされたエージェントのメトリクス・トレース・セッションを一箇所から確認できるとのことです。

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

公式ドキュメントの手順を参考にして、実際に2つのアカウントを使って試してみました!

仕組みの概要

クロスアカウントオブザーバビリティは、CloudWatchのObservability Access Manager(OAM)という仕組みで実現されます。

リソース 作成する場所 役割
Sink モニタリングアカウント ソースアカウントからのテレメトリを受け入れる窓口
Link ソースアカウント SinkのARNを指定してテレメトリを共有する接続

モニタリングアカウントにSinkを1つ作成し、各ソースアカウントからLinkを張ることで、モニタリングアカウントのAgentCore Observabilityコンソールにソースアカウントのデータが自動的に表示されるようになります。

この仕組みの詳細は川原さんが丁寧に記載されているので、ぜひ必要に応じてご参照ください。

https://dev.classmethod.jp/articles/aggregate-metrics-by-oam/

AgentCoreのオブザーバビリティで必要なテレメトリタイプはMetricsとLogsの2つです。トレースやセッションのデータはaws/spansというロググループに格納されるため、Logsの共有に含まれるかたちになります。

今回構築する構成は下記の通りです。

CleanShot 2026-07-11 at 21.49.20@2x

前提

今回の検証環境は下記の通りです。(アカウントIDはダミーです)

項目 内容
モニタリングアカウント 111111111111
ソースアカウント 222222222222
リージョン us-east-1
エージェント AgentCore CLIで作成するStrandsエージェント

ソース側のエージェントはAgentCore CLI(agentcore コマンド)で作成するところから始めます。CLIのインストールがまだの場合は下記でインストールできます。今回使用したバージョンは 1.0.0-preview.16 です。

実行コマンド
npm install -g @aws/agentcore

構築

OAMのセットアップはコンソールからもできますが、今回は公式ドキュメントに記載のCloudFormationテンプレートを使ってIaCで構築していきます。手順は下記の4ステップです。

  1. ソースアカウントにAgentCore CLIでエージェントをデプロイ
  2. 両アカウントでTransaction Searchを有効化
  3. モニタリングアカウントにOAM Sinkを作成
  4. ソースアカウントにOAM Linkを作成

ソースアカウントにエージェントをデプロイ

まずは監視対象となるエージェントを作ります。AgentCore CLIの agentcore create を実行すると、対話形式でプロジェクトを作成できます。今回はStrandsフレームワークのシンプルな構成にしました。

実行コマンド
agentcore create --project-name crossacctdemo --name demo_agent \
  --framework Strands --model-provider Bedrock --memory none
実行結果
[done]  Create crossacctdemo/ project directory
[done]  Prepare agentcore/ directory
[done]  Add agent to project
[done]  Set up Python environment

Created:
  crossacctdemo/
    app/demo_agent/  Python agent (Strands)
    agentcore/       Config and CDK project

Project created successfully!

エージェント本体(app/demo_agent/main.py)とCDKのデプロイ設定がまとめて生成されます。生成されたmain.pyのエントリーポイント部分を見てみます。あとでクロスアカウントでアプリケーションログを確認したいので、受け取ったプロンプトをログ出力する処理を1行追加しました。

app/demo_agent/main.py(抜粋)
app = BedrockAgentCoreApp()
log = app.logger

# 数値を加算するシンプルなツール
@tool
def add_numbers(a: int, b: int) -> int:
    """Return the sum of two numbers"""
    return a+b

@app.entrypoint
async def invoke(payload, context):
    log.info("Invoking Agent.....")

    agent = get_or_create_agent()

    prompt = _extract_prompt(payload)
    log.info("Received prompt: %s", prompt)  # 追加: アプリケーションログの確認用

    async for event in agent.stream_async(prompt):
        ...

app.loggerで出力したログは、AgentCoreランタイムのロググループにアプリケーションログとして記録されます。あとはソースアカウントのクレデンシャルで agentcore deploy を実行するだけです。

実行コマンド
cd crossacctdemo
agentcore deploy -y
実行結果
 Deployed to 'default' (stack: AgentCore-crossacctdemo-default)

Outputs:
  ...RuntimeArnOutput...: arn:aws:bedrock-agentcore:us-east-1:222222222222:runtime/crossacctdemo_demo_agent-XXXXXXXXXX
  ...RuntimeIdOutput...: crossacctdemo_demo_agent-XXXXXXXXXX
  StackNameOutput: AgentCore-crossacctdemo-default

Note: Transaction search enabled. It takes ~10 minutes for transaction search
to be fully active and for traces from invocations to be indexed.
Next: agentcore invoke | agentcore status

CDKスタックとしてランタイム・IAMロールがまとめてデプロイされました。

Transaction Searchの有効化

AgentCoreのトレースやセッションをコンソールで確認するには、CloudWatchのトランザクション検索(X-Rayトレースの送信先をCloudWatch Logsに変更する設定)が有効になっている必要があります。

スパンの取り込みを許可するには、アカウントごとにトランザクション検索を1回有効にします。CloudWatchコンソールのTransaction Search画面を開き、下記の「Enable Transaction Search」ボタンを押して有効化します。

Transaction Searchの有効化画面

この操作をモニタリングアカウント・ソースアカウントの両方で実施しておきます。なお、先ほどの agentcore deploy の出力にTransaction search enabledと表示されていた通り、AgentCore CLIでデプロイした場合はソースアカウント側の有効化は自動で行われるため、実質的にはモニタリングアカウント側の対応だけでOKです。

モニタリングアカウントにOAM Sinkを作成

続いてモニタリングアカウント側です。ソースアカウントからのLink作成を受け入れるSinkを作成します。公式ドキュメントのテンプレートをベースに、ソースアカウントIDをパラメータ化したものがこちらです。

monitoring-sink.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: OAM Sink for cross-account AgentCore Observability (specific accounts)

Parameters:
  SourceAccountId:
    Type: String
    Description: Source account ID to allow linking

Resources:
  ObservabilitySink:
    Type: AWS::Oam::Sink
    Properties:
      Name: AgentCoreObservabilitySink
      Policy:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - !Ref SourceAccountId
            Action:
              - 'oam:CreateLink'
              - 'oam:UpdateLink'
            Resource: '*'
            Condition:
              ForAllValues:StringEquals:
                oam:ResourceTypes:
                  - 'AWS::Logs::LogGroup'
                  - 'AWS::CloudWatch::Metric'
      Tags:
        Purpose: AgentCoreObservability

Outputs:
  SinkArn:
    Value: !GetAtt ObservabilitySink.Arn
    Description: Share this ARN with source accounts to create links

SinkのポリシーでLink作成を許可するアカウントを制御します。Conditionのoam:ResourceTypesでLogsとMetricsのみに共有範囲を絞っているため、意図しないテレメトリタイプが共有される心配はありません。

モニタリングアカウントのクレデンシャルでデプロイします。

実行コマンド
aws cloudformation deploy \
  --template-file monitoring-sink.yaml \
  --stack-name agentcore-observability-sink \
  --parameter-overrides SourceAccountId=222222222222 \
  --region us-east-1

デプロイが完了したら、OutputsからSinkのARNを控えておきます。

実行コマンド
aws cloudformation describe-stacks \
  --stack-name agentcore-observability-sink \
  --query 'Stacks[0].Outputs[0].OutputValue' \
  --output text \
  --region us-east-1
実行結果
arn:aws:oam:us-east-1:111111111111:sink/556e6669-6692-4950-86dc-18276be0c5a3

ソースアカウントにOAM Linkを作成

次はソースアカウント側です。先ほど控えたSinkのARNを指定してLinkを作成します。

source-link.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: OAM Link for cross-account AgentCore Observability

Parameters:
  SinkArn:
    Type: String
    Description: Sink ARN from the monitoring account

Resources:
  ObservabilityLink:
    Type: AWS::Oam::Link
    Properties:
      LabelTemplate: '$AccountName'
      ResourceTypes:
        - 'AWS::Logs::LogGroup'
        - 'AWS::CloudWatch::Metric'
      SinkIdentifier: !Ref SinkArn
      Tags:
        Purpose: AgentCoreObservability

LabelTemplateは、モニタリングアカウント側でソースアカウントを識別するための表示名です。$AccountNameを指定するとアカウント名がそのままラベルになります。ResourceTypesはSink側のポリシーで許可した範囲と一致させる必要があります。

今回はResourceTypesでLogsとMetricsを共有対象にしています。LinkConfigurationによる絞り込みは設定していないため、ソースアカウント内のロググループとCloudWatchメトリクスが広く共有対象になります。特定のロググループやメトリクス名前空間だけに限定したい場合は、Link側のLinkConfigurationでフィルターできます。

ソースアカウントのクレデンシャルでデプロイします。

実行コマンド
aws cloudformation deploy \
  --template-file source-link.yaml \
  --stack-name agentcore-observability-link \
  --parameter-overrides SinkArn=arn:aws:oam:us-east-1:111111111111:sink/556e6669-6692-4950-86dc-18276be0c5a3 \
  --region us-east-1

Linkが作成できたか確認してみます。

実行コマンド
aws oam list-links --region us-east-1
実行結果
{
    "Items": [
        {
            "Arn": "arn:aws:oam:us-east-1:222222222222:link/8d09e5f3-0884-44b0-a235-54d7e87837ab",
            "Id": "8d09e5f3-0884-44b0-a235-54d7e87837ab",
            "Label": "sandbox",
            "ResourceTypes": [
                "AWS::Logs::LogGroup",
                "AWS::CloudWatch::Metric"
            ],
            "SinkIdentifier": "arn:aws:oam:us-east-1:111111111111:sink/556e6669-6692-4950-86dc-18276be0c5a3"
        }
    ]
}

問題なくLinkが作成されていますね!これで構築は完了です。
早速検証してみましょう!

動作確認

テレメトリの生成

まずはデプロイしたエージェントを呼び出して、テレメトリを生成します。agentcore invoke で呼び出します。

実行コマンド
agentcore invoke '{"prompt": "123と456を足すといくつですか?ツールを使って計算してください"}'
実行結果
Session: b96f6616-36fb-46bd-b226-c3c0ea52ea12

--- RESPONSE ---
{
  "success": true,
  "response": "123と456を足すと、**579**になります。"
}

add_numbersツールを使って計算した応答が返ってきました。この裏でメトリクス・ログ・スパンが生成されている状態になっています。

モニタリングアカウントからCLIで確認

ここからはすべてモニタリングアカウントの権限で操作します。まずSinkに接続されているLinkの一覧を確認します。

実行コマンド
aws oam list-attached-links \
  --sink-identifier arn:aws:oam:us-east-1:111111111111:sink/556e6669-6692-4950-86dc-18276be0c5a3 \
  --region us-east-1
実行結果
{
    "Items": [
        {
            "Label": "sandbox",
            "LinkArn": "arn:aws:oam:us-east-1:222222222222:link/8d09e5f3-0884-44b0-a235-54d7e87837ab",
            "ResourceTypes": [
                "AWS::Logs::LogGroup",
                "AWS::CloudWatch::Metric"
            ]
        }
    ]
}

ソースアカウントがちゃんとリンクされていますね!次にメトリクスです。--include-linked-accountsオプションを付けると、リンクされたアカウントのメトリクスも一覧できます。

実行コマンド
aws cloudwatch list-metrics \
  --include-linked-accounts \
  --owning-account 222222222222 \
  --region us-east-1 \
  --query 'Metrics[].[Namespace,MetricName]' \
  --output text | sort -u | head
実行結果
AWS/Bedrock-AgentCore	Duration
AWS/Bedrock-AgentCore	Invocations
AWS/Bedrock-AgentCore	Latency
AWS/Bedrock-AgentCore	Sessions
AWS/Bedrock-AgentCore	SystemErrors
AWS/Bedrock-AgentCore	Throttles
AWS/Bedrock-AgentCore	UserErrors

ソースアカウントのAWS/Bedrock-AgentCore名前空間のメトリクスが、モニタリングアカウントから見えていますね!!

メトリクスの実データも取得してみます。クロスアカウントのメトリクス値を取得する場合は、get-metric-dataでAccountIdを指定します。

metric-query.json
[
  {
    "Id": "inv",
    "AccountId": "222222222222",
    "MetricStat": {
      "Metric": {
        "Namespace": "AWS/Bedrock-AgentCore",
        "MetricName": "Invocations",
        "Dimensions": [
          {"Name": "Resource", "Value": "arn:aws:bedrock-agentcore:us-east-1:222222222222:runtime/crossacctdemo_demo_agent-XXXXXXXXXX"},
          {"Name": "Operation", "Value": "InvokeAgentRuntime"},
          {"Name": "Name", "Value": "crossacctdemo_demo_agent::DEFAULT"}
        ]
      },
      "Period": 3600,
      "Stat": "Sum"
    }
  }
]
実行コマンド
aws cloudwatch get-metric-data \
  --metric-data-queries file://metric-query.json \
  --start-time 2026-07-11T00:00:00Z \
  --end-time 2026-07-11T02:00:00Z \
  --region us-east-1
実行結果
{
    "MetricDataResults": [
        {
            "Id": "inv",
            "Label": "Invocations",
            "Timestamps": [
                "2026-07-11T08:32:00+09:00"
            ],
            "Values": [
                1.0
            ],
            "StatusCode": "Complete"
        }
    ],
    "Messages": []
}

先ほどのエージェント呼び出しがInvocationsとしてカウントされ、モニタリングアカウントから取得できました!

ログも確認してみます。describe-log-groupsにも同様のオプションがあります。

実行コマンド
aws logs describe-log-groups \
  --include-linked-accounts \
  --account-identifiers 222222222222 \
  --region us-east-1 \
  --query 'logGroups[?contains(logGroupName, `agentcore`) || contains(logGroupName, `spans`)].logGroupName' \
  --output text
実行結果
/aws/bedrock-agentcore/runtimes/crossacctdemo_demo_agent-XXXXXXXXXX-DEFAULT	aws/spans

エージェントのランタイムログに加えて、トレースデータが格納されるaws/spansロググループも見えていますね。

エージェント自身が出力するアプリケーションログもクロスアカウントで読めるのか確認します。main.pyに追加した log.info("Received prompt: ...") の出力を、モニタリングアカウントから探してみます。

実行コマンド
aws logs filter-log-events \
  --log-group-identifier "arn:aws:logs:us-east-1:222222222222:log-group:/aws/bedrock-agentcore/runtimes/crossacctdemo_demo_agent-XXXXXXXXXX-DEFAULT" \
  --filter-pattern 'prompt' \
  --max-items 1 \
  --region us-east-1 \
  --query 'events[].message' \
  --output text
実行結果(抜粋)
{"resource":{"attributes":{"service.name":"crossacctdemo_demo_agent.DEFAULT",
"cloud.platform":"aws_bedrock_agentcore","cloud.region":"us-east-1",...}},
"severityText":"INFO",
"body":"Received prompt: {\"prompt\": \"123と456を足すといくつですか?ツールを使って計算してください\"}",
...}

エージェントのコードで出力したアプリケーションログが、モニタリングアカウントからも確認できましたね!OAMのLogs共有はロググループ単位なので、AgentCoreの標準テレメトリだけでなく、アプリケーション独自のログも一緒に共有されます。

トレースのスパンデータも同様に確認してみます。

実行コマンド
aws logs filter-log-events \
  --log-group-identifier "arn:aws:logs:us-east-1:222222222222:log-group:aws/spans" \
  --filter-pattern 'crossacctdemo' \
  --max-items 1 \
  --region us-east-1 \
  --query 'events[].message' \
  --output text
実行結果(抜粋)
{"resource":{"attributes":{"aws.local.service":"crossacctdemo_demo_agent.DEFAULT",
"cloud.region":"us-east-1","aws.service.type":"gen_ai_agent",
"cloud.platform":"aws_bedrock_agentcore",...}},
"traceId":"...","spanId":"...","kind":"CLIENT",...}

エージェントが生成したOpenTelemetryのスパンデータも読めました!無事メトリクス・アプリケーションログ・トレースのすべてがクロスアカウントで確認できました!

コンソールで確認

CLIでの確認だけだと味気ないので、本命のAgentCore Observabilityコンソールも見てみます。モニタリングアカウントでCloudWatchコンソールを開き、左ペインのGenAI Observabilityを選択します。

agents-list

ソースアカウントのエージェントが、モニタリングアカウントのコンソールに自動的に表示されていますね!クロスアカウント設定後は一覧にAccount / Account IDの列が追加され、どのアカウントのエージェントかが一目でわかるようになっています。

トレースの詳細画面も開いてみます。

trace-detail

トレース詳細にはAccount ID: Source Accountとして、ソースアカウントのデータであることが明示されています。add_numbersツールの呼び出しやLLM呼び出しのスパンツリー、Trajectory、入出力の中身まで、モニタリングアカウントからそのまま確認できましたね!

制約事項

公式ドキュメントに記載の制約をまとめておきます。

制約 内容
リージョン 単一リージョン内でのみ動作。モニタリングとソースは同一リージョン必須
Linkの維持 OAM Linkを削除するとクロスアカウントデータは見えなくなる
テレメトリタイプ MetricsとLogsの両方の共有が必要。片方だけだとデータが欠落する
リソース操作 Bedrockコンソールへの遷移など一部の操作はクロスアカウントでは不可。ソースアカウントへのサインインが必要

またベースとなるCloudWatchクロスアカウントオブザーバビリティ(OAM)自体の制限・仕様も押さえておくとよいです。

項目 内容
Sink数 1アカウント・1リージョンあたり1つまで
リンク数 モニタリングアカウントは最大10万ソースアカウントとリンク可能。ソースアカウント側は最大5つのモニタリングアカウントまで
テレメトリタイプの整合 ソース側がモニタリング側より多くのテレメトリタイプを選択しているとLink作成自体が失敗する
メトリクス表示 Link作成後に新しいデータポイントが発行されるまで、メトリクス名はモニタリングアカウントに表示されない
削除の順序 Sinkを削除するには、先にすべてのLinkを削除する必要がある
料金 クロスアカウント共有自体に追加料金はなし。ただしTransaction Searchのスパン取り込みなど元機能側の料金は別途発生

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Unified-Cross-Account.html

おわりに

マルチアカウントでエージェントを運用するケースで、運用チームのアカウントをモニタリングアカウントにして可視化する場合に今回紹介した機能は便利そうですね!今後はアラームやダッシュボードと組み合わせた運用設計なども考えらればと思いました。

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

補足: 検証環境のクリーンアップ

検証が終わったら、下記の順で削除すればもとに戻せます。

  1. ソースアカウントでLinkのスタックを削除(aws cloudformation delete-stack --stack-name agentcore-observability-link
  2. モニタリングアカウントでSinkのスタックを削除(aws cloudformation delete-stack --stack-name agentcore-observability-sink
  3. ソースアカウントでエージェントを削除。AgentCore CLIでプロジェクト設定からエージェントを外し、再デプロイすることでCDK経由でランタイムが削除されます
実行コマンド
agentcore remove agent --name demo_agent -y
agentcore deploy -y

CDKスタック自体も含めて完全に削除する場合は、aws cloudformation delete-stack --stack-name AgentCore-crossacctdemo-default を実行します。

この記事をシェアする

関連記事