![[アップデート] Amazon Bedrock AgentCore のトレーススパンがエージェントごとの CloudWatch ロググループに統合されるようになったので試してみた](https://images.ctfassets.net/ct0aopd36mqt/7M0d5bjsd0K4Et30cVFvB6/5b2095750cc8bf73f04f63ed0d4b3546/AgentCore2.png?w=3840&fm=webp)
[アップデート] Amazon Bedrock AgentCore のトレーススパンがエージェントごとの CloudWatch ロググループに統合されるようになったので試してみた
はじめに
こんにちは、スーパーマーケットが大好きなコンサル部の神野(じんの)です。
2026年7月23日、Amazon Bedrock AgentCore のトレース、プロンプト、構造化ログ、標準出力を、エージェントごとの単一の CloudWatch ロググループへ配信するアップデートが発表されました!
これまで AgentCore のエージェントをデバッグするとき、トレーススパンはアカウント共有の aws/spans ロググループ、実行ログはエージェントごとのロググループと出力先が分かれていました。
今回のアップデートで、スパンも構造化ログも標準出力も、全部エージェントごとの単一ロググループにまとまるようになりました!
アップデートの概要
発表内容を整理すると、次のような変更です。
| 項目 | 従来 | 今回のアップデート後 |
|---|---|---|
| スパン(トレース) | アカウント共有の aws/spans ロググループ | エージェントごとのロググループ内の spans ログストリーム |
| 構造化ログ | エージェントごとのロググループ | 変わらず(同じロググループ) |
| 標準出力 | エージェントごとのロググループ | 変わらず(同じロググループ) |
端的に言うとスパンがエージェントごとのロググループに集約されるようになったと言うアップデートですね!
それ以外は今まで通りですね。
集約先のロググループは下記の形式です。
/aws/bedrock-agentcore/runtimes/<agent_id>-<endpoint_name>
AWS の発表では、1つのロググループにまとまることのメリットとして次の点が挙げられています。
- トレースとログを同じ場所でトレースIDをキーに相関できる
- IAM ポリシーや CMK 暗号化をエージェント単位でスコープできる
- ロググループをサブスクリプションすれば、そのエージェントのトレースとログを一括エクスポートできる
SaaSなどでテナントごとに分離したいなどのケースで、ログをエージェントごとに分離できるようになったのが嬉しいポイントなのかなと感じました。
適用条件はエージェントの作成時期で変わります。2026年7月20日以降に新規作成したエージェントは自動で統一オブザーバビリティが有効になり、既存エージェントは環境変数 UNIFIED_TRACES_DESTINATION_ENABLED を true に設定してオプトインする形です。既存エージェントの有効化方法は後半の補足で紹介します。
開発者ガイドにも詳細が記載されています。
With this configuration, spans go to the
spanslog stream in/aws/bedrock-agentcore/runtimes/<agent_id>-<endpoint_name>, instead of the sharedaws/spanslog group.
前提
今回の検証環境は下記の通りです。
| 項目 | バージョン・設定 |
|---|---|
| リージョン | us-east-1 |
| AgentCore CLI | 1.0.0-preview.22 |
| ローカル Python | 3.12 |
| AgentCore Runtime | Python 3.14 |
| Strands Agents | 1.48.0 |
| aws-opentelemetry-distro | 0.18.0 |
またスパンをエージェントのロググループに配信するには、開発者ガイドによると下記の条件を満たす必要があります。
- アカウントで CloudWatch Transaction Search が有効で、トレースセグメントの送信先が CloudWatch Logs になっていること
- エージェントの実行ロールに logs:PutResourcePolicy が付与されていること(AgentCore が X-Ray からエージェントのロググループへのスパン配信を許可するために使用します。今回使った AgentCore CLI 生成の実行ロールには含まれていました)
- エージェントが ADOT(AWS Distro for OpenTelemetry)の要件バージョンを満たしていること
Transaction Search の状態は下記コマンドで確認できます。
aws xray get-trace-segment-destination
{
"Destination": "CloudWatchLogs",
"Status": "ACTIVE"
}
Destination が CloudWatchLogs で Status が ACTIVE になっていれば OK です!まだ有効化していない場合は、CloudWatch コンソールの Transaction Search 画面から有効化できます。

また、AgentCore CLIでデプロイを実施する場合は自動で有効化されます!
やってみた
ここからは実際にエージェントをデプロイして確認していきます!
AgentCore CLI のインストール
まだインストールしていない場合は、npm でグローバルインストールします。
npm install -g @aws/agentcore
agentcore --version
プロジェクトの作成
AgentCore CLI でプロジェクトを作成します。今回は Strands Agents + Bedrock の構成で、シンプルに HTTP プロトコルのエージェントを作ります。
agentcore create \
--name unified_obs_demo \
--project-name unifiedobsdemo \
--framework Strands \
--model-provider Bedrock \
--memory none \
--protocol HTTP \
--build CodeZip
cd unifiedobsdemo
数十秒でプロジェクト一式が生成されます。app/unified_obs_demo 配下にエージェントコード、agentcore 配下に CDK ベースのデプロイ設定が作られる構成です。以降のコマンドは、生成されたプロジェクトルートで実行します。
生成された main.py には、足し算を行う add_numbers というサンプルツールと、外部 MCP サーバーに接続するクライアントを持った Strands エージェントが定義されています。今回はオブザーバビリティの確認が目的なので、コードはテンプレートのまま使います。
生成された pyproject.toml には最初から aws-opentelemetry-distro が含まれており、ロックされたバージョンを確認すると 0.18.0 でした。統一スパン配信の要件をそのまま満たしていますね!
dependencies = [
"aws-opentelemetry-distro",
"bedrock-agentcore >= 1.9.1",
"botocore[crt] >= 1.35.0",
"mcp >= 1.19.0",
"strands-agents >= 1.15.0",
]
デプロイ
サクッとデプロイも実施します。
agentcore deploy -y
✓ Deployed to 'default' (stack: AgentCore-unifiedobsdemo-default)
Outputs:
ApplicationAgentUnifiedObsDemoRuntimeArnOutput4D9425DC: arn:aws:bedrock-agentcore:us-east-1:xxxxxxxxxxxx:runtime/unifiedobsdemo_unified_obs_demo-h5bEDj6U1C
ApplicationAgentUnifiedObsDemoRuntimeIdOutput7D20BDAE: unifiedobsdemo_unified_obs_demo-h5bEDj6U1C
...
Note: Transaction search enabled. It takes ~10 minutes for transaction search to be fully active and for traces from invocations to be indexed.
CDK 経由で CloudFormation スタックが作成され、5分ほどでデプロイが完了しました。
エージェントの呼び出し
デプロイしたエージェントを呼び出してみます。せっかくなのでサンプルツールの add_numbers が動く質問を投げてみます。
agentcore invoke "125と417を足すといくつ?"
125と417を足すと542です。
Session: ba605502-7d47-4ef5-bcfb-6be37f287136
問題なく回答が返ってきましたね!これでスパンとログが生成されているはずなので、いよいよ CloudWatch Logs を見に行きます。
ログループを確認してみる
ログストリームの確認
まずエージェントのロググループを確認します。
aws logs describe-log-groups \
--log-group-name-prefix "/aws/bedrock-agentcore/runtimes/unifiedobsdemo" \
--query 'logGroups[].logGroupName' --output text
/aws/bedrock-agentcore/runtimes/unifiedobsdemo_unified_obs_demo-h5bEDj6U1C-DEFAULT
発表どおり、agent_id とエンドポイント名(DEFAULT)を組み合わせた名前のロググループが作成されています。続いて中のログストリームを見てみます。
aws logs describe-log-streams \
--log-group-name "/aws/bedrock-agentcore/runtimes/unifiedobsdemo_unified_obs_demo-h5bEDj6U1C-DEFAULT" \
--query 'logStreams[].logStreamName' --output text
2026/07/23/[runtime-logs-ba605502-...]44cb9845-...
otel-rt-logs
spans
spans ログストリームがエージェントのロググループの中にいますね!!ストリームは3種類あり、それぞれ役割が分かれています。
| ログストリーム | 内容 |
|---|---|
| runtime-logs-... | ランタイムの標準出力・標準エラー(print や Python ロガーの出力を含む) |
| otel-rt-logs | ADOT が送る OpenTelemetry の構造化ログ(トレース相関用の ID を含む) |
| spans | トレーススパン(従来は aws/spans に配信されていたもの) |
従来はこのうち spans だけがアカウント共有の aws/spans ロググループに分離されていました。今回のアップデートで、1エージェント1ロググループにトレースとログが揃ったことになります。

CloudWatch コンソールから見ても、たしかに3つのログストリームが1つのロググループに収まっています。
スパンの中身
spans ストリームの中身も覗いてみます。
aws logs get-log-events \
--log-group-name "/aws/bedrock-agentcore/runtimes/unifiedobsdemo_unified_obs_demo-h5bEDj6U1C-DEFAULT" \
--log-stream-name spans --limit 1 --query 'events[].message' --output text
{
"traceId": "6a629b0f1c107b8249e568bc0fe12db4",
"spanId": "55c78d096060c7d6",
"name": "execute_event_loop_cycle",
"attributes": {
"gen_ai.system": "strands-agents",
"session.id": "ba605502-7d47-4ef5-bcfb-6be37f287136",
...
},
"events": [
{
"name": "gen_ai.user.message",
"attributes": {"content": "[{\"text\": \"125と417を足すといくつ?\"}]"}
},
...
]
}
OpenTelemetry のスパンが JSON レコードとして保存されていて、イベントには OpenTelemetry の生成AI向け semantic conventions に沿ったユーザーメッセージやツール呼び出しの情報も含まれています。
trace_id でログとトレースを相関させる
スパンとログが同じロググループにいるので、Logs Insights のクエリ1本、ロググループ1つの指定で相関検索ができます。
先ほどのスパンの traceId を使って検索してみます。
fields @logStream, @message
| filter @message like /6a629b0f1c107b8249e568bc0fe12db4/
| stats count(*) by @logStream
spans 10
otel-rt-logs 22
runtime-logs-ba605502-... 13
1回のエージェント呼び出しに紐づくスパン10件、構造化ログ22件、標準出力13件が、単一ロググループへのクエリだけで横断できました!従来は aws/spans とエージェントのロググループの2つをまたいでクエリする必要があったので、シンプルになっていいですね。なおスパン10件には、テンプレートに含まれる MCP クライアントの mcp tools/list なども含まれています。
今回確認した Python ロガーの出力には trace_id と span_id が埋め込まれていました。任意の print 出力に自動で付与されるわけではないので、スパンと相関させたい独自ログはロガー経由で出すのが良いかと思います。
2026-07-23 22:52:07,741 INFO [strands.telemetry.metrics] [metrics.py:607]
[trace_id=6a629b0f1c107b8249e568bc0fe12db4 span_id=0598ef3735501809 ...]
- Creating Strands MetricsClient
自作ログを仕込んで障害調査をやってみる
サービスが出すログを眺めるだけだと面白くないので、ツールに自作ログを仕込んで、実務でありそうな障害調査のシナリオを再現してみます。
シナリオはこんな感じです。
- ツールにビジネスロジック上の制約(1000より大きい数は計算できない)とログを仕込む
- ユーザーが制約に引っかかる質問を投げてエラーが発生する
- 調査担当者は CloudWatch のエラーログからスタートして、trace_id だけを頼りに「ユーザーが何を聞いたからこのエラーが起きたのか」を特定する
まず add_numbers ツールに、BedrockAgentCoreApp のロガー(app.logger)で自作ログを追加します。
@tool
def add_numbers(a: int, b: int) -> int:
"""Return the sum of two numbers"""
- return a+b
+ log.info("add_numbers called: a=%s, b=%s", a, b)
+ if a > 1000 or b > 1000:
+ log.error("add_numbers failed: input too large (a=%s, b=%s)", a, b)
+ raise ValueError("1000より大きい数は計算できません")
+ result = a + b
+ log.info("add_numbers succeeded: result=%s", result)
+ return result
log は main.py の冒頭で log = app.logger として定義されているロガーです。特別な設定は何もしておらず、普通にログを出しているだけです。
再デプロイして、わざと制約に引っかかる質問を投げてみます。
agentcore deploy -y
agentcore invoke "2000と500を足すといくつ?"
申し訳ございません。使用できる計算ツールには制限があり、1000より大きい数は計算できないようです。
2000 + 500 = 2500 です。
Session: d7a17577-2fc4-421a-9b78-cc56f20380ed
ツールは意図どおり入力制約で失敗していますね!
まずログループを add_numbers failed で検索して、エラーログを探します。
aws logs filter-log-events \
--log-group-name "/aws/bedrock-agentcore/runtimes/unifiedobsdemo_unified_obs_demo-h5bEDj6U1C-DEFAULT" \
--filter-pattern '"add_numbers failed"' \
--query 'events[].message' --output text
{
"severityText": "ERROR",
"body": "add_numbers failed: input too large (a=2000, b=500)",
"attributes": {
"code.file.path": "/var/task/main.py",
"code.function.name": "add_numbers",
"code.line.number": 33
},
"traceId": "6a62afc02d9d5b39663e59b82579443c",
"spanId": "cb85adbf20bd9bd3"
}
ADOT の自動計装によって traceId 付きの構造化ログとして格納されています。発生箇所のファイル名や行番号まで入っています。
あとはこの traceId を使って、同じロググループの spans ストリームを検索します。
aws logs filter-log-events \
--log-group-name "/aws/bedrock-agentcore/runtimes/unifiedobsdemo_unified_obs_demo-h5bEDj6U1C-DEFAULT" \
--log-stream-names spans \
--filter-pattern '"6a62afc02d9d5b39663e59b82579443c"' \
--query 'events[].message' --output text
span: chat
gen_ai.user.message: [{"text": "2000と500を足すといくつ?"}]
gen_ai.assistant.message: [{"toolUse": {"name": "add_numbers", "input": {"a": 2000, "b": 500}}}]
gen_ai.tool.message: [{"toolResult": {"status": "error", "content": [{"text": "Error: 1000より大きい数は計算できません"}]}}]
span: execute_tool add_numbers
gen_ai.tool.message: {"a": 2000, "b": 500}
trace_id からユーザーの質問、LLM が組み立てたツール引数、ツールのエラー結果まで確認できました!
相関自体は従来も trace_id で可能でしたが、見る場所が1つになったことに加えて、IAM や CMK 暗号化をエージェント単位に絞れるようになったのもよいポイントかなと思います。プロンプトの中身が入るスパンを共有ロググループから切り離せるのはマルチテナント構成だと便利な気がしますね。
従来の aws/spans 側の確認
念のため、共有の aws/spans ロググループも確認してみました。今回の呼び出し以降、aws/spans には新しいイベントが届いていませんでした。新規作成したエージェントのスパンは、たしかにエージェント側のロググループだけに配信されていることが確認できましたね!
GenAI Observability ダッシュボードでの見え方
スパンの配信先が変わっても、CloudWatch コンソールの GenAI Observability ダッシュボードでのトレース可視化はこれまでどおり利用できます。エージェントの Spans タブを開くと、今回の呼び出しで生成されたスパンが10件表示されており、先ほど Logs Insights で確認した spans ストリームの件数とも一致していますね!

おわりに
ぱっと見何が嬉しいの・・??と言うアップデートかもしれませんが、エージェント単位で IAM や CMK 暗号化をスコープできるようになった点が、マルチテナントでエージェントを提供するケースで有用な気がしました!
本記事が少しでも参考になりましたら幸いです。
最後までご覧いただきありがとうございました!
補足
既存エージェントで有効化する場合
2026年7月20日より前に作成したエージェント、またはリージョンが統一配信をサポートする前に作成したエージェントは、従来どおり aws/spans への配信がデフォルトのままです。オプトインするには、ランタイムの環境変数に下記を設定します。
UNIFIED_TRACES_DESTINATION_ENABLED=true
あわせて aws-opentelemetry-distro を要件バージョン以上(What's New では 0.17.1 以上、開発者ガイドでは 0.18.0 以上と記載)にアップデートしてください。逆に、新規エージェントで従来どおり aws/spans に配信したい場合は、開発者ガイドによると false を設定すればオプトアウトできます(本検証では未確認です)。
検証リソースの削除
CloudFormation スタックを削除すると、AgentCore Runtime や実行ロールなど、スタックで管理しているリソースが削除されます。
npx cdk destroy --app agentcore/cdk/cdk.out AgentCore-unifiedobsdemo-default
CloudFormation コンソールから AgentCore-unifiedobsdemo-default スタックを削除しても OK です。
ただしロググループはスタックの管理外で、プロンプトを含む検証ログが残ります。不要なら別途削除してください。アカウント単位の Transaction Search 設定もスタックの管理外です。
aws logs delete-log-group \
--log-group-name "/aws/bedrock-agentcore/runtimes/<agent_id>-<endpoint_name>"







