Amazon Bedrock AgentCore、任意のエージェントフレームワークの評価機能を公開
本文の状態
日本語全文を表示中
詳細モードで約19分の本文を読めます。
同じ出来事の情報源
この情報源を基点に整理
AWS Machine Learning Blog
AWS は、生産環境向けエージェント構築における評価ツールの不足に対処するため、特定の SDK や LLM クライアントに依存しない汎用的な評価パイプラインを提供する Amazon Bedrock AgentCore Evaluation。
AI深層分析を開く2026年8月27日 04:52
AI深層分析
キーポイント
評価ツールの非対称性解消
従来の評価システムは特定の SDK やモデルに依存していたが、新機能はフレームワーク固有の制約から解放され、多様な開発環境に対応する。
OpenTelemetry の標準化活用
主要なエージェントフレームワークが OpenTelemetry をサポートしているため、テレメトリデータが流れる限り SDK に依存せず評価が可能になる。
インフラの一元管理
Amazon Bedrock AgentCore runtime がホスティング、スケーリング、メモリ管理、観測性の基盤を提供し、プロジェクトごとの再構築を不要にする。
評価に必要な3つのスパン役割
セッションの再構築とスコアリングには、インボークエージェント、推論、ツール実行の3種類のスパンが必須である。これらはそれぞれユーザー入出力、モデル呼び出し履歴、およびツールの実行結果を保持する。
拡張性のあるスパン処理
検索やガードレールなどの追加コンテキストを持つリッチなトレースも特別設定なしで処理可能である。未知のスパン種別はエラーではなく無視されるため、将来の規格変更にも対応できる。
重要な引用
Most evaluation systems assume you built your agent in a specific way: a specific SDK, a specific large language model (LLM) client, a specific tracing pattern.
Amazon Bedrock AgentCore evaluations solves this fragmentation by decoupling evaluation from the framework choice.
The service classifies every span it receives, reads the values it needs from these three roles, and passes over the rest.
As frameworks and the conventions add new span kinds over time, this stays forward-compatible: an unfamiliar span kind is context the service skips, not an error.
編集コメントを表示
編集コメント
エージェント開発の成熟に伴い、フレームワークの多様化と評価基準の統一は不可欠な課題であった。AWS が OpenTelemetry を軸にこの問題を解決したことは、業界全体の標準化を加速させる重要な転換点となる。
Source Article
元記事を日本語で読む
本文に関係しない購読案内、埋め込み通知、サイト内プロモーションは除いています。
AI チームが生産環境向けのエージェントを構築する際、ある frustrating な非対称性に直面します。エージェントフレームワークの多様性は拡大し続ける一方で、評価ツールの進化は追いついていないのです。
多くの評価システムは、特定の SDK や LLM クライアント、あるいは特定のトレーシングパターンを用いてエージェントが構築されていることを前提としています。その狭い互換性領域から一歩外れると、評価パイプラインは機能しなくなります。
チームは、ワークフローのオーケストレーションモデルを重視して LangGraph を選び、検索パイプラインとの密接な連携を求めて LlamaIndex を採用します。組織で GPT モデルを標準化している場合は OpenAI Agents SDK を使い、複数エージェント間の調整には Google ADK を、Anthropic のネイティブ機能を活用したい場合には Claude Agent SDK を選択します。また、Strands Agents はモデル駆動型のループを採用しており、Amazon Bedrock AgentCore 上で動作するエージェントを数日ではなく数分で立ち上げられるため、ここを選ぶケースも増えています。
そして近年では、これらのフレームワークを Amazon Bedrock AgentCore runtime 上に展開することが一般的になっています。これは Amazon Bedrock AgentCore の機能の一つであり、各プロジェクトで個別に再構築する必要があったホスティング、スケーリング、メモリ管理、観測性のインフラを一元化して提供します。
Amazon Bedrock AgentCore の評価機能は、この断片化問題を解消するために、評価プロセスを特定のフレームワークから切り離すことで実現しています。主要なフレームワークのほとんどは、ネイティブ対応またはコミュニティ製のインストルメンテーションライブラリを通じて OpenTelemetry をサポートしています。エージェントのテレメトリが OpenTelemetry を経由して流れていれば、その背後にある SDK が何であれ、評価サービスはそのパフォーマンスをスコアリングできます。
本記事では、この仕組みの詳細について解説します。具体的には、サービスが読み取るテレメトリの種類、スパンを読み取るための判断基準、評価データを保持する属性、そしてリストにないフレームワークへの対応範囲などです。
OpenTelemetry を共通言語として
OpenTelemetry はベンダー中立のインストルメンテーションフレームワークであり、分散システムがトレース、メトリクス、ログをどのように発行するかを標準化しています。トレースはスパンからなるツリー構造で、各スパンはリクエスト内の単一のステップを表します。これは名前、タイムスタンプ、一連の型付き属性、およびオプションのスパンイベントを持つ作業の単位です。スパンは OpenTelemetry Protocol (OTLP) を経由してエクスポートされ、テレメトリバックエンドに収集されます。AgentCore ランタイムでは、このバックエンドが AWS Distro for OpenTelemetry (ADOT) であり、スパンとイベントレコードを Amazon CloudWatch にルーティングします。
エージェントの実行では、多様な作業を処理するため、多数種類のスパンが生成されます。1 つのユーザー操作(ターン)でも、モデル呼び出しやツール呼び出し、ベクトルストアやデータベースからの文書検索、取得結果の再ランク付け、埋め込み生成、ガードレールチェック、プロンプトテンプレートのレンダリング、メモリへの読み書き、そしてこれらを統合するオーケストレーションステップなど、さまざまなスパンが発生します。
2 つの規約では、これらの概念を明確に定義しています。OpenTelemetry GenAI 規約 では、chat や embeddings といった操作が具体的に規定されています。
検索、ツール実行、エージェントの呼び出し、エージェント作成、プランニング、そして一連のメモリ操作です。 (原文の技術表記: retrieval、execute_tool、invoke_agent、create_agent、plan)
OpenInference(https://github.com/Arize-ai/openinference)では、LLM、TOOL、RETRIEVER、RERANKER、EMBEDDING、AGENT といったスパンの種別を定義しています。 (原文の技術表記: LLM、TOOL、RETRIEVER、RERANKER、EMBEDDING、AGENT)
「CHAIN」「GUARDRAIL」「EVALUATOR」、そして「PROMPT」。
これらは、Amazon Bedrock AgentCore の評価機能において重要な要素です。
本番環境のトレースでは、通常これらが複数混在します。
この完全なセットから、評価サービスはセッション内で何が起こったかを再構築し、スコアリングするために 3 つのスパン役割が必要です。
「エージェント呼び出しスパン」は、会話におけるユーザーの1ターンに相当する最上位のリクエスト・レスポンスサイクルを表します。これには、ユーザーからのプロンプトと、最終的なエージェントからの応答が含まれます。
「推論スパン」は、モデルへの個別の呼び出しをそれぞれ表し、各スパンにはモデルに渡されたメッセージ履歴と、モデルからの返信が格納されます。
エージェントが呼び出した各ツールを表す「ツールスパン」には、ツールの名前、入力パラメータ、および結果が含まれます。
評価サービスが対象とするのは、以下の 3 つの要素です。このサービスは受信したすべてのスパンを分類し、必要な値をこれら 3 つの役割から読み取り、それ以外の部分はそのまま通過させます。検索(retrieval)、再ランク付け(reranking)、ガードレール、あるいはメモリ関連のスパンを含むより詳細なトレースも、特別な設定なしで処理可能です。これらの追加スパンは単に評価サービスが不要とする文脈情報を提供しているだけです。今後、フレームワークや慣習によって新しいスパン種別が追加されても、この仕組みは将来互換性を保ちます。未知のスパン種別はエラーではなく、サービスがスキップする文脈情報として扱われます。
Session (one runtimeSessionId)
└── Trace (one user turn, one trace_id)
├── invoke agent span ← read: user prompt + final agent response
├── inference span ← read: messages to model + model reply
├── execute tool span ← read: tool name + parameters + result
├── retriever span (context; not required by evaluators)
├── inference span ← read: next model call with tool result in history
└── ... (guardrail, memory, reranker, orchestration spans, and more)このサービスは、3 つの指定された役割を持つスパンを読み取り、それ以外のスパンを追加の文脈として扱います。
異なるフレームワークや計測ライブラリでは、これら 3 つの役割を記録する際に、属性名、ネスト構造、スパン命名規則がそれぞれ異なります。OpenTelemetry GenAI のセマンティック・コベントションズと OpenInference 仕様は、いずれもこの 3 つのスパン役割を記録するためのスキーマを定義していますが、使用する属性キーやスパン種別の用語体系は異なります。AgentCore Evaluations は、これらの異なるスキーマを統一された結果へと橋渡しします。
AgentCore Evaluations がトレースを読み取る仕組み
評価を実行する際(オンデマンドまたはオンライン評価設定を通じて)、サービスは CloudWatch からエージェントのスパンとイベントレコードを取得し、セッションを再構築します。セッションは session.id によってグループ化されます。その中で、各トレース(1 つの trace_id)が 1 ユーザーターンに相当します。すべてのターンは、前述した 3 つのスパン種別で構成されています。
このサービスは各スパンを分類し、必要な値を抽出して再構築されたセッションを評価者に渡します。これ以降の評価はフレームワークに依存しないものとなり、同じ評価基準(GoalSuccessRate、Correctness、Helpfulness、およびカスタム LLM-as-a-judge)がすべてのフレームワークに対して一貫して適用されます。この仕組みを図示すると以下のようになります。

図 1: AgentCore Runtime から Amazon CloudWatch を経由し、AgentCore Evaluations へ至るデータフロー
これらを設定する必要はありません。すべての OpenTelemetry インストルメンテーションライブラリは、生成するスパンやイベントレコードに scope.name という値を付与します。評価サービスはこの値を用いて読み取り方を決定します。適切な処理は、インストール済みのインストルメンテーションパッケージから自動的に有効化され、エージェント側のコードを変更する必要はありません。各サポート対象フレームワークとその対応する scope.name は、「サポート対象のエージェントフレームワーク」ドキュメントに記載されています。現時点では Strands Agents、LangGraph、OpenAI Agents SDK、LlamaIndex、Google ADK、Claude Agent SDK がカバーされており、これらには OpenTelemetry と OpenInference の両方のインストルメンテーションが提供されています。
対応範囲は特定のフレームワークに限定されません。OpenTelemetry GenAI 意味規約に従い、スコープ名が opentelemetry.instrumentation.* の下に属するライブラリや、OpenInference 仕様に従う openinference.instrumentation.* のいずれかに該当するものは、すべて汎用的なパスを通じて読み込まれます。実務上、新しいフレームワークへの対応は、通常、互換性のあるインストルメンテーションパッケージをインストールするだけで済みます。スコープ名のプレフィックスこそが、ライブラリが参加するかどうかを決める鍵です。例えば mycompany.agent.tracing という名前のスコープは、そのスパンが規約に完全に準拠していても、検出されることはありません。
プレフィックスは、インストルメンテーション作成者が文書化されたスキーマに意図的に準拠したことを示すシグナルです。
セッションをエンドツーエンドで評価するには、2 つの要件を満たす必要があります。第一にグループ化です。エージェントのスパンには、呼び出し時に指定した runtimeSessionId と一致する session.id 属性を含める必要があります。この属性こそが、サービス側でスパンをトレースに、さらにトレースをセッションとして組み立てる鍵となります。
AgentCore ランタイム上では、ADOT が自動的にこの属性を注入するため、エージェント側のコード変更は不要です。
2 番目の要件として、データソースにはスパンだけでなくメッセージ内容も含まれている必要があります。統一型観測可能性(新規作成されたエージェントのデフォルト設定)に対応するエージェントの場合、この要件は自動的に満たされます。メッセージ内容はスパンと同じエージェントごとのロググループに格納されるため、単一のロググループで十分です。
一方、まだ統一前構成を実行している既存のエージェントでは、スパンは共有の aws/spans ロググループに格納されます。メッセージ内容は、エージェントのロググループ内で相関イベントレコードとして別々に保存されています。
この設定では、データソースが aws/spans のみをカバーしている場合、スパンの分類は成功しますが、メッセージの内容は空として返され、応答品質を評価するすべての評価器でエラーが発生します。
OpenTelemetry GenAI 意味論的規約:評価を駆動する属性
OpenTelemetry GenAI の意味論的規約(semantic conventions)は、LLM フレームワークによって生成されるスパンのためのスキーマを定義しています。AgentCore Evaluations は、これらの属性のうち特定のサブセットを読み取り、スパンの分類と評価データの抽出を行います。評価のデバッグやカスタム計装(instrumentation)の作成において、どの属性にデータが含まれているかを知っておくことは非常に有用です。
スパンの分類は gen_ai.operation.name から始まります:
「invoke_agent」は、ユーザーのプロンプトと最終レスポンスを保持する、1ターンごとの最上位スパンであるインボークエージェントのスパンを示します。
chatは推論スパンを示します。サービスはメッセージ履歴とモデルの応答を読み取ります。
execute_toolはツール実行スパンを示します。サービスはツールの名前、入力パラメータ、および結果を読み取ります。
gen_ai.operation.name が存在しない場合(LlamaIndex のトレースでは一般的)、サービスは traceloop.span.kind にフォールバックします。ここで、workflow はエージェントの呼び出しに対応します。
span、ツール実行を示す tool スパン、および推論を示す llm スパン。
ツールの識別には gen_ai.tool.name が用いられ、gen_ai.tool.call.id は推論スパンでリクエストされたツール呼び出しと、対応する実行ツールスパンでの結果を結びつける相関 ID として機能します。また、推論スパンに含まれる gen_ai.tool.definitions 属性には、ツールのスキーマを格納した JSON 配列がエンコードされており、GoalSuccessRate エバルエータはこの情報を用いて、エージェントが実際に呼び出したツールが、事前に宣言された利用可能なツールの範囲内にあるかを確認します。
テレメトリの収集方法によって、メッセージの内容は 2 つの場所のいずれかに格納されます。テレメトリが分割されている場合、その内容は相関イベントレコード本体(body.input.messages および body.output.messages)に含まれます。
分割されない場合、コンテンツは gen_ai.input.messages や gen_ai.output.messages 属性、あるいはインラインのスパンイベントとしてスパン上に保持されます。サービスはコンテンツが格納されている場所から読み取るため、特定のデプロイメントがどのパスをたどったかを知る必要はありません。
コンテンツの所在を包括的に把握するには、スパン(Spans)、イベント記録、テレメトリ信号を確認してください。
OpenInference 規約:代替となるセマンティックレイヤー
OpenInference は Arize AI が維持するオープンな仕様であり、LlamaIndex、Haystack、Phoenix のエコシステムで広く採用されています。これは LLM(大規模言語モデル)の操作を記述する際に、OpenTelemetry GenAI 規約とは異なる属性名を使用します。
OpenAI Agents SDK(openinference-instrumentation-openai-agents)、Google ADK、Claude Agent SDK など、いくつかのフレームワークは OpenInference スパンを生成します。
OpenInference におけるスパン分類は、openinference.span.kind を用いて行われます。ここで指定できる値には、推論を表す LLM、ツールの実行を表す TOOL、エージェントの動作を表す AGENT、そしてチェーン処理を表す CHAIN があります。
エージェントの呼び出しと、構造化コンテナのスパンをそれぞれ行います。
推論スパンのメッセージ内容は、フラットでインデックス付きのアトリビュート規約に従います。入力メッセージは、llm.input_messages.{i}.message.role および llm.input_messages.{i}.message.content というパターンに従い、i は 0 から始まり、各メッセージごとに増分されます。
過去にさかのぼると、ツール結果メッセージには、対応するツールの呼び出しとリンクするための追加情報として llm.input_messages.{i}.message.tool_call_id が含まれています。
出力メッセージも、ツール呼び出しをさらにネストした同じインデックスパターンに従います。
llm.output_messages.0.message.role = "assistant"
llm.output_messages.0.message.tool_calls.0.tool_call.function.name = "get_pto_balance"
llm.output_messages.0.message.tool_calls.0.tool_call.function.arguments = "{\"employee_id\":\"EMP-001\"}"
llm.output_messages.0.message.tool_calls.0.tool_call.id = "call_abc123"推論スパンにおけるツールスキーマは、llm.tools.{i}.tool.json_schema を使用します。各値は、単純な関数スキーマまたは OpenAI 形式の {"type": "function", "function": {...}} ラッパーをエンコードした JSON 文字列です。
このサービスは両方に対応しており、name、description、parameters フィールドを読み取ります。
ツール実行のスパンでは、3 つの属性を使用します。ID には tool.name を、パラメータには input.value を使用します(複数引数を持つツールの場合は JSON エンコードされたオブジェクトを、単一引数のツールの場合はプレーンな文字列を指定)。結果は output.value に格納されます。
OpenInference 計測ライブラリのバージョンごとに output.value の形式は進化しており、サービス側では新旧両方の形状を読み込むよう対応しているため、特定のバージョンに縛られる必要はありません。
特定のバージョンについて。
任意の準拠フレームワークの評価
上記で名指しされたフレームワークは直接対象となりますが、設計上あえて汎用的な構造となっています。リストに含まれないフレームワークであっても、計測手法が文書化された規約に従っていれば、前述した2つの一般的なパスによって広範なカバレッジを得ることができます。
OpenInference パスでは、openinference.instrumentation.* の下のすべてのスコープが処理されます。このパスは、openinference.span.kind によってスパンを分類し、インデックスされた llm.input_messages から推論コンテンツを読み取ります。
llm.output_messages 属性を読み取り、ツールスパンについては tool.name、input.value、output.value を参照します。
OpenInference 仕様に準拠する主要なフレームワーク、およびその名称が明示された後にリリースされたものも含まれます。
- OpenTelemetry パスは、
opentelemetry.instrumentation.*の下位スコープすべてを処理します。このパスでは、gen_ai.operation.nameを用いてスパンを分類し、イベントレコード本体またはスパンからメッセージコンテンツを読み取り、ツール識別にはgen_ai.tool.nameを使用します。
スコープ名のプレフィックスは、ライブラリをこれらのパスのいずれかにルーティングする役割を果たします。汎用的に評価されるべきカスタム計装コードを開発するチームにとっては、opentelemetry.instrumentation.* または openinference.instrumentation.* の下にスコープ名を定義することが、参加するための適切な方法です。
エージェントコードから評価スコアへ:ウォークスルー
具体例として、AgentCore サンプルリポジトリ では、OpenAI Agents SDK、Google ADK、LlamaIndex、Claude Agent SDK をそれぞれ使用して構築された HR アシスタントの完全な動作サンプルが提供されています。これらはすべて AgentCore ランタイムにデプロイされ、組み込みおよびカスタムの評価器を用いて同じ基準で評価されます。
エージェントに明示的なコードを追加する必要はありません。AgentCore ランタイム上では、AWS Distro for OpenTelemetry (ADOT) が起動時にインストールされた計測パッケージを自動的に検出し、有効化します。OpenAI Agents SDK のサンプルの場合、requirements.txt に opentelemetry-instrumentation-openai-agents を追加するだけで準備は完了です。
LlamaIndex のサンプルでは、opentelemetry-instrumentation-llamaindex が同様の役割を果たします。OpenAI Agents SDK のエージェントが避けるべきは set_tracing_disabled(True) の呼び出しです。インストゥルメンテーションは SDK 独自のトレーシングパイプラインにフックするため、SDK のトレーシングを無効化すると評価スパンも出力されなくなります。
LlamaIndex の場合、特にエージェントの構造が重要になります。 エージェントは単なる AgentExecutor として構築するのではなく、FunctionAgent または ReActAgent(ワークフロー型エージェント)として実装する必要があります。ワークフロー型エージェントは、トランザスを追跡するためのアンカーとなるトップレベルのインボーク・スパンを出力します。これが存在しない場合、トランザスを再構築するためのトップレベルのスパンが欠落し、推論スパンのみからセッションを構成することができなくなります。
CloudWatch へのテレメトリを確実に配信するには、レスポンスを返す前に呼び出しハンドラの最後に明示的にフラッシュしてください。 AgentCore ランタイムはハンドラが戻った後に実行環境を一時停止しますが、OTel SDK はクライアント側のバッチプロセッサでテレメトリをバッファリングし、定期的なタイマーでエクスポートします。その結果、レスポンス返却時点では未エクスポートのデータがまだバッファに残っている可能性があり、一時停止前にエクスポートが完了する保証はありません。実際には、フラッシュを省略したことに起因するテレメトリの欠落が、評価失敗の最も一般的な原因となっています。OpenAI Agents SDK と LlamaIndex のサンプルでは、以下のパターンでこの対策を実装しています。
def _flush_telemetry():
from opentelemetry import trace as _trace
from opentelemetry._logs import get_logger_provider as _get_lp
for provider in (_trace.get_tracer_provider(), _get_lp()):
flush = getattr(provider, "force_flush", None)
if flush:
flush()
@app.entrypoint
async def invoke(payload, context):
prompt = payload.get("prompt", "")
try:
result = await run_agent(prompt)
finally:
_flush_telemetry()
return str(result)フラッシュ処理は、トレースプロバイダー(スパン)とロガープロバイダー(イベントレコード)の両方を対象とする必要があります。スパンとイベントレコードはそれぞれ独立したクライアント側のバッチプロセッサを経由するため、片方だけをフラッシュしてももう一方のバッファには影響が及びません。
AgentCore Evaluations は、2 つのフレームワークに対して EvaluationClient を同じように使用します。
関連記事
今日のまとめ
AIデイリーブリーフで今日の重要ニュースをまとめ読み