翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
AgentCore 評価の LangGraph テレメトリを設定する
このページでは、LangGraph エージェントを計測する方法、スパンの識別方法、評価フィールドの抽出方法について説明します。AgentCore Evaluations は、Python と TypeScript に組み込まれた LangGraph エージェントをサポートしています。このページでは、Python エージェントサポートと TypeScript エージェントサポートの各言語を個別に説明します。LangGraph エージェントを確実に評価できるように、LangGraph エージェントを構造化するためのベストプラクティスで終了します。
トピック
Python エージェントのサポート
Python LangGraph エージェントは、スコープ名 opentelemetry.instrumentation.langchain (OpenTelemetry) または openinference.instrumentation.langchain (OpenInference) でスパンを出力します。
エージェントを計測する
OpenTelemetry (opentelemetry-instrumentation-langchain) または OpenInference () の 2 つの計測ライブラリのいずれかを使用して、LangGraph エージェントを計測できますopeninference-instrumentation-langchain。Amazon Bedrock AgentCore Evaluations は両方のライブラリをサポートしています。ライブラリは異なるスコープ名を出力し、異なるスパン属性を使用します。評価サービスは、それぞれから同じ値を抽出します。
Amazon Bedrock AgentCore ランタイムなど、エージェントが AWS Distro for OpenTelemetry (ADOT) で実行されている場合、明示的な計測コードを追加する必要はありません。計測ライブラリをプロジェクトの依存関係に追加するだけで十分です。ADOT は起動時に検出し、自動的にアクティブ化します。
依存関係に必要なパスの計測ライブラリを追加します。次の例では、最小バージョンを固定します。固定する理由がない限り、利用可能な最新バージョンを使用します。
例
- OpenTelemetry
-
注: バージョン 0.55.0 以降を使用します。バージョン 0.55.0 では、評価サービスが依存する GitHub ウェブサイトに、新しい OpenTelemetry 生成 AI エージェントスパン規則のサポートが追加されました。
opentelemetry-instrumentation-langchain を依存関係に追加します。出力されるスコープ名は ですopentelemetry.instrumentation.langchain。
requirements.txt:
opentelemetry-instrumentation-langchain>=0.55.0
pyproject.toml:
[project]
dependencies = [
"opentelemetry-instrumentation-langchain>=0.55.0",
]
- OpenInference
-
openinference-instrumentation-langchain を依存関係に追加します。出力されるスコープ名は ですopeninference.instrumentation.langchain。
requirements.txt:
openinference-instrumentation-langchain>=0.1.62
pyproject.toml:
[project]
dependencies = [
"openinference-instrumentation-langchain>=0.1.62",
]
計測は、オブザーバビリティを設定する 1 つのステップです。評価のためにテレメトリをエクスポートするには、「オブザーバビリティの設定」で完全なセットアップを完了します。
スパンの識別方法
スパンの分類に使用される属性は、2 つの計測ライブラリ間で異なります。
例
- OpenTelemetry
-
OpenTelemetry 計測ライブラリは traceloop.span.kind 属性を使用してスパンを分類し、最新バージョンでは も設定しますgen_ai.operation.name。
| スパンタイプ |
属性の識別 |
|
エージェントを呼び出す
|
traceloop.span.kind = workflow ( も gen_ai.operation.name = invoke_agent)
|
|
実行ツール
|
traceloop.span.kind = tool ( も gen_ai.operation.name = execute_tool)
|
|
推測
|
gen_ai.operation.name = chat
|
- OpenInference
-
OpenInference 計測ライブラリは、 openinference.span.kind 属性を使用してスパンを分類します。
| スパンタイプ |
属性の識別 |
|
エージェントを呼び出す
|
openinference.span.kind = CHAINまたは AGENT
|
|
実行ツール
|
openinference.span.kind = TOOL
|
|
推測
|
openinference.span.kind = LLM
|
呼び出しエージェントスパンの場合、入力と出力にはメッセージごとのクリーンリストは含まれません。代わりに、コンテンツはシリアル化された LangChain グラフ状態、つまり完全な状態をラップする JSON 文字列です。このシリアル化された状態の正確な形状は、2 つの計測ライブラリ間で異なります。どちらの場合も、サービスはそれを解析してユーザープロンプト (ヒューマンメッセージ) とエージェントのレスポンス (AI メッセージ) を検索します。
LangGraph は、メッセージロールを複数の形式でシリアル化します。ロールは、小文字の値 (human、ai、tool) または LangChain メッセージクラス名 (HumanMessage、AIMessage、) として表示できますToolMessage。サービスは両方のフォームを認識します。
このコンテンツの場所は、テレメトリの収集方法によって異なります。どちらの場合も、識別属性 (traceloop.span.kind または openinference.span.kind) はスパン上にあります。詳細については、「テレメトリのセットアップと配信」を参照してください。
分割テレメトリでは、サービスは各スパンに相関するイベントレコードからコンテンツを読み取ります。
詳細については、「分割テレメトリのスパンの例」を参照してください。
統合テレメトリでは、同じコンテンツが属性と同じスパンに残ります。属性は、計測ライブラリによって異なります。
-
OpenTelemetry:
-
OpenInference:
詳細については、「統合テレメトリでのスパンの例」を参照してください。
分割テレメトリのスパンの例
分割テレメトリでは、スパンは識別属性を保持し、コンテンツは相関イベントレコードに存在します。次の例は、Amazon Bedrock AgentCore ランタイムにデプロイされた Python LangGraph の旅行計画エージェントからのものです。各計測ライブラリの下に同じエージェントが表示されます。
これらの例は完全なスパンではありません。実際のエージェントインタラクションからの代表的なデータが表示され、読みやすいように一部のフィールドは省略され、長い値は切り捨てられます。
OpenTelemetry
例
- Invoke agent span
-
traceloop.span.kind 属性 (workflow) は、これを呼び出しエージェントのスパンとして識別します。最近のライブラリバージョンも gen_ai.operation.name = に設定されていますinvoke_agent。
{
"traceId": "6a01eef11066751d68f90def0da1f80a",
"spanId": "ba1833fa7f097041",
"parentSpanId": "836a5ccf9a2186cc",
"name": "travel_agent.workflow",
"kind": "INTERNAL",
"scope": {
"name": "opentelemetry.instrumentation.langchain",
"version": "0.60.0"
},
"startTimeUnixNano": 1778511607308521744,
"endTimeUnixNano": 1778511610930280395,
"durationNano": 3621758651,
"attributes": {
"traceloop.span.kind": "workflow",
"gen_ai.operation.name": "invoke_agent",
"gen_ai.agent.name": "travel_agent",
"gen_ai.provider.name": "langgraph",
"traceloop.workflow.name": "travel_agent",
"session.id": "sea-nyc-trip-2-turns-adot_v17_opentelemetry_0_60_0"
},
"status": {
"code": "OK"
}
}
相関イベントレコードは会話を保持します。各メッセージの contentは、シリアル化された LangChain グラフの状態です。入力は 状態を inputsキーにラップします。出力は、各メッセージを LangChain コンストラクタオブジェクトとして outputsキーにラップします。ユーザープロンプトは人間のメッセージで、エージェントのレスポンスはそのシリアル化された状態内の AI メッセージです。
{
"spanId": "ba1833fa7f097041",
"traceId": "6a01eef11066751d68f90def0da1f80a",
"scope": {
"name": "opentelemetry.instrumentation.langchain"
},
"body": {
"input": {
"messages": [
{
"content": "{\"inputs\": {\"messages\": [{\"role\": \"user\", \"content\": \"Hey, how can you help me\"}]}, \"tags\": [], \"metadata\": {\"ls_integration\": \"langchain_create_agent\", \"lc_agent_name\": \"travel_agent\", \"thread_id\": \"sea-nyc-trip-2-turns-adot_v17_opentelemetry_0_60_0\"}, \"kwargs\": {\"name\": \"travel_agent\"}}",
"role": "user"
}
]
},
"output": {
"messages": [
{
"content": "{\"outputs\": {\"messages\": [{\"lc\": 1, \"type\": \"constructor\", \"id\": [\"langchain\", \"schema\", \"messages\", \"HumanMessage\"], \"kwargs\": {\"content\": \"Hey, how can you help me\", \"type\": \"human\", \"id\": \"12345678-1234-1234-1234-123456789012\"}}, {\"lc\": 1, \"type\": \"constructor\", \"id\": [\"langchain\", \"schema\", \"messages\", \"AIMessage\"], \"kwargs\": {\"content\": \"Hello! I'm your travel planning assistant ...\", \"type\": \"ai\"}}]}, \"kwargs\": {\"tags\": []}}",
"role": "assistant"
}
]
}
}
}
- Execute tool span
-
traceloop.span.kind 属性 (tool) は、これを実行ツールスパンとして識別します。 はツール名 と gen_ai.operation.name = gen_ai.tool.nameを保持しますexecute_tool。
{
"traceId": "6a01eefa5c52f3d86a35038f35f5ba30",
"spanId": "5b332f3cd15ace04",
"parentSpanId": "922a21edc04eba29",
"name": "execute_tool search_flights",
"kind": "INTERNAL",
"scope": {
"name": "opentelemetry.instrumentation.langchain",
"version": "0.60.0"
},
"startTimeUnixNano": 1778511614892698232,
"endTimeUnixNano": 1778511614893399618,
"durationNano": 701386,
"attributes": {
"traceloop.span.kind": "tool",
"gen_ai.operation.name": "execute_tool",
"gen_ai.tool.name": "search_flights",
"gen_ai.tool.type": "function",
"gen_ai.tool.description": "Search for available flights between cities.",
"gen_ai.provider.name": "langgraph",
"traceloop.workflow.name": "travel_agent",
"session.id": "sea-nyc-trip-2-turns-adot_v17_opentelemetry_0_60_0"
},
"status": {
"code": "OK"
}
}
相関イベントレコードには、ツールの入力 (引数) と出力 (結果、LangChain としてシリアル化) が保持されますToolMessage。
{
"spanId": "5b332f3cd15ace04",
"traceId": "6a01eefa5c52f3d86a35038f35f5ba30",
"scope": {
"name": "opentelemetry.instrumentation.langchain"
},
"body": {
"input": {
"messages": [
{ "content": "{\"origin\": \"SEA\", \"destination\": \"NYC\", \"date\": \"2025-03-15\"}" }
]
},
"output": {
"messages": [
{
"role": "tool",
"name": "search_flights",
"content": "{\"origin\": \"SEA\", \"destination\": \"NYC\", \"flights\": [ ... ]}"
}
]
}
}
}
OpenInference
OpenInference ライブラリでは、スパンタイプは openinference.span.kind 属性で実行され、エージェントの入出力は相関イベントレコードでシリアル化されます。
例
- Invoke agent span
-
openinference.span.kind 属性 (またはグラフが名前でコンパイルAGENTされている場合) はCHAIN、これを呼び出しエージェントのスパンとして識別します。
{
"traceId": "6a387ee61078243c1cc455ed45c6c313",
"spanId": "0a7990d804132a9b",
"parentSpanId": "29ae22014173881c",
"name": "LangGraph",
"kind": "INTERNAL",
"scope": {
"name": "openinference.instrumentation.langchain",
"version": "0.1.66"
},
"startTimeUnixNano": 1782087405949310976,
"endTimeUnixNano": 1782087408945828864,
"durationNano": 2996517888,
"attributes": {
"openinference.span.kind": "CHAIN",
"input.mime_type": "application/json",
"output.mime_type": "application/json",
"llm.input_messages.0.message.role": "user",
"session.id": "sea-nyc-trip-2-turns-oi-0-1-66"
},
"status": {
"code": "OK"
}
}
相関イベントレコードは会話を保持します。ユーザープロンプトはヒューマンロールメッセージで、エージェントのレスポンスはシリアル化されたメッセージの AI ロールメッセージです。
{
"spanId": "0a7990d804132a9b",
"traceId": "6a387ee61078243c1cc455ed45c6c313",
"scope": {
"name": "openinference.instrumentation.langchain"
},
"body": {
"input": {
"messages": [
{
"role": "user",
"content": "{\"messages\": [{\"role\": \"user\", \"content\": \"Hey, how can you help me\"}]}"
}
]
},
"output": {
"messages": [
{
"content": "{\"messages\": [{\"type\": \"human\", \"data\": {\"content\": \"Hey, how can you help me\", ...}}, {\"type\": \"ai\", \"data\": {\"content\": \"Hello! I'm your travel planning assistant ...\", ...}}]}",
"role": "assistant"
}
]
}
}
}
- Execute tool span
-
openinference.span.kind 属性 (TOOL) は、これを実行ツールスパンとして識別します。 はツール名tool.nameを保持します。
{
"traceId": "6a387ef07b8f4f3732fab45d3c0b51ff",
"spanId": "ab105c12cc40048f",
"parentSpanId": "9b2d4e72760690b4",
"name": "search_flights",
"kind": "INTERNAL",
"scope": {
"name": "openinference.instrumentation.langchain",
"version": "0.1.66"
},
"startTimeUnixNano": 1782087411724620032,
"endTimeUnixNano": 1782087411725306880,
"durationNano": 686848,
"attributes": {
"openinference.span.kind": "TOOL",
"tool.name": "search_flights",
"tool.description": "Search for available flights between cities.",
"input.mime_type": "application/json",
"output.mime_type": "application/json",
"session.id": "sea-nyc-trip-2-turns-oi-0-1-66"
},
"status": {
"code": "OK"
}
}
相関イベントレコードには、ツールの入力 (引数) と出力 (結果、LangChain としてシリアル化) が保持されますToolMessage。
{
"spanId": "ab105c12cc40048f",
"traceId": "6a387ef07b8f4f3732fab45d3c0b51ff",
"scope": {
"name": "openinference.instrumentation.langchain"
},
"body": {
"input": {
"messages": [
{
"role": "user",
"content": "{\"origin\": \"SEA\", \"destination\": \"NYC\", \"date\": \"2025-03-15\"}"
}
]
},
"output": {
"messages": [
{
"content": "{\"type\": \"tool\", \"data\": {\"content\": \"{\\\"origin\\\": \\\"SEA\\\", \\\"destination\\\": \\\"NYC\\\", \\\"flights\\\": [ ... ]}\", \"type\": \"tool\", \"name\": \"search_flights\", \"tool_call_id\": \"toolu_bdrk_01LzXXJCfpfuS7Bpf7e1qLMg\", \"status\": \"success\"}}",
"role": "assistant"
}
]
}
}
}
統合テレメトリのスパンの例
統合テレメトリでは、同じコンテンツがスパン属性に残り、個別のイベントレコードは生成されません。次の例は、Python LangGraph の旅行計画エージェントからのものです。各計測ライブラリの下に同じエージェントが表示されます。
これらの例は完全なスパンではありません。実際のエージェントインタラクションからの代表的なデータが表示され、読みやすいように一部のフィールドは省略され、長い値は切り捨てられます。
OpenTelemetry
例
- Invoke agent span
-
gen_ai.task.input 属性はユーザープロンプトを保持し、 gen_ai.task.output 属性はエージェントのレスポンスでシリアル化された状態を保持します。どちらもシリアル化された LangChain グラフの状態です。
{
"traceId": "6a4de7b85e61747e6b568a1f4768e89d",
"spanId": "31ea3d5882dac680",
"name": "LangGraph.workflow",
"kind": "INTERNAL",
"scope": {
"name": "opentelemetry.instrumentation.langchain",
"version": "0.62.1"
},
"attributes": {
"traceloop.span.kind": "workflow",
"gen_ai.operation.name": "invoke_agent",
"gen_ai.agent.name": "LangGraph",
"gen_ai.task.input": "{\"inputs\": {\"messages\": [{\"role\": \"user\", \"content\": \"Hey, how can you help me\"}]}, \"tags\": [], \"metadata\": { ... }, \"kwargs\": {\"name\": \"LangGraph\"}}",
"gen_ai.task.output": "{\"outputs\": {\"messages\": [{\"lc\": 1, \"type\": \"constructor\", \"id\": [\"langchain\", \"schema\", \"messages\", \"HumanMessage\"], \"kwargs\": {\"content\": \"Hey, how can you help me\", \"type\": \"human\"}}, {\"lc\": 1, \"type\": \"constructor\", \"id\": [\"langchain\", \"schema\", \"messages\", \"AIMessage\"], \"kwargs\": {\"content\": \"Hello! I'm your travel planning assistant ...\", \"type\": \"ai\"}}]}, \"kwargs\": {\"tags\": []}}",
"session.id": "sea-nyc-trip-2-turns-unified"
},
"status": {
"code": "OK"
}
}
- Execute tool span
-
gen_ai.tool.call.arguments 属性はツール引数を保持し、 gen_ai.tool.call.result 属性は LangChain としてシリアル化されたツール結果を保持しますToolMessage。
{
"traceId": "6a4de7c376913db82e6f0f336a16731d",
"spanId": "b64c37adefae74f0",
"name": "execute_tool search_flights",
"kind": "INTERNAL",
"scope": {
"name": "opentelemetry.instrumentation.langchain",
"version": "0.62.1"
},
"attributes": {
"traceloop.span.kind": "tool",
"gen_ai.operation.name": "execute_tool",
"gen_ai.tool.name": "search_flights",
"gen_ai.tool.description": "Search for available flights between cities.",
"gen_ai.tool.call.arguments": "{\"input_str\": \"{'origin': 'SEA', 'destination': 'NYC', 'date': '2025-03-15'}\", \"inputs\": {\"origin\": \"SEA\", \"destination\": \"NYC\", \"date\": \"2025-03-15\"}, \"metadata\": { ... }}",
"gen_ai.tool.call.result": "{\"output\": {\"lc\": 1, \"type\": \"constructor\", \"id\": [\"langchain\", \"schema\", \"messages\", \"ToolMessage\"], \"kwargs\": {\"content\": \"{\\\"origin\\\": \\\"SEA\\\", \\\"destination\\\": \\\"NYC\\\", \\\"flights\\\": [ ... ]}\", \"type\": \"tool\", \"name\": \"search_flights\", \"status\": \"success\"}}}",
"session.id": "sea-nyc-trip-2-turns-unified"
},
"status": {
"code": "OK"
}
}
OpenInference
例
- Invoke agent span
-
input.value 属性はユーザープロンプトを保持し、 output.value 属性はエージェントのレスポンスでシリアル化された状態を保持します。
{
"traceId": "6a387ee61078243c1cc455ed45c6c313",
"spanId": "b8c0b67876b78b91",
"name": "LangGraph",
"kind": "INTERNAL",
"scope": {
"name": "openinference.instrumentation.langchain",
"version": "0.1.66"
},
"attributes": {
"openinference.span.kind": "CHAIN",
"input.value": "{\"messages\": [{\"role\": \"user\", \"content\": \"Hey, how can you help me\"}]}",
"output.value": "{\"messages\": [{\"type\": \"human\", \"data\": {\"content\": \"Hey, how can you help me\"}}, {\"type\": \"ai\", \"data\": {\"content\": \"Hello! I'm your travel planning assistant ...\"}}]}",
"session.id": "sea-nyc-trip-2-turns-oi-0-1-66"
},
"status": {
"code": "OK"
}
}
- Execute tool span
-
input.value 属性はツール引数を保持し、 output.value 属性は LangChain としてシリアル化されたツール結果を保持しますToolMessage。
{
"traceId": "6a387ef07b8f4f3732fab45d3c0b51ff",
"spanId": "58752612d9b22ae1",
"name": "search_flights",
"kind": "INTERNAL",
"scope": {
"name": "openinference.instrumentation.langchain",
"version": "0.1.66"
},
"attributes": {
"openinference.span.kind": "TOOL",
"tool.name": "search_flights",
"tool.description": "Search for available flights between cities.",
"input.value": "{\"origin\": \"SEA\", \"destination\": \"NYC\", \"date\": \"2025-03-15\"}",
"output.value": "{\"type\": \"tool\", \"data\": {\"content\": \"{\\\"origin\\\": \\\"SEA\\\", \\\"destination\\\": \\\"NYC\\\", \\\"flights\\\": [ ... ]}\", \"name\": \"search_flights\"}}",
"session.id": "sea-nyc-trip-2-turns-oi-0-1-66"
},
"status": {
"code": "OK"
}
}
TypeScript エージェントのサポート
TypeScript LangGraph エージェントは Python エージェントと同じスパンタイプを出力するため、評価サービスはそれを同じ方法で読み取ります。TypeScript 計測ライブラリは 3 つあり、それぞれに独自のスコープ名とスパン分類規則があります。
エージェントを計測する
TypeScript の依存関係に必要なパスの計測ライブラリを追加します。次の例では、最小バージョンを固定します。固定する理由がない限り、利用可能な最新バージョンを使用します。
例
- ADOT (OpenTelemetry)
-
ADOT の TypeScript エージェントの場合、依存関係に AWS Distro Node 自動計測パッケージ (@aws/aws-distro-opentelemetry-node-autoinstrumentation) を追加します。これには、起動時にアクティブ化され、スコープ名 を出力する組み込みの LangChain 計測が含まれています@aws/aws-distro-opentelemetry-instrumentation-langchain。
package.json:
{
"dependencies": {
"@aws/aws-distro-opentelemetry-node-autoinstrumentation": "^0.12.0"
}
}
- Traceloop (OpenTelemetry)
-
Traceloop LangChain 計測 (@traceloop/instrumentation-langchain) を依存関係に追加します。出力されるスコープ名は です@traceloop/instrumentation-langchain。
package.json:
{
"dependencies": {
"@traceloop/instrumentation-langchain": "^0.27.0"
}
}
- OpenInference
-
@arizeai/openinference-instrumentation-langchain を依存関係に追加します。出力されるスコープ名は です@arizeai/openinference-instrumentation-langchain。
package.json:
{
"dependencies": {
"@arizeai/openinference-instrumentation-langchain": "^4.0.14"
}
}
計測は、オブザーバビリティを設定する 1 つのステップです。評価のためにテレメトリをエクスポートするには、「オブザーバビリティの設定」で完全なセットアップを完了します。
スパンの識別方法
スパン識別は、計測ライブラリによって異なります。
-
ADOT (OpenTelemetry): AWS Distro Node 自動計測パッケージ (@aws/aws-distro-opentelemetry-node-autoinstrumentation)。他の ADOT ネイティブフレームワークと同じスコープ名 @aws/aws-distro-opentelemetry-instrumentation-langchain、 セット gen_ai.operation.name (invoke_agent、execute_tool、chat) を出力します。
-
Traceloop (OpenTelemetry): Traceloop (@traceloop/instrumentation-langchain) セットの OpenTelemetry JS ライブラリ traceloop.span.kind (workflow呼び出しエージェントスパンの場合は 、ツールスパンtaskの場合は )。Python OpenTelemetry ライブラリに一致。「Python エージェントサポートでスパンを識別する方法」を参照してください。 Python エージェントのサポート
-
OpenInference: OpenInference JS ライブラリ (@arizeai/openinference-instrumentation-langchain) は、Python OpenInference ライブラリと同じ openinference.span.kind (CHAIN または AGENT、TOOL、LLM) を設定します。
フィールド抽出は、計測ライブラリによって異なります。
-
ADOT (OpenTelemetry): 呼び出しエージェントのスパンは構造コンテナであり、会話コンテンツはパート形式とgen_ai.input.messagesgen_ai.output.messages属性の推論 (chat) スパンに存在します。
-
Traceloop (OpenTelemetry): Traceloop の OpenTelemetry JS ライブラリでは、会話はシリアル化された LangChain 状態として traceloop.entity.inputおよび traceloop.entity.output 属性にあります。これは Python OpenTelemetry ライブラリと一致します。Python エージェントサポートで評価フィールドを抽出する方法を参照してください。
-
OpenInference: OpenInference JS ライブラリでは、会話は 属性と input.value output.value 属性にあり、推論メッセージはインデックス付き属性llm.input_messages.*と llm.output_messages.* 属性にも表示されます。これは Python OpenInference ライブラリと一致します。
TypeScript エージェントからのスパンの例
次の例は、統合テレメトリを使用して Amazon Bedrock AgentCore ランタイムにデプロイされた TypeScript LangGraph の旅行計画エージェントからのものです。3 つの TypeScript 計測ライブラリのそれぞれに同じエージェントが表示されます。
これらの例は完全なスパンではありません。実際のエージェントインタラクションからの代表的なデータが表示され、読みやすいように一部のフィールドは省略され、長い値は切り捨てられます。
OpenTelemetry (ADOT ネイティブ)
ADOT ネイティブライブラリ ( AWS Distro Node 自動計測パッケージ から、スコープ名 を出力@aws/aws-distro-opentelemetry-instrumentation-langchain) では@aws/aws-distro-opentelemetry-node-autoinstrumentation、呼び出しエージェントスパンは構造コンテナであり、会話コンテンツはパート形式とgen_ai.input.messagesgen_ai.output.messages属性の推論 (chat) スパンに存在します。
例
- Invoke agent span
-
gen_ai.operation.name 属性 (invoke_agent) は、これを呼び出しエージェントのスパンとして識別します。スパンはエージェント名とモデルを保持しますが、会話コンテンツは保持しません。
{
"traceId": "6a6bd0a1c8d91ed1e70a3906b551618",
"spanId": "ba1833fa7f097041",
"name": "invoke_agent LangGraph",
"kind": "INTERNAL",
"scope": {
"name": "@aws/aws-distro-opentelemetry-instrumentation-langchain",
"version": "0.12.0"
},
"attributes": {
"gen_ai.operation.name": "invoke_agent",
"gen_ai.agent.name": "LangGraph",
"gen_ai.provider.name": "openai",
"gen_ai.request.model": "gpt-4o-mini",
"session.id": "sea-nyc-trip-2-turns"
},
"status": {
"code": "OK"
}
}
- Execute tool span
-
gen_ai.operation.name 属性 (execute_tool) は、これを実行ツールスパンとして識別します。 はツール名gen_ai.tool.nameを保持します。gen_ai.tool.call.arguments および gen_ai.tool.call.result 属性は、ツールの引数と結果を保持します。
{
"traceId": "6a6bd0a25c52f3d86a35038f35f5ba30",
"spanId": "5b332f3cd15ace04",
"name": "execute_tool search_flights",
"kind": "INTERNAL",
"scope": {
"name": "@aws/aws-distro-opentelemetry-instrumentation-langchain",
"version": "0.12.0"
},
"attributes": {
"gen_ai.operation.name": "execute_tool",
"gen_ai.tool.name": "search_flights",
"gen_ai.tool.type": "function",
"gen_ai.tool.call.arguments": "{\"origin\": \"SEA\", \"destination\": \"NYC\", \"date\": \"2025-03-15\"}",
"gen_ai.tool.call.result": "{\"origin\": \"SEA\", \"destination\": \"NYC\", \"flights\": [ ... ]}",
"session.id": "sea-nyc-trip-2-turns"
},
"status": {
"code": "OK"
}
}
- Inference span
-
gen_ai.operation.name 属性 (chat) は、これを推論スパンとして識別します。属性gen_ai.input.messagesと gen_ai.output.messages 属性は、会話を parts 形式で保持し、システムプロンプトgen_ai.system_instructionsを保持します。
{
"traceId": "6a6bd0a1c8d91ed1e70a3906b551618",
"spanId": "7c1f9a2b4d6e8a03",
"name": "chat gpt-4o-mini",
"kind": "INTERNAL",
"scope": {
"name": "@aws/aws-distro-opentelemetry-instrumentation-langchain",
"version": "0.12.0"
},
"attributes": {
"gen_ai.operation.name": "chat",
"gen_ai.provider.name": "openai",
"gen_ai.request.model": "gpt-4o-mini",
"gen_ai.input.messages": "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Hey, how can you help me\"}]}]",
"gen_ai.output.messages": "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"I can assist you with planning your trip ...\"}]}]",
"gen_ai.system_instructions": "[{\"type\": \"text\", \"content\": \"You are a travel planning assistant ...\"}]",
"session.id": "sea-nyc-trip-2-turns"
},
"status": {
"code": "OK"
}
}
OpenTelemetry (トレースループ)
Traceloop (@traceloop/instrumentation-langchain) の OpenTelemetry JS ライブラリでは、スパンタイプは traceloop.span.kind 属性 (workflow呼び出しエージェントスパンの場合は 、ツールスパンtaskの場合は ) で、呼び出しエージェントスパンworkflowの場合は gen_ai.operation.name = で実行されます。会話は、シリアル化された LangChain 状態として、 属性traceloop.entity.inputと traceloop.entity.output 属性にあります。
例
- Invoke agent span
-
traceloop.span.kind 属性 (workflow) は、これを呼び出しエージェントのスパンとして識別します。traceloop.entity.input および traceloop.entity.output 属性は、シリアル化された LangChain 状態を保持し、ユーザープロンプト (ヒューマンメッセージ) とエージェントレスポンス (AI メッセージ) が解析されます。
{
"traceId": "6a6bd0b1c8d91ed1e70a3906b551618",
"spanId": "ba1833fa7f097041",
"name": "workflow RunnableSequence",
"kind": "INTERNAL",
"scope": {
"name": "@traceloop/instrumentation-langchain",
"version": "0.27.0"
},
"attributes": {
"traceloop.span.kind": "workflow",
"gen_ai.operation.name": "workflow",
"gen_ai.provider.name": "langchain",
"traceloop.workflow.name": "RunnableSequence",
"traceloop.entity.input": "{\"messages\": [{\"lc\": 1, \"type\": \"constructor\", \"id\": [\"langchain_core\", \"messages\", \"HumanMessage\"], \"kwargs\": {\"content\": \"Hey, how can you help me\"}}]}",
"traceloop.entity.output": "{\"messages\": [{\"lc\": 1, \"type\": \"constructor\", \"id\": [\"langchain_core\", \"messages\", \"AIMessage\"], \"kwargs\": {\"content\": \"I can assist you with planning your trip ...\"}}]}",
"session.id": "sea-nyc-trip-2-turns"
},
"status": {
"code": "OK"
}
}
- Execute tool span
-
traceloop.span.kind 属性 (task) は、これを実行ツールスパンとして識別します。traceloop.entity.input および traceloop.entity.output 属性は、ツールの引数と結果を保持します。
{
"traceId": "6a6bd0b25c52f3d86a35038f35f5ba30",
"spanId": "5b332f3cd15ace04",
"name": "task search_flights",
"kind": "INTERNAL",
"scope": {
"name": "@traceloop/instrumentation-langchain",
"version": "0.27.0"
},
"attributes": {
"traceloop.span.kind": "task",
"traceloop.entity.name": "search_flights",
"traceloop.entity.input": "{\"origin\": \"SEA\", \"destination\": \"NYC\", \"date\": \"2025-03-15\"}",
"traceloop.entity.output": "{\"output\": {\"lc\": 1, \"type\": \"constructor\", \"id\": [\"langchain_core\", \"messages\", \"ToolMessage\"], \"kwargs\": {\"status\": \"success\", \"content\": \"{\\\"origin\\\": \\\"SEA\\\", \\\"destination\\\": \\\"NYC\\\", \\\"flights\\\": [ ... ]}\"}}}",
"session.id": "sea-nyc-trip-2-turns"
},
"status": {
"code": "OK"
}
}
OpenInference
OpenInference JS ライブラリ (@arizeai/openinference-instrumentation-langchain) では、スパンタイプは openinference.span.kind 属性で伝送されます。会話の内容は input.valueおよび output.value 属性にあり、推論メッセージはインデックス付き llm.input_messages.*および llm.output_messages.* 属性にも表示されます。
例
- Invoke agent span
-
openinference.span.kind 属性 (CHAIN) は、これを呼び出しエージェントのスパンとして識別します。属性input.valueと output.value 属性は、シリアル化された LangChain 状態を保持します。
{
"traceId": "6a6bd0c1c8d91ed1e70a3906b551618",
"spanId": "0a7990d804132a9b",
"name": "LangGraph",
"kind": "INTERNAL",
"scope": {
"name": "@arizeai/openinference-instrumentation-langchain",
"version": "4.0.14"
},
"attributes": {
"openinference.span.kind": "CHAIN",
"input.value": "{\"messages\": [{\"lc\": 1, \"type\": \"constructor\", \"id\": [\"langchain_core\", \"messages\", \"HumanMessage\"], \"kwargs\": {\"content\": \"Hey, how can you help me\"}}]}",
"output.value": "{\"messages\": [{\"lc\": 1, \"type\": \"constructor\", \"id\": [\"langchain_core\", \"messages\", \"AIMessage\"], \"kwargs\": {\"content\": \"I can assist you with planning your trip ...\"}}]}",
"session.id": "sea-nyc-trip-2-turns"
},
"status": {
"code": "OK"
}
}
- Execute tool span
-
openinference.span.kind 属性 (TOOL) は、これを実行ツールスパンとして識別します。 はツール名tool.nameを保持します。input.value および output.value 属性は、ツール引数と結果を保持します (LangChain としてシリアル化)ToolMessage。
{
"traceId": "6a6bd0c25c52f3d86a35038f35f5ba30",
"spanId": "ab105c12cc40048f",
"name": "search_flights",
"kind": "INTERNAL",
"scope": {
"name": "@arizeai/openinference-instrumentation-langchain",
"version": "4.0.14"
},
"attributes": {
"openinference.span.kind": "TOOL",
"tool.name": "search_flights",
"input.value": "{\"origin\": \"SEA\", \"destination\": \"NYC\", \"date\": \"2025-03-15\"}",
"output.value": "{\"output\": {\"lc\": 1, \"type\": \"constructor\", \"id\": [\"langchain_core\", \"messages\", \"ToolMessage\"], \"kwargs\": {\"status\": \"success\", \"content\": \"{\\\"origin\\\": \\\"SEA\\\", \\\"destination\\\": \\\"NYC\\\", \\\"flights\\\": [ ... ]}\"}}}",
"session.id": "sea-nyc-trip-2-turns"
},
"status": {
"code": "OK"
}
}
- Inference span
-
openinference.span.kind 属性 (LLM) は、これを推論スパンとして識別します。llm.input_messages.* 属性はシステムプロンプトとユーザープロンプトを保持し、llm.output_messages.*属性はエージェントのレスポンスを保持します。
{
"traceId": "6a6bd0c1c8d91ed1e70a3906b551618",
"spanId": "1221a062c7f90a8e",
"name": "ChatOpenAI",
"kind": "INTERNAL",
"scope": {
"name": "@arizeai/openinference-instrumentation-langchain",
"version": "4.0.14"
},
"attributes": {
"openinference.span.kind": "LLM",
"llm.model_name": "gpt-4o-mini",
"llm.input_messages.0.message.role": "system",
"llm.input_messages.0.message.content": "You are a travel planning assistant ...",
"llm.input_messages.1.message.role": "user",
"llm.input_messages.1.message.content": "Hey, how can you help me",
"llm.output_messages.0.message.role": "assistant",
"llm.output_messages.0.message.content": "I can assist you with planning your trip ...",
"session.id": "sea-nyc-trip-2-turns"
},
"status": {
"code": "OK"
}
}
LangGraph エージェントに関するベストプラクティス
LangGraph エージェントを構築して呼び出す方法は、テレメトリに表示される内容、つまりエージェントの評価の信頼性に影響します。以下のプラクティスは、ユーザープロンプト、エージェントのレスポンス、ツールアクティビティを回復可能にするのに役立ちます。
1. エージェント構築パターンを選択する
LangGraph エージェントを構築するには、次の 2 つの一般的な方法があります。
-
構築済み create_agent : 最も簡単な開始方法。これにより、1 ターンあたり 1 回の呼び出しエージェントスパンが生成され、会話は LangGraph の組み込み実行ループを通過します。これは、カスタムコントロールフローのない標準の reason-act エージェントが必要な場合に使用します。
from langchain.agents import create_agent
agent = create_agent(model=model, tools=[search_flights, book_flight])
-
カスタム StateGraph : ノード、エッジ、および条件付きルーティングを完全に制御できます。各ノード実行は独自のスパンになるため、トレースはより詳細になります。カスタムオーケストレーションが必要な場合は、これを使用します。
from langgraph.graph import StateGraph, START, END
from typing_extensions import TypedDict
class State(TypedDict):
messages: list
graph = StateGraph(State)
graph.add_node("generate_response", generate_response)
graph.add_node("tools", run_tools)
graph.add_edge(START, "generate_response")
agent = graph.compile()
どちらのパターンも同じ方法で評価されます。違いはトレースの粒度です。
2. グラフの状態messagesで を使用する (推奨)
評価サービスは、エージェントの入力メッセージと出力メッセージから会話を再構築します。messages フィールドの使用は必須ではありませんが、最も信頼性の高い抽出が可能になります。カスタム の場合StateGraph、会話は 状態のmessagesフィールドに保持します。
-
を 状態messagesに含める (推奨)。他のカスタムフィールド ( user_idや メタデータなど) を追加できます。messages が存在する場合、標準抽出はユーザープロンプトとエージェントのレスポンスを直接検出します。messages が存在しない場合、サービスは個々の推論スパンからの会話の再構築にフォールバックします。これは信頼性が低くなります。
-
追加します。置き換えないでください。LangGraph の規則に従って、新しいメッセージを上書きせずにリストに追加すると、会話履歴全体が保持されます。
-
正規の LangChain メッセージタイプ (HumanMessage、AIMessage、ToolMessage、) を使用しますSystemMessage。計測はこれらを正しくシリアル化し、サービスはそれらのロールを認識します。
3. サポートされている形式でユーザーメッセージを渡す
LangGraph エージェントを呼び出すときは、ユーザーメッセージをグラフmessagesの状態に追加します。LangGraph はメッセージを 3 つの交換可能な形式で受け入れ、AgentCore Evaluations はそれらのすべてをサポートします。各 は、サービスが読み取ることができるスパンとイベントレコードを生成します。
-
タプル: (role, content)ペア:
agent.invoke({"messages": [("user", user_message)]}, config=config)
-
LangChain メッセージオブジェクト: HumanMessage (または他のメッセージクラス):
from langchain_core.messages import HumanMessage
agent.invoke({"messages": [HumanMessage(content=user_message)]}, config=config)
-
ディクショナリ: {"role", "content"}ディクショナリ:
agent.invoke({"messages": [{"role": "user", "content": user_message}]}, config=config)
3 つの形式はすべて同じmessages状態になるため、どの形式を選択しても、ユーザープロンプトとエージェントのレスポンスは同じように抽出されます。