はじめに
第一回では、AWSネイティブサービスで実現するDataOps × LLMOps統合アーキテクチャを紹介し、AgentCore Runtime上で動作するAIエージェントの品質管理ライフサイクルを扱いました。
第二回である今回は、そのアーキテクチャを支える技術基盤のひとつであるAgentCore Observabilityに焦点を当てます。
AIエージェントの本番運用とObservability
AIエージェントの本番運用においては、Observabilityを初日から組み込むことが重要です。従来のWebアプリケーションであれば、リクエスト/レスポンスのレイテンシやエラー率を監視すれば概ね十分でした。
しかしAIエージェントでは、以下の特有の課題が加わります。
- 非決定的な推論過程: 同じ入力に対して、異なるツール呼出パターンや応答が生成される可能性がある
- ツール呼出の連鎖: 複数のツールを連鎖的に呼び出すため、どの段階で品質が低下したかの特定が容易でない
- LLM入出力の大容量データ: プロンプトと応答は従来のログと比べデータ量が大きく、格納・
検索に工夫が求められる
これらの課題に対応するためには、推論過程をトレースとして記録し、メトリクス・
AgentCore Observabilityの概要
Amazon Bedrock AgentCore Observabilityは、AIエージェントの動作をトレース・
OTelはCNCF(Cloud Native Computing Foundation)が策定するテレメトリ収集のオープンスタンダードで、Traces・
AgentCore Observabilityは、このOTel互換のテレメトリをAgentCoreの各コンポーネントに対して自動的に生成・
OTelの仕様では、OTel SDKをベースにベンダー固有の拡張を付加したものをDistro
本記事のスコープ
本記事では、AgentCore Observabilityの中でもRuntimeのゼロコード計装に焦点を当てます。また検証では、本番運用におけるIaC(Infrastructure as Code)の標準的な選択肢の一つであるAWS CDK for TypeScriptを用います。検証を通じて、ゼロコード計装の内部的な仕組みを本番運用視点を交えて深掘りします。
ゼロコード計装とは
前節で触れた通り、AgentCore Observabilityはテレメトリの収集基盤にOTelを、送信にADOTを用いています。本節では、OTelが提供する2つの計装アプローチを整理した上で、AgentCore Runtimeのゼロコード計装がこれらとどのような関係にあるのかを明らかにします。
OTelにおける2つの計装アプローチ
OTelは、テレメトリを取得するためのアプローチとしてコードベース計装とゼロコード計装の2つを提供しています[2]。
コードベース計装は、開発者がアプリケーションのソースコードにOTel APIを直接記述する方式です。OTel公式ドキュメントに基づくと、概ね以下の作業が必要になります。
- OTel SDK
(またはADOT等のDistro) のインストール - アプリケーションコードへの計装
(TracerProviderの初期化、スパンの生成、メトリクスの記録など — OTel APIを使ったコード記述) - Exporterの送信先をはじめとする環境変数やSDKの設定
- (Collectorを経由する場合)
Collectorの構築・ 設定ファイルの管理
上記のうち、最も開発負担が大きいのは2.のアプリケーションコードへの計装です。各処理にスパンを手動で挿入し、適切な属性を付与し、エラーハンドリングと組み合わせるといった作業は、アプリケーション全体にわたる継続的な取り組みとなります。
ゼロコード計装は、この負担を解消するアプローチです。OTel公式ドキュメントでは、以下のように説明されています。
"Zero-code instrumentation adds the OpenTelemetry API and SDK capabilities to your application typically as an agent or agent-like installation. The specific mechanisms involved may differ by language, ranging from bytecode manipulation, monkey patching, or eBPF to inject calls to the OpenTelemetry API and SDK into your application."
つまり、ゼロコード計装では専用のランチャーがアプリケーション起動時にOTel SDKをアプリケーションプロセスへ自動的に組み込み、HTTPクライアントやデータベースドライバ、ロギングといった領域の主要ライブラリに対してmonkey patching
AgentCore ObservabilityとOTelゼロコード計装
AgentCore Runtimeのゼロコード計装は、このOTelのゼロコード計装を基盤としています。AWS公式ドキュメントでは、AgentCoreのObservabilityを有効化する手順としてOTelのopentelemetry-instrumentコマンドの使用を案内しており、以下の様に述べています。
"Execute your agent code using the OpenTelemetry auto-instrumentation command:
opentelemetry-instrument python my_. This auto-instrumentation approach automatically adds the SDK to the Python path. You may already be using this approach as part of your standard OpenTelemetry implementation."agent. py
つまり、AgentCoreのゼロコード計装は独自の仕組みではなく、OTel標準のゼロコード計装をそのまま利用していることが公式ドキュメントから読み取れます。では、OTelのゼロコード計装のテレメトリパイプラインはどのような構成なのか、次に整理します。
OTelゼロコード計装のテレメトリパイプライン
OTelはPythonに限らずJava, Go, .NETなど多くの言語をサポートしていますが、以下では本記事の検証環境であるPythonを前提に説明します。OTelのテレメトリパイプラインは、主に以下のコンポーネントで構成されます。
| コンポーネント | 役割 | 実行場所 |
|---|---|---|
| opentelemetry-instrument | アプリケーションの起動プロセス中で実行されるPythonランチャー。アプリのソースコードを変更することなくOTel SDKを組み込み、初期化する[3] | アプリプロセス内 |
| OTel SDK, Distro | テレメトリの生成・ |
アプリプロセス内 |
| Exporter | 収集したテレメトリを外部に送信するSDKのコンポーネント。送信先は環境変数で設定される [4] | アプリプロセス内 |
| OpenTelemetry Collector | テレメトリの受信・ |
別プロセス |
ここで重要な点は2つあります。1つめは、opentelemetry-instrument・
テレメトリの送信プロトコルとして代表的なものがOTLP(OpenTelemetry Protocol)です。OTLPを用いる場合、Exporterの送信先は環境変数OTEL_で設定します[3]。シグナル毎に送信先を分ける場合は、以下の環境変数が優先的に使用されます。
- Traces:
OTEL_EXPORTER_ OTLP_ TRACES_ ENDPOINT - Metrics:
OTEL_EXPORTER_ OTLP_ METRICS_ ENDPOINT - Logs:
OTEL_EXPORTER_ OTLP_ LOGS_ ENDPOINT
OTel仕様におけるこれらの環境変数のデフォルト値はhttp://http://
AgentCore Runtimeのゼロコード計装は何をしてくれるのか
ここまでの整理を踏まえ、OTel標準のゼロコード計装と比べてAgentCore Runtimeがさらに何を自動化しているのかをまとめます。
| # | OTelゼロコード計装で開発者が行う作業 | AgentCore Runtime |
|---|---|---|
| 1 | OTel SDK |
開発者が行う |
| 2 | 環境変数の設定 | 不要 |
| 3 | opentelemetry-instrumentの起動コマンドへの追加 |
開発者が行う |
| 4 | Collectorの構築・ |
不要 |
前述の通り、コードベース計装で最も負担の大きかった
"Setting this variable (
DISABLE_) to true unsets the AgentCore runtime's default ADOT environment variables, ensuring that none of the default ADOT configurations are set."ADOT_ OBSERVABILITY=true
一方、4. Collectorの構築・
CDK for TypeScriptを用いた動作検証
ここからは、実際の動作検証を通してAgentCore Runtimeのゼロコード計装の仕組みを確認していきます。AgentCoreの実装には、前述の通りAWS CDK for TypeScriptを用いました。
検証の概要
CDK for TypeScriptからAgentCore Runtimeをデプロイする際には、AgentRuntimeArtifactクラスの5つのファクトリメソッドfromAsset, fromCodeAsset, fromEcrRepository, fromS3, fromImageUri)
本検証では、Dockerコンテナイメージを用いるfromAsset
なお、検証環境の主なコンポーネントのバージョンは以下です。
| コンポーネント | バージョン |
|---|---|
| AWS CDK CLI | v2. |
| @aws-cdk/ |
v2. |
| aws-opentelemetry-distro | v0. |
| OpenTelemetry SDK |
v1. |
| Pythonランタイム | 3. |
| リージョン | us-east-1 |
観測結果と考察
以降では、動作検証で得られた観測結果と、そこから読み解けるゼロコード計装の仕組みを併せて述べていきます。なお、考察部分は観測結果や仕様に基づく推察であり、誤っている可能性がある点、予めご理解いただけると幸いです。
1. 環境変数から読み解くテレメトリの送信構成
検証用コードにより、Runtimeが自動設定するOTel関連の環境変数を確認しました。以下の22個が観測されました。
| 環境変数 | 値 |
|---|---|
AGENT_ |
true |
AWS_ |
AWS_ |
AWS_ |
us-east-1 |
OTEL_ |
https:// |
OTEL_ |
https:// |
OTEL_ |
http/ |
OTEL_ |
aws_ |
OTEL_ |
aws_ |
OTEL_ |
xray |
OTEL_ |
baggage,xray,tracecontext |
OTEL_ |
otlp |
OTEL_ |
otlp |
OTEL_ |
parentbased_ |
OTEL_ |
true |
OTEL_ |
true |
OTEL_ |
service. |
OTEL_ |
x-aws-log-group=..., x-aws-log-stream=otel-rt-logs, ... |
OTEL_ |
5000 |
OTEL_ |
base2_ |
OTEL_ |
false |
OTEL_ |
false |
OTEL_ |
/ping |
これらの環境変数から、テレメトリの送信構成について以下の点が読み取れます。
OTEL_, OTEL_の値や、複数のOTEL_という環境変数名から、テレメトリの送信プロトコルはデフォルトでOTLPに設定されていると判断出来ます。またOTEL_の値から、OTLP ExporterがテレメトリをOTLP/OTEL_とOTEL_の値は、AWSがX-Ray及びCloudWatch Logs用に公式に提供しているOTLP受信エンドポイントでした[5]。
さらに、OTEL_の値を確認すると、CloudWatch Logsへの出力先が以下のようにHTTPヘッダーで指定されていました。
x-aws-log-group=/aws/bedrock-agentcore/runtimes/{runtimeId}-DEFAULT,
x-aws-log-stream=otel-rt-logs,
x-aws-metric-namespace=bedrock-agentcore
CloudWatch LogsのOTLPエンドポイントはx-aws-log-groupとx-aws-log-streamヘッダーで出力先のロググループ/ストリームを指定する仕様です[6]。
実際、デプロイ後のCloudWatch Logsにはotel-rt-logsruntime-logsotel-rt-logsのみです。runtime-logsはOTelパイプラインとは別にRuntimeがstdout/otel-rt-logsの出力例を以下に示します。
{
"resource": {
"attributes": {
"service.name": "obsVerifyAgent.DEFAULT",
"cloud.region": "us-east-1",
"cloud.platform": "aws_bedrock_agentcore",
"telemetry.sdk.version": "1.39.1",
"telemetry.auto.version": "0.15.0-aws"
}
},
"severityText": "INFO",
"body": "AGENT_OBSERVABILITY_ENABLED = true",
"traceId": "69aecfdf01797dd1421693173ddf2bd5",
"spanId": "0cd510dfab4d8935"
}
AIエージェントのコードでは標準ライブラリのlogging.を呼んでいるだけですが、テレメトリの発信元を識別するためのResource Attributesresource.)traceIdとspanId)
2. コンテナ内部の構成
AgentCore Runtimeコンテナ内の稼働中プロセスを確認したところ、python main./procディレクトリを走査したところ、Collectorプロセスは見つかりませんでした。さらにファイルシステム上でCollector設定ファイルを検索しましたが/etc/, /opt/, /opt/等)、こちらも見つかりませんでした。
また、Collectorが別プロセスではなくライブラリとして組み込まれている可能性を検証するためsys.を確認したところ、215個のOTel関連モジュールがロードされていましたが、いずれもSDKやExporter、計装のライブラリであり、Collector関連のモジュールは含まれていませんでした。
以上を踏まえると — Exporterの送信先がAWSのOTLPエンドポイントを直接指している点、コンテナ内にCollectorプロセスもライブラリも存在しない点から — AgentCore Runtimeのゼロコード計装は、TracesとLogsに関してCollectorレス構成で動作していると推察されます。ADOT SDKもこのCollectorレス構成をサポートしています[7]。
3. Metricsシグナルの経路
前節の環境変数には、OTEL_とOTEL_は設定されていましたが、OTEL_は設定されていませんでした。汎用のOTEL_も未設定のため、OTel仕様に従いMetricsの送信先はデフォルト値http://)
これは、AgentCore RuntimeのMetricsがOTelパイプラインとは別の経路で提供される設計であることに起因すると考えられます。AWS公式ドキュメント[8]によると、Invocations, Latency, SessionCountなどのセッションメトリクスやCPU/
4. opentelemetry-instrumentの役割
opentelemetry-instrumentがテレメトリ生成にどのような役割を果たすのかを検証するために、fromCodeAssetの構成でentrypointからopentelemetry-instrumentのみを除外してデプロイしました。
// CDK スタック(TypeScript)— opentelemetry-instrument を省略
const runtime = new AgentRuntime(this, 'Runtime', {
// ...
artifact: AgentRuntimeArtifact.fromCodeAsset({
// ...
entrypoint: ['main.py'], // ← opentelemetry-instrument なし
}),
});
結果は以下の通りでした。
- Runtimeが自動設定した環境変数: 同一
- ログストリーム
runtime-logs: 同一 - ログストリーム
otel-rt-logs: ストリームは作成されたが、イベントは一切記録されなかった
opentelemetry-instrumentを省略しても環境変数は注入されるが、テレメトリは予想通り生成されませんでした。一方、runtime-logsは変わらずstdoutをキャプチャしていたことから、runtime-logsはOTelとは無関係にRuntimeがstdout/opentelemetry-instrumentによるSDKの初期化と計装が不可欠であることを示しています。
以上を踏まえた全体像
ここまでの検証結果と考察を踏まえ、AgentCore Runtimeのゼロコード計装の全体像を2つの視点で整理します。
テレメトリ送信のアーキテクチャ
検証結果を踏まえたAgentCore Runtimeのゼロコード計装の全体像を、以下のアーキテクチャ図に示します。
なお、ユーザーのDockerコンテナ外
第一に、Exporterの送信先はAWSのOTLPエンドポイントを直接指しており(前述1.)、Collectorへのルーティングを示す設定は存在しません。
第二に、コンテナ内にCollectorのプロセス・
第三に、送信先のX-RayとCloudWatch LogsはいずれもOTLPをネイティブに受け付けるため(前述1.)、Collectorによるプロトコル変換やフォーマット変換を挟む技術的な必要性はありません。
ゼロコード計装の3層構造
以上を整理すると、AgentCore Runtimeのゼロコード計装は3つの層で構成されていると捉えることが出来ます。なお、これは執筆時点における筆者の解釈であり、AWSが公式に定義しているものではない点、ご注意下さい。
層1
層2opentelemetry-instrumentを省略した場合、層1の環境変数が注入されるにもかかわらずotel-rt-logsが空でした。これは、層2が層1と層3を橋渡しする役割を果たしていることを示しています。
層3logging.を呼ぶだけで、層2のopentelemetry-instrumentがPythonのロガーをモンキーパッチしているため、Resource AttributesとTrace Contextが付与されたOTelログに自動変換されます。
また、OTelのゼロコード計装はboto3等の主要ライブラリも自動計装の対象としており、Bedrock API呼出がスパンとして記録されることが期待されます。これが
本番運用の観点では、各層の管理責務を明確にしておくことが重要です。
層1は完全マネージドのため、障害時にはAWS側への問い合わせが必要です。
層2は開発者が管理するため、ADOTのバージョンアップやopentelemetry-instrumentの設定変更は開発チームの責務になります。
層3はOTelコードが不要である反面、ロガーのモンキーパッチによりlogging.の出力形式が変わるため、既存のログ解析パイプラインがある場合は影響を確認する必要があります。
本番運用時の注意事項
検証結果と考察を踏まえると、ゼロコード計装の利便性の裏側には、コスト・
コストへの影響: サンプリング率とログの二重出力
検証で確認した環境変数OTEL_は、全トレースを収集する設定です[8]。これは検証や開発時には便利ですが、全てのリクエストがトレースとしてX-Rayに送信されるため、高トラフィックの本番環境ではX-RayとCloudWatchのコストが増大する可能性があると思われます。当該記事の検証では、Runtimeが設定するこの値をCDKの環境変数設定等で上書きできるか否か、また上書きした場合の動作については確認していません。デフォルトのまま利用する場合、コスト規模の事前見積もりが重要となります。
また、runtime-logsotel-rt-logslogging.の呼出は、stdoutへの出力
運用フロー: ADOTのバージョン管理
層1の環境変数はRuntime側が設定するため、Runtimeのアップデートによって新しい環境変数が追加されたり、値が変更されたりする可能性があります。層2のADOTバージョンがその変更に対応していない場合、テレメトリの動作が変わる可能性があります。プロジェクト事情に伴いCDK側でADOTのバージョンを固定している場合は、Runtimeの更新時に互換性を確認する運用フローが必要になる可能性があると思われます。
信頼性: ネットワーク障害時のテレメトリ損失
検証で推察した通り、AgentCore Runtimeのゼロコード計装はCollectorレス構成で動作していると見受けられます。この場合、Collectorが担うバッファリングの仕組みが無いため、ネットワーク障害が発生した際のテレメトリ損失への耐性はADOT SDKのエクスポーター実装に依存します。テレメトリの欠損が許容できない場合は、エクスポーターのタイムアウト値OTEL_)
参考文献
おわりに
本記事では、まずOTelのゼロコード計装の仕組みを整理し、AgentCore Runtimeがその上に何を自動化しているのかを位置付けた上で、CDK for TypeScriptによる検証を通じて実際の動作を確認しました。
観測結果と考察から、テレメトリ送信はCollectorレス構成でAWSのOTLPエンドポイントへ直接送信されるアーキテクチャであり、ゼロコード計装全体はRuntime
また、内部の仕組みを理解することで見えてきた、サンプリング率やログの二重出力、ADOTのバージョン管理といった本番運用時の注意事項についても整理しました。
第3回では、AgentCore利用時の GRC・
