Integración de la observabilidad del agente mediante OTel directo

Aprende a integrar la observabilidad del agente con el Agente 365 enviando telemetría directamente a través de OpenTelemetry (OTLP/HTTP+JSON). Este enfoque ayuda a los agentes que no pueden usar el SDK Agent 365 o la Distribución OpenTelemetry de Microsoft a enviar telemetría de forma eficiente y segura. Antes de empezar, lee los conceptos de observabilidad del Agente 365 para entender el modelo, los flujos de autenticación y dónde aparecen tus datos.

Importante

La ruta de acceso directa de OTel es la excepción, no la predeterminada. Úselo solo si ya tiene una canalización de OpenTelemetry, el marco de trabajo no puede usar el SDK del Agente 365 o el agente está en un lenguaje que el SDK todavía no admite (por ejemplo, Java). Para todos los demás, la opción recomendada es la Distribución OpenTelemetry de Microsoft, que proporciona un SDK de observabilidad unificado para Agent 365, Microsoft Foundry, Azure Monitor y otros. El SDK de observabilidad anterior sigue funcionando sin cambios importantes, pero ya no se recomienda para nuevas integraciones; La guía de migración para los usuarios del SDK existentes estará disponible.

Prerequisites

Asegúrese de que se han implementado las siguientes configuraciones antes de que se produzcan flujos de telemetría.

Quién What
Administrador de inquilinos Regístrese en el Agente 365 y conceda consentimiento para la aplicación del agente. Consulte Primeros pasos con Agent 365. Sin un inquilino válido, la ingesta puede devolver 200 OK aunque la respuesta results indique que los intervalos fueron rechazados.
Administrador de inquilinos Asigne una licencia de Microsoft 365 E7 o Microsoft Agent 365 a al menos un usuario del inquilinato. No basta con que el SKU esté presente. La asignación a un usuario inicia el flujo de trabajo de back-end de Defender que permite la ingesta. Sin una licencia asignada, la ingestión puede regresar 200 OK mientras se rechazan los tramos.
Administrador de inquilinos Conceda el consentimiento del inquilino. Consulte Conceder a los agentes acceso a los recursos de Microsoft 365. Sin él, los tokens se emiten sin el rol ni el ámbito y las solicitudes devuelven 403.
Su equipo de desarrollo Registre la aplicación (aplicación Microsoft Entra estándar o plano técnico). Ver Identidad del agente.
Su equipo de desarrollo Agregue Agent365.Observability.OtelWrite debajo de Permisos de API (rol de la aplicación para S2S, ámbito para permisos delegados). Para ver los planos técnicos, consulte Configuración de permisos heredables. Coordine con el equipo de incorporación de Agent 365 para habilitar el permiso.

Recetas de autenticación

Las cuatro recetas usan el punto de conexión de token estándar de Microsoft Entra:

Field Value
Punto de conexión de token https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/token
Recurso (aud en token devuelto) 9b975845-388f-4429-889e-eab1ef63949c (también acepta api://9b975845-388f-4429-889e-eab1ef63949c)
Ámbito de S2S 9b975845-388f-4429-889e-eab1ef63949c/.default
Ámbito de OBO 9b975845-388f-4429-889e-eab1ef63949c/Agent365.Observability.OtelWrite

Las siguientes recetas muestran HTTP en bruto para mayor claridad. En producción, usa Microsoft. Identity.Web u otra biblioteca MSAL, que gestiona la actualización de tokens y la caché.

¿Qué receta necesito?

Mi modelo de aplicación Mi flujo de OAuth Vaya a
Registro de aplicaciones de Microsoft Entra estándar S2S (credenciales de cliente) S2S, aplicación Microsoft Entra estándar
Registro de aplicaciones de Microsoft Entra estándar OBO (delegado) OBO, aplicación Microsoft Entra estándar
Identidad del agente derivado del plano técnico S2S (credenciales de cliente) S2S, identidad del agente derivado del plano técnico
Identidad del agente derivado del plano técnico Compañero de equipo de OBO/AI OBO, identidad del agente derivado del plano técnico

S2S, aplicación estándar de Microsoft Entra

Envía una solicitud POST al punto de conexión del token del inquilino con grant_type=client_credentials. Autentique la aplicación mediante un secreto de cliente, un certificado (aserción JWT firmada) o una identidad administrada o una credencial federada.

POST https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

client_id={your-app-id}
&scope=9b975845-388f-4429-889e-eab1ef63949c%2F.default
&client_secret={secret}
&grant_type=client_credentials

El token devuelto tiene appid/azp = {your-app-id}, roles que contiene Agent365.Observability.OtelWritey .aud = 9b975845-... Úselo en la ruta /observabilityService/.../traces.

Para la autenticación basada en certificados, reemplace por client_secret={secret}client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={signed-jwt}.

S2S, identidad de agente derivada del plano técnico

Las identidades del agente no tienen credenciales propias. La plantilla de identidad del agente contiene las credenciales (FIC de identidad administrada, certificado o secreto de cliente) y emite tokens en nombre de sus identidades de agente secundarias mediante un intercambio de dos pasos. Para más información, consulte flujo OAuth de la aplicación independiente.

  1. La plantilla se autentica y obtiene un token T1 de intercambio de identidad federada:

    • {blueprint-credential} es el token MSI del plano técnico JWT firmado por certificado o la aserción de token de intercambio secreto, según la configuración del plano técnico.
    POST https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/token
    Content-Type: application/x-www-form-urlencoded
    
    client_id={blueprint-app-id}
    &scope=api%3A%2F%2FAzureADTokenExchange%2F.default
    &fmi_path={agent-identity-app-id}
    &client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
    &client_assertion={blueprint-credential}
    &grant_type=client_credentials
    
  2. La identidad del agente intercambia T1 por el token de recurso de observabilidad de Agent 365:

    POST https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/token
    Content-Type: application/x-www-form-urlencoded
    
    client_id={agent-identity-app-id}
    &scope=9b975845-388f-4429-889e-eab1ef63949c%2F.default
    &client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
    &client_assertion={T1}
    &grant_type=client_credentials
    
    • El token devuelto tiene appid/azp = {agent-identity-app-id}, roles que contiene Agent365.Observability.OtelWritey .aud = 9b975845-...
    • Usa este token en la ruta /observabilityService/.../traces.
    • La URL {agentId} es el appId de identidad del agente, no el appId del blueprint.

OBO, aplicación estándar de Microsoft Entra

Reciba el token entrante del usuario Tc de quien realiza la llamada ascendente (Bearer o PFAT) y, a continuación, intercámbielo:

POST https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

client_id={your-app-id}
&scope=9b975845-388f-4429-889e-eab1ef63949c%2FAgent365.Observability.OtelWrite
&client_secret={secret}
&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&assertion={Tc}
&requested_token_use=on_behalf_of

Para la autenticación mediante certificado, reemplace client_secret={secret} por el mismo par client_assertion_type + client_assertion que en S2S.

El token devuelto tiene appid/azp = {your-app-id}, scp que contiene Agent365.Observability.OtelWritey .aud = 9b975845-... Úselo en la ruta /observability/.../traces. Se devuelve además un token de actualización; guárdelo en caché y reutilícelo en lugar de repetir el intercambio en cada llamada.

OBO, identidad de agente derivada de plano técnico (incluyendo compañero de equipo con IA)

Hay tres pasos principales del flujo con derechos delegados. Para obtener más información, consulte Flujos de OAuth del agente: flujo con derechos delegados.

  1. Reciba el token Tcde usuario . Para un compañero de equipo de IA, este token representa la propia cuenta de usuario del agente; de lo contrario, representa al autor de la llamada humana.

  2. El plano técnico autentica y obtiene T1, igual que el flujo de identidad del agente derivado del plano técnico S2S.

  3. La identidad del agente intercambia T1 y Tc por un token de recurso delegado:

    POST https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/token
    Content-Type: application/x-www-form-urlencoded
    
    client_id={agent-identity-app-id}
    &scope=9b975845-388f-4429-889e-eab1ef63949c%2FAgent365.Observability.OtelWrite
    &client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
    &client_assertion={T1}
    &grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
    &assertion={Tc}
    &requested_token_use=on_behalf_of
    

El token devuelto tiene appid/azp = {agent-identity-app-id}, scp que contiene Agent365.Observability.OtelWritey representa el usuario del agente. Úselo en la ruta /observability/.../traces. La URL {agentId} es el appId de identidad del agente, no el appId del blueprint. Se devuelve también un token de actualización; guárdelo en caché y reutilícelo.

Declaraciones obligatorias en el token devuelto

Ruta S2S (/observabilityService/...) - token solo para aplicación:

Reclamación Valor requerido
aud 9b975845-388f-4429-889e-eab1ef63949c (o api://9b975845-...)
roles Debe contener Agent365.Observability.OtelWrite
appid (v1) o azp (v2) Debe ser igual a la dirección URL {agentId}
scp Debe estar ausente

Ruta delegada (/observability/...): token delegado por el usuario (portador o PFAT):

Reclamación Valor requerido
aud 9b975845-388f-4429-889e-eab1ef63949c (o api://9b975845-...)
scp Debe contener Agent365.Observability.OtelWrite
appid / azp Debe ser igual a la dirección URL {agentId}

La ruta delegada acepta tokens Bearer y MSAuth1.0 PFAT . Los autores de llamadas directos deben usar Bearer. Si no sabe cuál tiene, use Bearer.

Endpoints

Dos rutas; elija en función de cómo se autentica su servicio, no de lo que hace el usuario:

POST https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1   # S2S
POST https://agent365.svc.cloud.microsoft/observability/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1          # OBO

Encabezados:

Authorization: Bearer <token>      # or MSAuth1.0 ... for delegated PFAT
Content-Type: application/json

Parámetros de dirección URL

  • {tenantId}: el GUID de inquilino de cliente. El servidor considera este valor como autoritario. Si tus spans están configurados microsoft.tenant.id y no coinciden, el servidor rechaza la solicitud.
  • {agentId} : el appId de la aplicación que realiza la llamada (también OAuth client_id). Para las identidades derivadas de plantilla, este valor es la identidad del agente, no el appId de la plantilla. Debe coincidir con la declaración appid o azp de su token.
  • api-version=1 -Obligatorio.

Comprobar la elegibilidad del inquilino

Las integraciones de terceros integradas que utilizan el modelo de autenticación S2S pueden comprobar si un cliente inquilino es elegible para la observabilidad del Agente 365 antes de habilitar una integración o enviar telemetría. Esta comprobación puede ayudar a las integraciones a evitar enviar telemetría para inquilinos que actualmente no son elegibles.

Usa el mismo token de solo aplicación descrito en la autenticación S2S. El token debe contener el rol de aplicación Agent365.Observability.OtelWrite, y la notificación tid debe coincidir con {tenantId} en la URL de solicitud.

GET https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/eligibility?api-version=1
Authorization: Bearer <access-token>

Una respuesta exitosa contiene el resultado de elegibilidad:

{
  "enabled": true
}

Gestiona la respuesta de la siguiente manera:

Situación Meaning Acción del cliente
200 OK, enabled: true El inquilino es elegible para observabilidad. La integración puede enviar telemetría.
200 OK, enabled: false El arrendatario no cumple actualmente los requisitos para la observabilidad. No envíes telemetría. Verifica que el inquilino cumpla los requisitos previos y vuelve a comprobar cuando cambie su estado. Si se envía telemetría de todos modos, el punto final de ingestión puede regresar 200 OK mientras rechaza los tramos.
400 Bad Request {tenantId} está vacía o no es válida. Corrige el ID del inquilino antes de volver a intentarlo.
401 Unauthorized Falta el token de access o no es válido. Obtén un token válido para el recurso de observabilidad de Agent 365.
403 Forbidden El token carece del rol de aplicación requerido o su inquilino no coincide con {tenantId}. Corrige la discrepancia de permiso, consentimiento o inquilino antes de volver a intentarlo.
429 Too Many Requests El llamante superó el límite de elegibilidad solicitado. Honra Retry-After y vuelve a intentarlo con una retirada y giro.
503 Service Unavailable No se pudo determinar la elegibilidad. La respuesta no tiene cuerpo. Respeta Retry-After: 30 y vuelve a intentarlo. No trates esta respuesta como enabled: false.

Codificación del cuerpo de la solicitud

El cuerpo utiliza el formato estándar OTLP/HTTP+JSON: un ExportTraceServiceRequest con resourceSpansscopeSpansspans. Tenga en cuenta los detalles siguientes:

  • Enviar traceId (16 bytes) y spanId (8 bytes) como cadenas hexadecimales minúsculas.
  • startTimeUnixNano y endTimeUnixNano son cadenas que contienen nanosegundos de la época Unix.
  • kind es el valor entero de enum OTLP (por ejemplo, 1 para INTERNAL). status.code es el enum entero (por ejemplo, 1 para OK, 2 para ERROR).
  • Envía todos los valores de los atributos como stringValue.

Forma de respuesta

Una 200 OK respuesta significa que el Agente 365 ha procesado la solicitud. No garantiza que todos los tramos hayan sido dirigidos a un destino. Inspecciona tanto partialSuccess como results.

El results array informa del resultado para cada tramo en cada destino aplicable:

  • sent - el tramo se dirigía hasta el destino.
  • rejected: el tramo no se enrutó. El reason campo explica por qué.
  • not_routed - el destino no fue seleccionado para el tramo. El reason campo explica por qué.

Por ejemplo, un tramo enrutado correctamente puede devolver:

{
  "partialSuccess": {
    "rejectedSpans": 0,
    "errorMessage": ""
  },
  "results": [
    {
      "spanId": "0123456789abcdef",
      "sinks": {
        "flashpoint": {
          "status": "sent"
        },
        "sentinel": {
          "status": "sent"
        },
        "esp": {
          "status": "sent"
        }
      }
    }
  ]
}

Si el inquilino no es elegible, la solicitud aún puede devolverse 200 OK. En ese caso, results indica que los intervalos fueron rechazados:

{
  "partialSuccess": {
    "rejectedSpans": 0,
    "errorMessage": ""
  },
  "results": [
    {
      "spanId": "0123456789abcdef",
      "sinks": {
        "flashpoint": {
          "status": "rejected",
          "reason": "tenant_not_licensed"
        },
        "sentinel": {
          "status": "rejected",
          "reason": "tenant_not_licensed"
        },
        "esp": {
          "status": "rejected",
          "reason": "tenant_not_licensed"
        }
      }
    }
  ]
}

Para decisiones de enrutamiento de petición completa, partialSuccess.rejectedSpans puede permanecer 0 incluso cuando results muestra que todos los tramos fueron rechazados. No uses partialSuccess ni el estado HTTP por sí solo como prueba de ingestión. Los nombres de campo se escriben en camelCase en la transmisión. Consulta Límites y condiciones de descarte para conocer otros motivos por los que la telemetría podría no aparecer.

Solicitud más pequeña posible

La prueba de extremo a extremo más sencilla envía un único invoke_agent span. Este intervalo es el cuerpo más pequeño que llega a Microsoft Defender.

Paso 1. Obtenga un token Bearer. Para S2S, use las credenciales de cliente con ámbito 9b975845-388f-4429-889e-eab1ef63949c/.default (consulte Recetas de autenticación para la receta completa).

Paso 2. POST un solo intervalo:

TOKEN="$(./get-token.sh)"
TENANT_ID="<customer-tenant-guid>"
AGENT_ID="<your-agent-app-id>"

curl -i -X POST \
  "https://agent365.svc.cloud.microsoft/observabilityService/tenants/${TENANT_ID}/otlp/agents/${AGENT_ID}/traces?api-version=1" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  --data @- <<EOF
{
  "resourceSpans": [{
    "scopeSpans": [{
      "scope": { "name": "my-instrumentation", "version": "1.0.0" },
      "spans": [{
        "traceId": "0102030405060708090a0b0c0d0e0f10",
        "spanId":  "1111111111111111",
        "parentSpanId": "",
        "name": "invoke_agent",
        "kind": 1,
        "startTimeUnixNano": "1736175600000000000",
        "endTimeUnixNano":   "1736175601500000000",
        "status": { "code": 1 },
        "attributes": [
          { "key": "gen_ai.operation.name", "value": { "stringValue": "invoke_agent" } },
          { "key": "gen_ai.agent.id",       "value": { "stringValue": "${AGENT_ID}" } },
          { "key": "gen_ai.agent.name",     "value": { "stringValue": "MyAgent" } },
          { "key": "microsoft.a365.agent.blueprint.id", "value": { "stringValue": "${AGENT_ID}" } },
          { "key": "gen_ai.conversation.id","value": { "stringValue": "conv-001" } },
          { "key": "microsoft.channel.name","value": { "stringValue": "web" } },
          { "key": "user.id",               "value": { "stringValue": "<entra-user-objectid>" } },
          { "key": "client.address",        "value": { "stringValue": "10.1.2.80" } },
          { "key": "server.address",        "value": { "stringValue": "myagent.example.com" } },
          { "key": "server.port",           "value": { "stringValue": "443" } },
          { "key": "gen_ai.input.messages", "value": { "stringValue": "[{\"role\":\"user\",\"content\":\"hi\"}]" } },
          { "key": "gen_ai.output.messages","value": { "stringValue": "[{\"role\":\"assistant\",\"content\":\"hello\"}]" } }
        ]
      }]
    }]
  }]
}
EOF

Paso 3. Espere 200 OK, luego inspeccione results como se describe en la estructura de la respuesta. Confirma que los destinos aplicables tienen un estado de sent.

Paso 4. Confirme que los datos han llegado realmente. Un 200 OK no es prueba de ingestión; consulta Verificando la ingesta para el flujo de verificación. Para hacer un POST con un archivo de cuerpo guardado en su lugar, sustituya --data @- <<EOF ... EOF por --data @./otlp-request.json.

Ejemplo de ejecución del agente

Un usuario de Microsoft Teams pregunta "¿Cuál es el tiempo en Seattle?". El agente llama a una GetWeather función, le pide a un LLM que dé formato a la respuesta y responde. Esa ejecución única es de cuatro intervalos:

graph TD
    A["<b>invoke_agent</b> · spanId=A · parentSpanId=∅<br/><i>root - the run itself</i>"]
    B["<b>chat</b> · spanId=B · parentSpanId=A<br/><i>LLM picks the tool / formats reply</i>"]
    C["<b>execute_tool</b> · spanId=C · parentSpanId=A<br/><i>the GetWeather call</i>"]
    D["<b>output_messages</b> · spanId=D · parentSpanId=A<br/><i>final reply emitted to the user</i>"]
    A --> B
    A --> C
    A --> D

Atributos de todo el tramo establecidos para cada tramo:

Attribute Ejemplo de valor
traceId 0102030405060708090a0b0c0d0e0f10
gen_ai.conversation.id 19:abc@thread.tacv2
microsoft.session.id session-1234
microsoft.channel.name msteams
gen_ai.agent.id <AGENT_APP_ID>
gen_ai.agent.name WeatherBot
microsoft.a365.agent.blueprint.id <BLUEPRINT_APP_ID>
user.id <entra-user-objectid>
client.address 10.1.2.80
server.address weatherbot.example.com
server.port 443

Importante

Estos atributos a nivel de ejecución no se propagan automáticamente. Debes ajustar gen_ai.conversation.id, microsoft.channel.name, y microsoft.session.id en cada tramo.

Tramo A: invoke_agent (raíz)

{
  "traceId": "0102030405060708090a0b0c0d0e0f10",
  "spanId": "1111111111111111",
  "parentSpanId": "",
  "name": "invoke_agent",
  "kind": 1,
  "startTimeUnixNano": "1736175600000000000",
  "endTimeUnixNano":   "1736175601500000000",
  "status": { "code": 1 },
  "attributes": [
    { "key": "gen_ai.operation.name",   "value": { "stringValue": "invoke_agent" } },
    { "key": "gen_ai.execution.type",   "value": { "stringValue": "HumanToAgent" } },
    { "key": "gen_ai.input.messages",   "value": { "stringValue": "[{\"role\":\"user\",\"content\":\"What's the weather in Seattle?\"}]" } },
    { "key": "gen_ai.output.messages",  "value": { "stringValue": "[{\"role\":\"assistant\",\"content\":\"It's 65F and partly cloudy in Seattle.\"}]" } },
    { "key": "user.email",              "value": { "stringValue": "alice@contoso.com" } }
    /* plus all the run-wide attributes listed above */
  ]
}

Tramo B: chat (llamada al LLM)

{
  "traceId": "0102030405060708090a0b0c0d0e0f10",
  "spanId": "2222222222222222",
  "parentSpanId": "1111111111111111",
  "name": "chat",
  "kind": 1,
  "startTimeUnixNano": "1736175600200000000",
  "endTimeUnixNano":   "1736175600900000000",
  "status": { "code": 1 },
  "attributes": [
    { "key": "gen_ai.operation.name",      "value": { "stringValue": "chat" } },
    { "key": "gen_ai.request.model",       "value": { "stringValue": "gpt-4o" } },
    { "key": "gen_ai.provider.name",       "value": { "stringValue": "openai" } },
    { "key": "gen_ai.usage.input_tokens",  "value": { "stringValue": "42" } },
    { "key": "gen_ai.usage.output_tokens", "value": { "stringValue": "23" } }
    /* plus all the run-wide attributes */
  ]
}

Tramo C: execute_tool

{
  "traceId": "0102030405060708090a0b0c0d0e0f10",
  "spanId": "3333333333333333",
  "parentSpanId": "1111111111111111",
  "name": "execute_tool",
  "kind": 1,
  "startTimeUnixNano": "1736175600950000000",
  "endTimeUnixNano":   "1736175601200000000",
  "status": { "code": 1 },
  "attributes": [
    { "key": "gen_ai.operation.name",      "value": { "stringValue": "execute_tool" } },
    { "key": "gen_ai.tool.name",           "value": { "stringValue": "GetWeather" } },
    { "key": "gen_ai.tool.type",           "value": { "stringValue": "function" } },
    { "key": "gen_ai.tool.call.id",        "value": { "stringValue": "call-001" } },
    { "key": "gen_ai.tool.call.arguments", "value": { "stringValue": "{\"location\":\"Seattle\"}" } },
    { "key": "gen_ai.tool.call.result",    "value": { "stringValue": "{\"tempF\":65,\"condition\":\"partly cloudy\"}" } }
    /* plus all the run-wide attributes */
  ]
}

Intervalo D: output_messages

{
  "traceId": "0102030405060708090a0b0c0d0e0f10",
  "spanId": "4444444444444444",
  "parentSpanId": "1111111111111111",
  "name": "output_messages",
  "kind": 1,
  "startTimeUnixNano": "1736175601400000000",
  "endTimeUnixNano":   "1736175601500000000",
  "status": { "code": 1 },
  "attributes": [
    { "key": "gen_ai.operation.name",  "value": { "stringValue": "output_messages" } },
    { "key": "gen_ai.output.messages", "value": { "stringValue": "[{\"role\":\"assistant\",\"content\":\"It's 65F and partly cloudy in Seattle.\"}]" } }
    /* plus all the run-wide attributes */
  ]
}

Envío de telemetría

Usa un SDK OTel

La mayoría de los socios envían trazas mediante un SDK de OTel en lugar de HTTP implementado manualmente. El SDK controla el procesamiento por lotes, el reintento y la codificación OTLP/HTTP+JSON. Configure el punto de conexión del exportador e inyecte el encabezado Authorization.

El punto de conexión del exportador es la propia dirección URL de ruta, incluida la cadena de consulta:

https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1

(Use /observability/... en lugar de /observabilityService/... para la ruta delegada).

Python

from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

exporter = OTLPSpanExporter(
    endpoint="https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1",
    headers={"Authorization": f"Bearer {token}"},
)

Paquete: opentelemetry-exporter-otlp-proto-http.

Node.js/TypeScript

import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";

const exporter = new OTLPTraceExporter({
  url: "https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1",
  headers: { Authorization: `Bearer ${token}` },
});

Paquete: @opentelemetry/exporter-trace-otlp-http.

.NET

using OpenTelemetry.Exporter;

services.AddOpenTelemetry().WithTracing(b => b
    .AddOtlpExporter(o =>
    {
        o.Endpoint = new Uri("https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1");
        o.Headers = $"Authorization=Bearer {token}";
        o.Protocol = OtlpExportProtocol.HttpJson;
    }));

Paquete: OpenTelemetry.Exporter.OpenTelemetryProtocol.

HTTP manual

Si no puede o no desea usar un SDK de OTel, compile la solicitud OTLP/HTTP+JSON usted mismo y POST. La especificación OTLP/HTTP+JSON de OpenTelemetry define la estructura del cuerpo:

{
  "resourceSpans": [{
    "resource":  { "attributes": [ ... ] },          // optional
    "scopeSpans": [{
      "scope":  { "name": "<your-instrumentation>", "version": "1.0.0" },
      "spans":  [ <span>, <span>, ... ]
    }]
  }]
}

Cada <span> es un objeto cuyos campos obligatorios son traceId, spanId, namekindstartTimeUnixNanoendTimeUnixNano, attributes, y (para intervalos que no son raíz). parentSpanId Para reglas de codificación (tiempos codificados por cadena, hexadecimaltraceId / spanId, entero / kindstatus.code, todos los valores de atributos como stringValue), véase Endpoints y codificación de cuerpos de solicitud.

El conjunto de atributos que se va a establecer en cada intervalo se define en Contratos de mensajes. Para la lista completa de atributos, véase Referencia de atributos. Consulte el Ejemplo de ejecución del agente para ver un ejemplo funcional integral con el token de portador en el encabezado y el cuerpo en línea.

Puede enviar todos los intervalos de una ejecución en un único cuerpo POST (preferido: una solicitud, un seguimiento) o en varios POST. El servidor reconstruye la ejecución a partir de traceId + parentSpanId + gen_ai.conversation.id, por lo que cada span contiene suficiente información para correlacionarse en ambos sentidos.

Contratos de mensajes

Esta sección define qué intervalos puede emitir y qué atributos van en cada uno. Para obtener la especificación completa de atributos por atributo, consulte la referencia de atributo.

Tipos de operación

Cada intervalo que envíe debe tener gen_ai.operation.name configurado con uno de estos cuatro valores (sin distinción entre mayúsculas y minúsculas). El servidor elimina cualquier espacio con un valor faltante o no reconocido y lo cuenta en partialSuccess.rejectedSpans.

gen_ai.operation.name Meaning Gotcha más googleada
invoke_agent Una invocación de un agente. La "raíz" de la ejecución de un agente. Necesario para que la ejecución aparezca en las vistas de actividad del agente de Microsoft Defender o en el centro de administración de Microsoft 365. Sin ella, la telemetría solo aparece en la búsqueda avanzada de Microsoft Defender (CloudAppEvents).
execute_tool Una llamada de herramienta o función realizada por un agente. --
chat Una llamada de inferencia de LLM. Use el literal chat, NOT inference.
output_messages Mensaje de salida final emitido. --

Jerarquía de intervalos y agrupación de ejecución

Agent 365 reconstruye una ejecución a partir de la gráfica estándar de intervalos de OTLP (traceId, spanId, parentSpanId), junto con los atributos globales de la ejecución de la Referencia de atributos.

Seis reglas:

  1. Establezca siempre parentSpanId en cada span no raíz. Sin él, no puedes reconstruir la estructura del árbol de la partida.
  2. Reutiliza el mismo traceId en cada tramo de una ejecución.
  3. Establezca gen_ai.conversation.id en cada intervalo con el mismo valor. Este valor es la clave principal de unión para "todos los tramos en esta ejecución". No se propaga automáticamente.
  4. Establezca microsoft.channel.name en cada intervalo con el mismo valor. Los intervalos de herramientas a los que les faltan el canal o la conversación pueden heredarlos de su intervalo principal invoke_agentsolo si el intervalo principal está en la misma solicitud OTLP, así que configúrelos usted mismo en cada intervalo.
  5. Establezca microsoft.session.id en cada intervalo cuando tenga una sesión lógica.
  6. En las llamadas de agente a agente en las que el agente secundario está en una solicitud independiente, reutilice el mismo gen_ai.conversation.id y use los atributos microsoft.a365.caller.agent.* (consulte Referencia de atributos) para capturar el contexto del agente que llama.

El árbol de cuatro intervalos del ejemplo de ejecución del Agente es la forma canónica.

Formas de ejecución comunes

Forma Intervalos para emitir Notas
Chatbot de un solo agente (sin herramientas, sin segmento de LLM) Solo un invoke_agent Establezca atributos para toda la ejecución, además de gen_ai.input.messages y gen_ai.output.messages. Idéntico a la solicitud más pequeña posible.
Agente con herramientas (más comunes) invoke_agent raíz + chat, execute_tool, output_messages secundarios Todos los elementos secundarios comparten los valores traceId y parentSpanId = root.spanId del elemento raíz. Todos tienen los mismos atributos para toda la ejecución. Consulte Ejemplo de ejecución del agente para obtener un ejemplo completo.
Agente a agente Cada agente emite su propio invoke_agent Reutilice el mismo gen_ai.conversation.id en ambos agentes. En el invoke_agent del destino, establezca gen_ai.execution.type = "Agent2Agent" y los atributos microsoft.a365.caller.agent.* (el appId del agente que realiza la llamada, el nombre, el blueprint appId, el identificador de usuario y el correo electrónico). Si el agente que realiza la llamada no tiene un registro de Entra, use microsoft.a365.caller.agent.platform.id y gen_ai.caller.agent.type en su lugar.

Lista de verificación para la puesta en producción

Ejecute esta lista de comprobación antes de ir a producción.

Categoría Activar
Auth Su aplicación Entra (o plantilla) está registrada y puede acuñar tokens para esta.
Auth Tu aplicación tiene concedido Agent365.Observability.OtelWrite (rol de aplicación para S2S, alcance para permisos delegados).
Auth Cada agente tiene su propio appId de Entra, como {agentId} en la URL. Para las identidades derivadas de plantillas, esta appId es la identidad del agente, no el appId de la plantilla. Si el agente no tiene registro de Entra, vea Selección de valores.
Auth Un administrador del inquilino otorga el consentimiento para Agent365.Observability.OtelWrite. Sin consentimiento, los tokens se emiten sin el rol o alcance y las solicitudes se rechazan con 403.
Licencias Al menos un usuario del tenant del cliente tiene asignada una licencia de Microsoft 365 E7 o Microsoft Agent 365 (es decir, una asignación real, no solo la presencia del SKU en el tenant). Sin una licencia asignada, las respuestas results muestran que los tramos fueron rechazados. Consulte Requisitos previos.
Intervalos Cada intervalo establece los aspectos básicos de toda la ejecución (jerarquía de intervalos y agrupación de ejecución).
Intervalos invoke_agent conjunto de intervalos gen_ai.input.messages y gen_ai.output.messages.
Intervalos execute_tool conjunto de intervalos gen_ai.tool.name, gen_ai.tool.type, gen_ai.tool.call.id, gen_ai.tool.call.arguments, gen_ai.tool.call.result.
Intervalos chat conjunto de intervalos gen_ai.request.model y gen_ai.provider.name (y, idealmente, gen_ai.usage.input_tokens / gen_ai.usage.output_tokens - codificado como cadena).
Intervalos Todos los intervalos no raíz establecidos parentSpanId; todos los intervalos de una ejecución comparten el mismo traceId.
Carga útil El cuerpo de la solicitud es de ≤ 1 MB.
Comprobación Inspeccionas tanto partialSuccess como results en cada respuesta y registras los rechazos.
Comprobación Ejecutaste el flujo de verificación en Verificación de la ingesta, comparándolo con tus primeras ejecuciones.

Pasos siguientes