Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Configurar la LangGraph telemetría para las evaluaciones AgentCore
En esta página se explica cómo instrumentar un LangGraph agente, cómo se identifican los intervalos y cómo se extraen los campos de evaluación. AgentCore Evaluations admite LangGraph agentes creados en Python y, en esta página TypeScript, se describe cada idioma por separado, en el soporte para agentes y el soporte para TypeScript agentes de Python. Termina con las mejores prácticas para estructurar un LangGraph agente de modo que pueda evaluarse de forma fiable.
Temas
Soporte de agentes de Python
Un LangGraph agente de Python emite intervalos con el nombre de ámbito opentelemetry.instrumentation.langchain (OpenTelemetry) o openinference.instrumentation.langchain (OpenInference).
Instrumenta a tu agente
Puede instrumentar un LangGraph agente con cualquiera de las dos bibliotecas de instrumentación: OpenTelemetry (opentelemetry-instrumentation-langchain) o OpenInference (openinference-instrumentation-langchain). Amazon Bedrock AgentCore Evaluations es compatible con ambas bibliotecas. Las bibliotecas emiten distintos nombres de ámbito y utilizan distintos atributos de intervalo. El servicio de evaluación extrae los mismos valores de cada uno.
Cuando su agente se ejecuta con la AWS distribución para OpenTelemetry (ADOT), como en Amazon Bedrock AgentCore Runtime, no es necesario añadir código de instrumentación explícito. Basta con añadir la biblioteca de instrumentación a las dependencias de su proyecto. ADOT la descubre al inicio y la activa automáticamente.
Agregue la biblioteca de instrumentación para la ruta que desee a sus dependencias. Los siguientes ejemplos fijan una versión mínima; usa la última versión disponible a menos que tengas una razón para anclarla.
ejemplo
- OpenTelemetry
-
NOTA: Usa la versión 0.55.0 o posterior. La versión 0.55.0 agregó compatibilidad con las convenciones más recientes sobre el intervalo de agentes de OpenTelemetry IA generativa del GitHub sitio web, en las que se basa el servicio de evaluación.
Añada opentelemetry-instrumentation-langchain a sus dependencias. El nombre del ámbito emitido es. opentelemetry.instrumentation.langchain
requirements.txt:
opentelemetry-instrumentation-langchain>=0.55.0
pyproject.toml:
[project]
dependencies = [
"opentelemetry-instrumentation-langchain>=0.55.0",
]
- OpenInference
-
Añada openinference-instrumentation-langchain a sus dependencias. El nombre del ámbito emitido esopeninference.instrumentation.langchain.
requirements.txt:
openinference-instrumentation-langchain>=0.1.62
pyproject.toml:
[project]
dependencies = [
"openinference-instrumentation-langchain>=0.1.62",
]
La instrumentación es un paso para configurar la observabilidad. Para exportar la telemetría para su evaluación, complete la configuración completa en Configurar la observabilidad.
Cómo se identifican los intervalos
El atributo utilizado para clasificar los intervalos difiere entre las dos bibliotecas de instrumentación.
ejemplo
- OpenTelemetry
-
La biblioteca de OpenTelemetry instrumentación clasifica los intervalos mediante el traceloop.span.kind atributo y también establece las versiones recientes. gen_ai.operation.name
| Tipo de intervalo |
Atributo identificativo |
|
Invocar al agente
|
traceloop.span.kind= workflow (también gen_ai.operation.name =invoke_agent)
|
|
Ejecute la herramienta
|
traceloop.span.kind= tool (también gen_ai.operation.name =execute_tool)
|
|
Inferencia
|
gen_ai.operation.name = chat
|
- OpenInference
-
La biblioteca de OpenInference instrumentación clasifica los intervalos mediante el atributo. openinference.span.kind
| Tipo de intervalo |
Atributo identificativo |
|
Invocar al agente
|
openinference.span.kind= CHAIN o AGENT
|
|
Ejecutar herramienta
|
openinference.span.kind = TOOL
|
|
Inferencia
|
openinference.span.kind = LLM
|
Para el intervalo de agentes de invocación, la entrada y la salida no contienen una lista limpia por mensaje. En cambio, el contenido es el estado del LangChain gráfico serializado: una cadena JSON que contiene el estado completo. La forma exacta de este estado serializado difiere entre las dos bibliotecas de instrumentación. En ambos casos, el servicio lo analiza para encontrar el mensaje del usuario (el mensaje humano) y la respuesta del agente (el mensaje de la IA).
LangGraph también serializa los roles de los mensajes en más de un formulario. Un rol puede aparecer como un valor en minúscula (human,ai,tool) o como un nombre de clase de LangChain mensaje (HumanMessage,,AIMessage). ToolMessage El servicio reconoce ambas formas.
La ubicación de este contenido depende de cómo se recopiló la telemetría. El atributo identificativo (traceloop.span.kindoopeninference.span.kind) está en el intervalo en ambos casos. Para obtener más información, consulte Configuración y entrega de telemetría.
Con la telemetría dividida, el servicio lee el contenido del registro de eventos en relación con cada intervalo:
-
Mensaje del usuario y respuesta del agente: desde el registro de eventos del intervalo del agente que invoca, en y. body.input body.output
-
Llamada a la herramienta: el nombre de la herramienta del conjunto de herramientas de ejecución. Los argumentos y el resultado de la herramienta provienen del registro de eventos de ese intervalo, en body.input ybody.output.
Para obtener más información, consulte el ejemplo de intervalos en telemetría dividida.
Con la telemetría unificada, el mismo contenido permanece en el intervalo que los atributos. Los atributos dependen de la biblioteca de instrumentación:
-
OpenTelemetry:
-
Mensaje del usuario y respuesta del agente: desde gen_ai.task.input y después del gen_ai.task.output intervalo del agente que invoca.
-
Llamada a la herramienta: el nombre de la herramienta desdegen_ai.tool.name, los argumentos y el resultado de gen_ai.tool.call.arguments ygen_ai.tool.call.result, en el intervalo de la herramienta de ejecución.
-
OpenInference:
-
Mensaje del usuario y respuesta del agente: desde input.value y hacia output.value el intervalo del agente de invocación.
-
Llamada a la herramienta: el nombre de la herramienta desdetool.name, los argumentos y el resultado de input.value youtput.value, en el intervalo de la herramienta de ejecución.
Para obtener más información, consulte Ejemplos de intervalos en telemetría unificada.
Ejemplos de intervalos en telemetría dividida
Con la telemetría dividida, el intervalo contiene los atributos de identificación y el contenido se encuentra en un registro de eventos correlacionado. Los siguientes ejemplos provienen de un agente de LangGraph planificación de viajes de Python implementado en Amazon Bedrock Runtime. AgentCore El mismo agente se muestra en cada biblioteca de instrumentación.
Estos ejemplos no son conjuntos completos. Muestran datos representativos de una interacción real con un agente; se omiten algunos campos y se truncan los valores largos para facilitar la lectura.
OpenTelemetry
ejemplo
- Invoke agent span
-
El traceloop.span.kind atributo (workflow) lo identifica como un intervalo de agentes de invocación; las versiones recientes de la biblioteca también establecen =. 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"
}
}
El registro de eventos correlacionados contiene la conversación. El de cada mensaje content es el estado del LangChain gráfico serializado. La entrada envuelve el estado bajo una inputs clave. La salida lo envuelve en una outputs clave, con cada mensaje como un objeto LangChain constructor. El mensaje del usuario es el mensaje humano y la respuesta del agente es el mensaje de la IA dentro de ese estado serializado.
{
"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
-
El traceloop.span.kind atributo (tool) lo identifica como un conjunto de herramientas de ejecución; gen_ai.tool.name contiene el nombre de la herramienta y gen_ai.operation.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"
}
}
El registro de eventos correlacionados contiene la entrada (argumentos) y la salida (resultado, serializado como a) de la herramienta. 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
En la OpenInference biblioteca, el tipo de intervalo se incluye en el openinference.span.kind atributo y la entrada y la salida del agente se serializan en el registro de eventos correlacionados.
ejemplo
- Invoke agent span
-
El openinference.span.kind atributo (CHAINo AGENT cuando el gráfico se compila con un nombre) lo identifica como un intervalo de agentes de invocación.
{
"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"
}
}
El registro de eventos correlacionados contiene la conversación. La solicitud del usuario es el mensaje del rol humano y la respuesta del agente es el AI-role mensaje de los mensajes serializados.
{
"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
-
El openinference.span.kind atributo (TOOL) lo identifica como un conjunto de herramientas de ejecución; tool.name contiene el nombre de la herramienta.
{
"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"
}
}
El registro de eventos correlacionados contiene la entrada (argumentos) y la salida (resultado, serializado como un LangChain ToolMessage) de la herramienta.
{
"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"
}
]
}
}
}
Los ejemplos abarcan la telemetría unificada
Con la telemetría unificada, el mismo contenido permanece en los atributos del intervalo y no se produce ningún registro de eventos independiente. Los siguientes ejemplos provienen de un agente de planificación de LangGraph viajes de Python. El mismo agente se muestra en cada biblioteca de instrumentación.
Estos ejemplos no son conjuntos completos. Muestran datos representativos de una interacción real con un agente, con algunos campos omitidos y los valores largos truncados para facilitar la lectura.
OpenTelemetry
ejemplo
- Invoke agent span
-
El gen_ai.task.input atributo contiene la solicitud del usuario y el gen_ai.task.output atributo contiene el estado serializado con la respuesta del agente. Ambos son el estado del LangChain gráfico serializado.
{
"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
-
El gen_ai.tool.call.arguments atributo contiene los argumentos de la herramienta y el gen_ai.tool.call.result atributo contiene el resultado de la herramienta, serializado como un. 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
ejemplo
- Invoke agent span
-
El input.value atributo contiene la solicitud de usuario y el output.value atributo contiene el estado serializado con la respuesta del agente.
{
"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
-
El input.value atributo contiene los argumentos de la herramienta y el output.value resultado de la herramienta, serializado como un. 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 soporte de agentes
Un TypeScript LangGraph agente emite los mismos tipos de intervalo que un agente de Python, por lo que el servicio de evaluación lo lee de la misma manera. Hay tres bibliotecas de TypeScript instrumentación, cada una con su propio nombre de ámbito y convención de clasificación de tramos.
Instrumente a su agente
Agregue la biblioteca de instrumentación de la ruta que desee a sus TypeScript dependencias. Los siguientes ejemplos fijan una versión mínima; usa la última versión disponible a menos que tengas una razón para anclarla.
ejemplo
- ADOT (OpenTelemetry)
-
Para TypeScript los agentes de ADOT, añada el paquete de autoinstrumentación AWS Distro Node (@aws/aws-distro-opentelemetry-node-autoinstrumentation) a sus dependencias. Incluye la LangChain instrumentación integrada, que se activa al inicio y emite el nombre del ámbito. @aws/aws-distro-opentelemetry-instrumentation-langchain
package.json:
{
"dependencies": {
"@aws/aws-distro-opentelemetry-node-autoinstrumentation": "^0.12.0"
}
}
- Traceloop (OpenTelemetry)
-
Añade la LangChain instrumentación de Traceloop () a tus dependencias. @traceloop/instrumentation-langchain El nombre del ámbito emitido es. @traceloop/instrumentation-langchain
package.json:
{
"dependencies": {
"@traceloop/instrumentation-langchain": "^0.27.0"
}
}
- OpenInference
-
Añada @arizeai/openinference-instrumentation-langchain a sus dependencias. El nombre del ámbito emitido es@arizeai/openinference-instrumentation-langchain.
package.json:
{
"dependencies": {
"@arizeai/openinference-instrumentation-langchain": "^4.0.14"
}
}
La instrumentación es un paso para configurar la observabilidad. Para exportar la telemetría para su evaluación, complete la configuración completa en Configurar la observabilidad.
Cómo se identifican los intervalos
La identificación de los intervalos depende de la biblioteca de instrumentación:
-
ADOT (OpenTelemetry): el paquete de autoinstrumentación de AWS Distro Node (@aws/aws-distro-opentelemetry-node-autoinstrumentation), que emite el nombre del ámbito@aws/aws-distro-opentelemetry-instrumentation-langchain, establece gen_ai.operation.name (,,chat) invoke_agentexecute_tool, igual que en los demás marcos. ADOT-native
-
Traceloop (OpenTelemetry): la biblioteca OpenTelemetry JS de Traceloop () establece (para el intervalo del agente de invocación, workflow para el intervalo de la traceloop.span.kind herramienta@traceloop/instrumentation-langchain), que coinciden con la biblioteca de Python. task OpenTelemetry Consulta Cómo se identifican los intervalos en el apartado de compatibilidad con agentes de Python. Soporte de agentes de Python
-
OpenInference: la biblioteca OpenInference JS (@arizeai/openinference-instrumentation-langchain) establece openinference.span.kind (CHAINoAGENT,,LLM)TOOL, lo mismo que la OpenInference biblioteca de Python.
La extracción de campos depende de la biblioteca de instrumentación:
-
ADOT (OpenTelemetry): el intervalo del agente de invocación es un contenedor estructural y el contenido de la conversación se encuentra en el intervalo de inferencia (chat), en el formato de las partes y los atributos. gen_ai.input.messages gen_ai.output.messages
-
Traceloop (OpenTelemetry): con la biblioteca OpenTelemetry JS de Traceloop, la conversación se encuentra en los atributos y, en estado serializado. traceloop.entity.input traceloop.entity.output LangChain Esto coincide con la OpenTelemetry biblioteca de Python; consulta Cómo se extraen los campos de evaluación en la sección Soporte para agentes de Python. Soporte de agentes de Python
-
OpenInference: con la biblioteca OpenInference JS, la conversación se encuentra en los output.value atributos input.value y, y los mensajes de inferencia también aparecen en los atributos indexados llm.input_messages.* yllm.output_messages.*. Esto coincide con la biblioteca de Python OpenInference .
Un ejemplo abarca desde un agente TypeScript
Los siguientes ejemplos provienen de un agente de TypeScript LangGraph planificación de viajes implementado en Amazon Bedrock AgentCore Runtime con telemetría unificada. El mismo agente se muestra en cada una de las tres bibliotecas de instrumentación. TypeScript
Estos ejemplos no son conjuntos completos. Muestran datos representativos de una interacción real con un agente; se omiten algunos campos y se truncan los valores largos para facilitar la lectura.
OpenTelemetry (nativo de ADOT)
En la ADOT-native biblioteca (del paquete de autoinstrumentación AWS Distro Node, donde se emite el nombre del ámbito@aws/aws-distro-opentelemetry-instrumentation-langchain)@aws/aws-distro-opentelemetry-node-autoinstrumentation, el intervalo del agente invocador es un contenedor estructural y el contenido de la conversación reside en el intervalo inference (chat), en el formato de las piezas y los atributos. gen_ai.input.messages gen_ai.output.messages
ejemplo
- Invoke agent span
-
El gen_ai.operation.name atributo (invoke_agent) lo identifica como un intervalo de agentes de invocación. El intervalo incluye el nombre y el modelo del agente, pero no el contenido de la conversación.
{
"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
-
El gen_ai.operation.name atributo (execute_tool) lo identifica como un conjunto de herramientas de ejecución; gen_ai.tool.name contiene el nombre de la herramienta. Los gen_ai.tool.call.result atributos gen_ai.tool.call.arguments y contienen los argumentos y el resultado de la herramienta.
{
"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
-
El gen_ai.operation.name atributo (chat) lo identifica como un intervalo de inferencia. Los gen_ai.output.messages atributos gen_ai.input.messages y mantienen la conversación en formato de piezas y contienen el indicador del gen_ai.system_instructions sistema.
{
"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)
En la biblioteca OpenTelemetry JS de Traceloop (@traceloop/instrumentation-langchain), el tipo span se incluye en el traceloop.span.kind atributo (workflowpara el intervalo del agente de invocación, task para el intervalo de la herramienta) y gen_ai.operation.name = en el intervalo del agente de invocación. workflow La conversación se encuentra en los traceloop.entity.output atributos traceloop.entity.input y, en estado serializado. LangChain
ejemplo
- Invoke agent span
-
El traceloop.span.kind atributo (workflow) lo identifica como un intervalo de agentes de invocación. Los traceloop.entity.output atributos traceloop.entity.input y mantienen el LangChain estado serializado, a partir del cual se analizan la solicitud del usuario (mensaje humano) y la respuesta del agente (mensaje de IA).
{
"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
-
El traceloop.span.kind atributo (task) lo identifica como un intervalo de herramientas de ejecución. Los traceloop.entity.output atributos traceloop.entity.input y contienen los argumentos y el resultado de la herramienta.
{
"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
Con la biblioteca OpenInference JS (@arizeai/openinference-instrumentation-langchain), el tipo de intervalo se incluye en el openinference.span.kind atributo. El contenido de la conversación está en los output.value atributos input.value y, y los mensajes de inferencia también aparecen en los atributos indexados llm.input_messages.* yllm.output_messages.*.
ejemplo
- Invoke agent span
-
El openinference.span.kind atributo (CHAIN) lo identifica como un intervalo de agentes de invocación. Los output.value atributos input.value y contienen el estado serializado. 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
-
El openinference.span.kind atributo (TOOL) lo identifica como un conjunto de herramientas de ejecución; tool.name contiene el nombre de la herramienta. Los output.value atributos input.value y contienen los argumentos y el resultado de la herramienta (serializados como a 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
-
El openinference.span.kind atributo (LLM) lo identifica como un intervalo de inferencia. Los llm.input_messages.* atributos contienen la solicitud del sistema y la solicitud del usuario, y los llm.output_messages.* atributos contienen la respuesta del agente.
{
"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"
}
}
Mejores prácticas para los LangGraph agentes
La forma en que se crea e invoca un LangGraph agente afecta a lo que aparece en su telemetría y, por lo tanto, a la fiabilidad con la que se puede evaluar el agente. Las siguientes prácticas ayudan a garantizar que la respuesta del usuario, la respuesta del agente y la actividad de la herramienta sean recuperables.
1. Elija un patrón de construcción de agentes
Hay dos maneras comunes de crear un LangGraph agente:
-
Prediseñado create_agent: la forma más rápida de empezar. Produce un único intervalo de agentes de invocación por turno, y la conversación pasa por el ciclo LangGraph de ejecución integrado. Utilízalo cuando quieras un agente estándar de acción por motivos sin un flujo de control personalizado.
from langchain.agents import create_agent
agent = create_agent(model=model, tools=[search_flights, book_flight])
-
Personalizado StateGraph: te brinda un control total sobre los nodos, los bordes y el enrutamiento condicional. La ejecución de cada nodo se convierte en su propio intervalo, por lo que los seguimientos son más granulares. Utilízala cuando necesites una orquestación personalizada.
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()
Ambos patrones se evalúan de la misma manera; la diferencia es la granularidad de la traza.
2. Usa los mensajes en el estado de tu gráfico (recomendado)
El servicio de evaluación reconstruye la conversación a partir de los mensajes de entrada y salida del agente. El uso de un messages campo no es obligatorio, pero permite la extracción más fiable. Como costumbreStateGraph, mantenga la conversación en un messages campo de su estado:
-
Incluya messages en su estado (recomendado). Puede agregar otros campos personalizados (por ejemplo, user_id metadatos). Cuando messages está presente, la extracción estándar busca directamente la solicitud del usuario y la respuesta del agente. Si messages está ausente, el servicio recurre a reconstruir la conversación a partir de intervalos de inferencia individuales, lo que resulta menos fiable.
-
Añada, no reemplace. Siga la LangGraph convención de agregar nuevos mensajes a la lista en lugar de sobrescribirlos, de modo que se conserve el historial completo de las conversaciones.
-
Usa tipos de LangChain mensajes canónicos (HumanMessage,,,AIMessage). ToolMessage SystemMessage La instrumentación los serializa correctamente y el servicio reconoce sus funciones.
3. Transmita el mensaje de usuario en un formato compatible
Cuando invocas a un LangGraph agente, agregas el mensaje del usuario al messages estado del gráfico. LangGraph acepta el mensaje en tres formatos intercambiables y AgentCore Evaluations admite todos ellos. Cada uno produce intervalos y registros de eventos que el servicio puede leer.
-
Tupla: un (role, content) par:
agent.invoke({"messages": [("user", user_message)]}, config=config)
-
LangChain objeto de mensaje: una HumanMessage (u otra clase de mensaje):
from langchain_core.messages import HumanMessage
agent.invoke({"messages": [HumanMessage(content=user_message)]}, config=config)
-
Diccionario: un {"role", "content"} diccionario:
agent.invoke({"messages": [{"role": "user", "content": user_message}]}, config=config)
Los tres formatos dan como resultado el mismo messages estado, por lo que la solicitud del usuario y la respuesta del agente se extraen de forma idéntica, independientemente del formato que elija.