Интеграция наблюдаемости агента с помощью прямого OTel

Это руководство проведёт вас сквозь этап отправки телеметрии агента Агенту 365 напрямую через OpenTelemetry (OTLP/HTTP+JSON). Перед началом ознакомьтесь с концепциями наблюдаемости агента 365 , чтобы понять модель, потоки аутентификации и поверхности, на которые попадают ваши данные.

Important

Прямой путь OTel — исключение, а не по умолчанию. Используйте его только если у вас уже есть конвейер OpenTelemetry, ваш фреймворк не может использовать SDK Agent 365 или ваш агент работает на языке, который SDK пока не поддерживает (например, Java). Для всех остальных рекомендуемый путь — Microsoft OpenTelemetry Distro, который обеспечивает единый SDK наблюдаемости для Agent 365, Microsoft Foundry, Azure Monitor и других. Прежний SDK Observability продолжает работать без нарушений изменений, но больше не рекомендуется для новых интеграций; Руководство по миграции для существующих пользователей SDK скоро будет.

Prerequisites

Убедитесь, что следующие конфигурации приведены до начала телеметрии.

Кто What
Администрирование арендаторов Зарегистрируйтесь в Agent 365 и дайте согласие на оформление вашего приложения для агента. См. На борту агента 365. Без лицензированного арендатора входящий запрос тихо прекращается — запрос возвращается 200 OK , partialSuccess: null но данные так и не появляются дальше.
Администрирование арендаторов Assign Microsoft 365 лицензии E7 или Microsoft Agent 365 как минимум одному пользователю в арендаторе. Наличие SKU недостаточно. Назначение пользователю запускает рабочий процесс Defender backend, который позволяет внедрять процесс. Без присвоенной лицензии запросы возвращаются 200 OK , partialSuccess: null а данные тихо исчезают.
Администрирование арендаторов Дайте согласие арендатора. См. Доступ агентов грантов к Microsoft 365 ресурсам. Без него токены выдаются без роли/области и запросы возвращаются 403.
Ваша команда разработчиков Зарегистрируйте своё приложение (стандартное приложение Microsoft Entra или blueprint). См. Начать с разработкой Agent 365.
Ваша команда разработчиков Добавить Agent365.Observability.OtelWrite в раздел API ( роль приложения для S2S, область для делегированных). Для чертежей см. раздел Configure inheritable permissions. Координируйтесь с командой по онбордингу Агента 365, чтобы получить разрешение.

Рецепты аутентификации

Все четыре рецепта используют стандартную точку токена Microsoft Entra:

Поле Ценность
Конечная точка токена https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/token
Ресурс (aud в возвращаемом токене) 9b975845-388f-4429-889e-eab1ef63949c (также принимается api://9b975845-388f-4429-889e-eab1ef63949c)
Сфера применения S2S 9b975845-388f-4429-889e-eab1ef63949c/.default
Телескоп OBO 9b975845-388f-4429-889e-eab1ef63949c/Agent365.Observability.OtelWrite

Рецепты ниже показывают необработанный HTTP для ясности. В производстве предпочитаю Microsoft. Identity.Web или другой библиотеке MSAL, которая занимается обновлением и кэшированием токенов.

Какой рецепт мне нужен?

Моя модель приложения Мой поток OAuth Перейти к
Стандартная регистрация приложений Microsoft Entra S2S (учетные данные клиента) S2S, стандартное Microsoft Entra приложение
Стандартная регистрация приложений Microsoft Entra OBO (делегированная) OBO, стандартное Microsoft Entra приложение
Идентичность агента, полученная из чертежа S2S (учетные данные клиента) S2S, идентичность агента, полученная из чертежа
Идентичность агента, полученная из чертежа OBO / AI по команде OBO, идентичность агента, полученного из чертежа

S2S, Standard Microsoft Entra app

Один POST на токен-эндпоинт арендатора с grant_type=client_credentials. Аутентификация приложения с помощью секрета клиента, сертификата (подписанного утверждения JWT) или управляемой личности или федеративного учетного данных.

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

Возвращённый токен имеет appidazp/ = {your-app-id}, roles содержащий Agent365.Observability.OtelWrite, и .aud = 9b975845-... Используйте его на /observabilityService/.../traces маршруте.

Для аутентификации на основе сертификатов замените client_secret={secret} на client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={signed-jwt}.

S2S, идентичность агента, полученная из чертежа

У удостоверений агента нет собственных учетных данных. План идентификации агента хранит учетные данные (управляемый идентификатор FIC, сертификат или секрет клиента) и формирует токены от имени своих дочерних идентификаторов агентов через двухэтапный обмен. Для получения дополнительной информации смотрите автономное приложение OAuth flow.

  1. Чертеж аутентифицируется и получает федеративный токен T1обмена идентичностью:

    • {blueprint-credential} является MSI-токен чертежа, JWT с сертификатом или подтверждение секретного токена обмена — в зависимости от конфигурации чертежа.
    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. Идентичность агента обменивается T1 токен ресурса Observability 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
    
    • Возвращённый токен имеет appidazp/ = {agent-identity-app-id}, roles содержащий Agent365.Observability.OtelWrite, и .aud = 9b975845-...
    • Используйте этот жетон на /observabilityService/.../traces маршруте.
    • {agentId} URL — это идентификатор агента appId, а не blueprint appId.

OBO, Standard Microsoft Entra app

Получите входящий токен Tc пользователя от вашего входящего абонента (Bearer или PFAT), затем обменяйте его:

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

Для аутентификации сертификата замените client_secret={secret} на ту же client_assertion_type + client_assertion пару, что и в S2S.

Возвращённый токен имеет appidazp/ = {your-app-id}, scp содержащий Agent365.Observability.OtelWrite, и .aud = 9b975845-... Используйте его на /observability/.../traces маршруте. Рядом возвращается жетон обновления; Кэшировать и использовать его повторно вместо повторного запуска Exchange при каждом вызове.

OBO, идентичность агента, основанного на Blueprint (включая ИИ-напарника)

Существует три основных этапа перехода в сторону потока. Для получения дополнительной информации см. Агент OAuth flows: От имени потока.

  1. Получите пользовательский токен Tc. Для AI-члена команды этот токен представляет собственную учетную запись агента; в противном случае он представляет человеческого звона.

  2. Чертеж аутентифицируется и получает T1, тот же, что и поток идентичности агента, полученный из чертежа S2S.

  3. Идентичность агента обменивается T1 и Tc для делегированного токена ресурса:

    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
    

Возвращённый токен имеет appid = azp{agent-identity-app-id}/, scp содержащий Agent365.Observability.OtelWrite, и представляет пользователя агента. Используйте его на /observability/.../traces маршруте. {agentId} URL — это идентификатор агента appId, а не blueprint appId. Рядом возвращается жетон обновления; Кэшировать и использовать его повторно.

Требуемые претензии на возвращённый токен

Маршрут S2S (/observabilityService/...) — токен только для приложения:

Утверждение Обязательное значение
aud 9b975845-388f-4429-889e-eab1ef63949c (или api://9b975845-...)
roles Должно содержать Agent365.Observability.OtelWrite
appid (v1) или azp (v2) Должно быть равно URL {agentId}
scp Должно быть, отсутствует

Делегированный маршрут (/observability/...) — токен, делегированный пользователем (Bearer или PFAT):

Утверждение Обязательное значение
aud 9b975845-388f-4429-889e-eab1ef63949c (или api://9b975845-...)
scp Должно содержать Agent365.Observability.OtelWrite
appid / azp Должно быть равно URL {agentId}

Делегированный маршрут принимает и BearerMSAuth1.0 PFAT токены. Прямые звонящие должны использовать Bearer. Если вы не знаете, какой из них у вас, используйте Bearer.

Конечные точки

Два маршрута; выбирайте по тому, как ваш сервис аутентифицируется, а не по тому, что делает пользователь:

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

Заголовки:

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

Параметры URL-адреса

  • {tenantId} - клиент-арендатор GUID. Сервер рассматривает это как авторитет; Если ваши промежутки установлены microsoft.tenant.id , а система не согласна, запрос отклоняется.
  • {agentId} - appId вызывающего приложения (также OAuth client_id). Для идентичностей, полученных из чертежа, это идентификатор агента appId, а не blueprint appId. Должно быть равно appid / azp претензии на твой жетон.
  • api-version=1 - Обязательно.

Кодирование тела запроса

Корпус имеет стандартную форму OTLP/HTTP+JSON: с ExportTraceServiceRequestresourceSpansscopeSpansspans. Имейте в виду следующие детали:

  • traceId (16 байт) и spanId (8 байт) передаются в виде строчных шестигранных строк.
  • startTimeUnixNano / endTimeUnixNanoэто струны, удерживающие эпохальные наносекунды Unix.
  • kind — целочисленное значение enum OTLP (например 1 , для INTERNAL); status.code — целое число (например 1 , для OK, 2 для ERROR).
  • Все значения атрибутов передаются как stringValue.

Структура ответа

Успешный вызов возвращается 200 OK:

{ "partialSuccess": null }

Если некоторые отсеки были отклонены фильтром по пролёту:

{
  "partialSuccess": {
    "rejectedSpans": 2,
    "errorMessage": "Dropped 2 non-A365 span(s) ..."
  }
}

Имена полей — это camelCase on the wire. Всегда проверяйте partialSuccess: 200 с отклонёнными промежутками — это реальный результат, который вы должны получить. Лимиты и условия выпадения перечисляют случаи, когда 200 возвращается с partialSuccess: null тем, что данные не появляются дальше.

Минимальный возможный запрос

Самый простой сквозной тест отправляет один invoke_agent пролёт. Этот диапазон — самый маленький корпус, который попадает в Microsoft Defender.

Шаг 1. Получите жетон Носителя. Для S2S используйте учетные данные клиента с объёмом 9b975845-388f-4429-889e-eab1ef63949c/.default (см. рецепты аутентификации для полного рецепта).

Шаг 2. ПОСТ на одном пролёте:

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

Шаг 3. Ожидайте 200 OK от этого тела:

{ "partialSuccess": null }

Шаг 4. Подтвердите, что данные действительно приземлились. 200 OK — это не доказательство проглатывания; Проверка поедания проходит через процесс проверки. Чтобы ВЫЛОЖИТЬ сохранённый файл тела, замените --data @- <<EOF ... EOF на --data @./otlp-request.json.

Пример запуска агентов

Пользователь Microsoft Teams спрашивает: «Какая погода в Сиэтле?» Ваш агент вызывает функцию GetWeather , просит LLM отформатировать ответ и отвечает. Этот единственный пробег состоит из четырёх пролётов:

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

Характеристики по всему пробегу, установленные на каждом пролёте:

Атрибут Пример значения
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

Important

Эти общие характеристики не распространяются автоматически. Вы должны устанавливать gen_ai.conversation.id, microsoft.channel.nameи microsoft.session.id на каждом пролёте самостоятельно.

Span A: invoke_agent (корень)

{
  "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 */
  ]
}

Span B: chat (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 */
  ]
}

Span 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 */
  ]
}

Span 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 */
  ]
}

Передача телеметрии

Использование OTel SDK

Большинство партнёров отправляют трассировки через OTel SDK, а не через вручную свернутый HTTP. SDK отвечает за пакетирование, повторное тестирование и кодирование OTLP/HTTP+JSON за вас. Задайте конечную точку экспортера и введите заголовок Authorization .

Конечная точка экспортера — это сам URL маршрута, включая строку запроса:

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

(Используйте /observability/... вместо /observabilityService/... делегированного маршрута.)

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}"},
)

Пакет: 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}` },
});

Пакет: @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;
    }));

Пакет: OpenTelemetry.Exporter.OpenTelemetryProtocol.

Ручной HTTP

Если вы не можете или не хотите использовать OTel SDK, создайте запрос OTLP/HTTP+JSON самостоятельно и ОПУБЛИКУЙТЕ его. Форма корпуса определяется спецификацией OpenTelemetry OTLP/HTTP+JSON:

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

Каждый <span> — это объект, требуемые поля которого — traceId, spanId, name, endTimeUnixNanoattributeskindstartTimeUnixNanoи (для некорневых отсеков) . parentSpanId См. Endpoints и кодирование тел запроса для правил кодирования (размножение строк, шестнадцатеричное traceId / spanId,status.codekind / целое число , все значения атрибутов как ).stringValue

Набор атрибутов, которые нужно задать на каждом отсеке, определяется в контрактах сообщений. См. ссылку на атрибуты для полного списка атрибутов. Обратитесь к примеру запуска Agent для сквозной рабочей пробы с токен Bearer в заголовке и корпусом в строке.

Вы можете отправить все промежутки запуска в одном теле POST (предпочтительно — один запрос, одна трасса) или через несколько POST. Сервер восстанавливает пробег из traceId + + parentSpanIdgen_ai.conversation.id, так что каждый отсек несёт достаточно данных, чтобы коррелировать в любом случае.

Контракты сообщений

В этом разделе указано, какие промежутки можно излучать и какие атрибуты появляются на каждом. Полную спецификацию по атрибутам см. ссылку на атрибут.

Типы операций

Каждый отправленный вами диапазон должен иметь gen_ai.operation.name задание на одно из этих четырёх значений (без регистра). Любой промах с отсутствующим или нераспознанным значением бесшумно отбрасывается и засчитывается в partialSuccess.rejectedSpans.

gen_ai.operation.name Значение Самый часто гуглил, понял
invoke_agent Призыв агента. «Корень» агентского побега. Требуется для появления запуска в режиме agent-activity Microsoft Defender или в Центр администрирования Microsoft 365. Без него телеметрия попадает только в Microsoft Defender продвинутую охоту (CloudAppEvents).
execute_tool Вызов инструмента/функции, выполняемый агентом. --
chat Вызов вывода LLM. Используйте буквальное chat, НЕ inference.
output_messages Финальное исходное сообщение. --

Иерархия спанов и группировка забегов

Агент 365 восстанавливает запуск из стандартного графа OTLP span (traceId, spanIdparentSpanId, ) плюс атрибуты по всему run, исходя из ссылки на Attribute.

Шесть правил:

  1. Всегда готов parentSpanId на каждом некорневом расплетении. Без него древовидная структура трассы нельзя восстановить.
  2. Повторное использование того traceId же на каждом пролёте за пробежку.
  3. Устанавливайте gen_ai.conversation.id на каждый пролёт с одинаковым значением. Это основной ключ join для «всех пролетов в этом пробеге». Он не распространяется автоматически.
  4. Устанавливайте microsoft.channel.name на каждый пролёт с одинаковым значением. Отсутствующие канал или разговор могут наследовать их от родителя invoke_agentтолько если родитель находится в одном OTLP-запросе, поэтому устанавливайте их на каждый span самостоятельно.
  5. Ставьте microsoft.session.id на каждый пролёт , когда проходит логическая сессия.
  6. Для вызовов агент-агент, когда дочерний агент находится в отдельном запросе, используйте его gen_ai.conversation.id повторно и используйте microsoft.a365.caller.agent.* атрибуты ( см. ссылку на атрибуты) для захвата контекста вызывающего-агента.

Четырёхпролётное дерево в примере Agent run — это каноническая форма.

Распространённые формы пробежек

Форма Пролёты для излучения Примечания
Чат-бот с одним агентом (без инструментов, без обхвата LLM) Только один invoke_agent Задайте универсальные атрибуты плюс gen_ai.input.messages и gen_ai.output.messages. Идентично минимальному запросу.
Агент с инструментами (чаще всего встречается) invoke_agent корень + chat, execute_tool, output_messages потомки Все дети имеют traceId общие корни и наборы parentSpanId = root.spanId. Все они обладают одинаковыми характеристиками для общего бега. Полный пример см. пример Agent run .
Агент — агент Каждый агент излучает свой собственный invoke_agent Используйте одинаковое gen_ai.conversation.id для обоих агентов. В целевом invoke_agentнаборе gen_ai.execution.type = "Agent2Agent" и атрибутах microsoft.a365.caller.agent.* (агент вызова appId, имя, чертеж appId, user id и email). Если у звонящего агента нет регистрации Entra, используйте microsoft.a365.caller.agent.platform.id и gen_ai.caller.agent.type вместо этого.

Чек-лист адаптации

Пройдитесь по этому чек-листу перед тем, как идти в продакшн.

Category Проверьте
Проверка подлинности Ваше приложение Entra (или blueprint) зарегистрировано, и вы можете выпускать для него токены.
Проверка подлинности Ваша заявка одобрена Agent365.Observability.OtelWrite (роль в заявке для S2S, полномочия для делегирования).
Проверка подлинности У каждого агента есть свой собственный Entra appId , как {agentId} указано в URL. Для тождественностей, полученных из чертежа, этот appId является идентификатором агента appId, а не blueprint appId. Если у агента нет регистрации Entra, см. значения выбора.
Проверка подлинности Администратор арендатора дал согласие на Agent365.Observability.OtelWrite. Без согласия токены выпускаются без роли/сферы действия, а запросы отклоняются с 403помощью .
Лицензирование По крайней мере одному пользователю в клиентском арендаторе назначена лицензия Microsoft 365 E7 или Microsoft Agent 365 (присвояване, а не просто присутствие SKU в арендаторе). Без назначенной лицензии глотание молча прекращается. См. предварительные требования.
Диапазоны Каждый span задаёт основные значения для всего пробежки (иерархия спанов и группировка забегов).
Диапазоны invoke_agent охватывает множество gen_ai.input.messages и gen_ai.output.messages.
Диапазоны execute_toolПролёты заданы gen_ai.tool.name, gen_ai.tool.type, gen_ai.tool.call.id, gen_ai.tool.call.resultgen_ai.tool.call.arguments, .
Диапазоны chat spans set gen_ai.request.model и gen_ai.provider.name (и желательно gen_ai.usage.input_tokens / gen_ai.usage.output_tokens — закодированы строками).
Диапазоны Все некорневые расщепления множны parentSpanId; все расплёны в серии имеют одинаковое traceId.
Полезная нагрузка Тело запроса ≤ 1 МБ.
Проверка Вы анализируете partialSuccess каждый ответ и фиксируете отказы.
Проверка Вы запускали процесс верификации при проверке поедания по сравнению с первыми забегами.

Дальнейшие действия