Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Aprenda como integrar a observabilidade do agente com o Agent 365 enviando telemetria diretamente pelo OpenTelemetry (OTLP/HTTP+JSON). Essa abordagem ajuda agentes que não conseguem usar o SDK do Agente 365 ou a Distribuição Microsoft OpenTelemetry a enviar telemetria de forma eficiente e segura. Antes de começar, leia os conceitos de observabilidade do Agent 365 para entender o modelo, os fluxos de autenticação e onde seus dados aparecem.
Importante
O caminho OTel direto é a exceção, não o padrão. Use-o apenas se você já tiver um pipeline do OpenTelemetry, se sua estrutura não puder usar o SDK do Agent 365 ou se seu agente estiver em uma linguagem que o SDK ainda não suporta (como Java). Para todos os outros, o caminho recomendado é o Microsoft OpenTelemetry Distro, que fornece um SDK de observabilidade unificado para o Agent 365, Microsoft Foundry, Azure Monitor e outros. O SDK de Observabilidade anterior continua funcionando sem alterações interruptivas, mas não é mais recomendado para novas integrações; orientações de migração para usuários existentes do SDK estão a caminho.
Pré-requisitos
Garanta que as seguintes configurações sejam definidas antes de qualquer fluxo de telemetria.
| Quem | What |
|---|---|
| Administrador do locatário | Cadastre-se no Agent 365 e dê consentimento para seu aplicativo de agente. Veja Introdução ao Agent 365. Sem um locatário elegível, a ingestão pode retornar 200 OK mesmo que o results da resposta mostre que os intervalos foram rejeitados. |
| Administrador do locatário |
Atribua uma licença Microsoft 365 E7 ou Microsoft Agent 365 a pelo menos um usuário no locatário. A presença do SKU não é suficiente. A atribuição a um usuário inicia o fluxo de trabalho back-end do Defender que permite a ingestão. Sem uma licença atribuída, o processo de ingestão pode retornar 200 OK ao mesmo tempo que rejeita os spans. |
| Administrador do locatário | Dê consentimento ao locatário. Consulte Conceder aos agentes acesso aos recursos do Microsoft 365. Sem ele, os tokens são emitidos sem a função/o escopo e as solicitações retornam 403. |
| Sua equipe de desenvolvimento | Registre seu aplicativo (aplicativo padrão do Microsoft Entra ou blueprint). Veja Identidade do Agente. |
| Sua equipe de desenvolvimento | Adicione Agent365.Observability.OtelWrite em permissões de API (função de aplicativo para S2S, escopo para permissões delegadas). Para blueprints, confira Configurar permissões que podem ser herdadas. Coordene com a equipe de integração do Agent 365 para habilitar a permissão. |
Métodos de autenticação
As quatro receitas usam o endpoint de token padrão do Microsoft Entra:
| Campo | Valor |
|---|---|
| Ponto de extremidade de token | https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/token |
Recurso (aud no token retornado) |
9b975845-388f-4429-889e-eab1ef63949c (também aceita api://9b975845-388f-4429-889e-eab1ef63949c) |
| Escopo do S2S | 9b975845-388f-4429-889e-eab1ef63949c/.default |
| Escopo do OBO | 9b975845-388f-4429-889e-eab1ef63949c/Agent365.Observability.OtelWrite |
As receitas a seguir mostram HTTP puro para maior clareza. Em produção, use Microsoft.Identity.Web ou outra biblioteca MSAL, que gerencia a atualização de tokens e o armazenamento em cache.
De qual receita eu preciso?
| Meu modelo de aplicativo | Meu fluxo OAuth | Ir para |
|---|---|---|
| Registro de aplicativo padrão do Microsoft Entra | S2S (credenciais de cliente) | S2S, aplicativo padrão do Microsoft Entra |
| Registro de aplicativo padrão do Microsoft Entra | OBO (delegado) | OBO, aplicativo padrão do Microsoft Entra |
| Identidade de agente derivada do Blueprint | S2S (credenciais de cliente) | S2S, identidade de agente derivada do Blueprint |
| Identidade de agente derivada do Blueprint | OBO / colega de equipe de IA | OBO, identidade de agente derivada do Blueprint |
S2S, aplicativo padrão da Microsoft Entra
Envie uma requisição POST para o endpoint do token do locatário com grant_type=client_credentials. Autentique o aplicativo usando um segredo do cliente, um certificado (declaração JWT assinada), uma identidade gerenciada ou uma 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
O token retornado possui appid/azp = {your-app-id}, roles que contém Agent365.Observability.OtelWrite e aud = 9b975845-.... Use-o na rota /observabilityService/.../traces.
Para autenticação baseada em certificado, substitua client_secret={secret} por client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={signed-jwt}.
S2S, identidade de agente derivada do blueprint
As identidades dos agentes não têm credenciais próprias. O modelo de identidade do agente contém as credenciais (FIC de identidade gerenciada, certificado ou segredo do cliente) e emite tokens em nome das suas identidades de agente filhas por meio de um processo de troca em duas etapas. Para obter mais informações, consulte fluxo OAuth do aplicativo autônomo.
O blueprint se autentica e obtém um token de troca de identidade federada
T1:-
{blueprint-credential}é o token MSI do blueprint, o JWT assinado com certificado ou a asserção de token de troca baseada em segredo, de acordo com a configuração do blueprint.
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-
A identidade do agente troca
T1pelo token do recurso de observabilidade do 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- O token retornado possui
appid/azp={agent-identity-app-id},rolesque contémAgent365.Observability.OtelWriteeaud=9b975845-.... - Use este token na rota
/observabilityService/.../traces. - A URL
{agentId}é o appId da identidade do agente, não o appId do blueprint.
- O token retornado possui
OBO, aplicativo padrão da Microsoft Entra
Receba do chamador upstream o token de entrada do usuário Tc (Bearer ou PFAT) e, em seguida, troque-o:
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 autenticação por certificado, substitua client_secret={secret} pelo mesmo par client_assertion_type + client_assertion usado no S2S.
O token retornado possui appid/azp = {your-app-id}, scp que contém Agent365.Observability.OtelWrite e aud = 9b975845-.... Use-o na rota /observability/.../traces. Um token de atualização é retornado junto; armazene-o em cache e reutilize-o, em vez de executar nova troca em cada chamada.
OBO, identidade de agente derivada do blueprint (incluindo companheiro de equipe IA)
Existem três etapas principais para o fluxo On-Behalf-Of. Para obter mais informações, consulte Fluxos OAuth do agente: fluxo On-Behalf-Of.
Receba o token de usuário
Tc. Para um colega de equipe de IA, esse token representa a conta de usuário do próprio agente; caso contrário, representa o chamador humano.O blueprint autentica e obtém
T1, assim como no fluxo de identidade do agente derivado do blueprint S2S.A identidade do agente troca
T1eTcpor um 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
O token retornado tem appid/azp = {agent-identity-app-id}, scp contendo Agent365.Observability.OtelWrite e representa o usuário do agente. Use-o na rota /observability/.../traces. A URL {agentId} é o appId da identidade do agente, não o appId do blueprint. Um token de atualização é retornado junto; armazene-o em cache e reutilize-o.
Declarações obrigatórias no token devolvido
Rota S2S (/observabilityService/...) - token somente para aplicativo:
| Reclamação | Valor obrigatório |
|---|---|
aud |
9b975845-388f-4429-889e-eab1ef63949c (ou api://9b975845-...) |
roles |
Deve conter Agent365.Observability.OtelWrite |
appid (v1) ou azp (v2) |
Deve ser igual à URL {agentId} |
scp |
Deve estar ausente |
Rota delegada (/observability/...) - token delegado de usuário (Bearer ou PFAT):
| Reclamação | Valor obrigatório |
|---|---|
aud |
9b975845-388f-4429-889e-eab1ef63949c (ou api://9b975845-...) |
scp |
Deve conter Agent365.Observability.OtelWrite |
appid / azp |
Deve ser igual à URL {agentId} |
A rota delegada aceita os tokens Bearer e MSAuth1.0 PFAT. Chamadores diretos devem usar Bearer. Se você não sabe qual deles você tem, use Bearer.
Endpoints
Duas rotas; escolha com base em como seu serviço se autentica, não pelo que o usuário está fazendo:
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
Cabeçalhos:
Authorization: Bearer <token> # or MSAuth1.0 ... for delegated PFAT
Content-Type: application/json
Parâmetros de URL
-
{tenantId}- o GUID do locatário do cliente. O servidor trata esse valor como autoritativo. Se seus spans estiverem definidosmicrosoft.tenant.ide não coincidirem, o servidor rejeita o pedido. -
{agentId}– o appId do aplicativo de chamada (também conhecido comoclient_iddo OAuth). Para identidades derivadas de modelo, esse valor é o appId da identidade do agente, não o appId do modelo. Ele deve corresponder à declaraçãoappidouazpdo seu token. -
api-version=1- obrigatório.
Verifique a elegibilidade do inquilino
Integrações de terceiros incorporadas que utilizam o modelo de autenticação S2S podem verificar se um cliente é elegível para observabilidade do Agente 365 antes de habilitar uma integração ou enviar telemetria. Essa verificação pode ajudar integrações a evitar o envio de telemetria para inquilinos que atualmente não são elegíveis.
Use o mesmo token exclusivo de aplicativo descrito na autenticação S2S.
O token deve conter a Agent365.Observability.OtelWrite função do aplicativo, e sua tid declaração deve corresponder a {tenantId} na URL da requisição.
GET https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/eligibility?api-version=1
Authorization: Bearer <access-token>
Uma resposta bem-sucedida contém o resultado de elegibilidade:
{
"enabled": true
}
Trate a resposta da seguinte forma:
| Status | Meaning | Ação do cliente |
|---|---|---|
200 OK, enabled: true |
O locatário é elegível para observabilidade. | A integração pode enviar telemetria. |
200 OK, enabled: false |
No momento, o locatário não está qualificado para observabilidade. | Não envie telemetria. Verifique se o inquilino atende aos pré-requisitos e verifique novamente após suas mudanças de status. Se a telemetria for enviada mesmo assim, o endpoint de ingestão pode retornar 200 OK ao mesmo tempo que rejeita os spans. |
400 Bad Request |
{tenantId} é vazio ou inválido. |
Corrija o ID do inquilino antes de tentar novamente. |
401 Unauthorized |
O token de acesso está ausente ou inválido. | Obtenha um token válido para o recurso Agent 365 Observability. |
403 Forbidden |
O token não possui a função de aplicativo exigida, ou seu tenant não corresponde a {tenantId}. |
Corrija a permissão, consentimento ou incompatibilidade entre inquilinos antes de tentar novamente. |
429 Too Many Requests |
O interlocutor ultrapassou o limite de elegibilidade exigido. | Siga Retry-After e tente novamente com retirada e jitter. |
503 Service Unavailable |
A elegibilidade não pôde ser determinada. A resposta não tem corpo. | Respeite Retry-After: 30 e tente novamente. Não trate essa resposta como enabled: false. |
Codificação do corpo da solicitação
O corpo utiliza o formato padrão OTLP/HTTP+JSON: um ExportTraceServiceRequest com resourceSpans → scopeSpans → spans. Lembre-se dos seguintes detalhes:
- Enviar
traceId(16 bytes) espanId(8 bytes) como strings hexadecimais minúsculas. -
startTimeUnixNanoeendTimeUnixNanosão cadeias que contêm nanossegundos da época Unix. -
kindé o valor inteiro do enum OTLP (por exemplo,1paraINTERNAL).status.codeé o enum inteiro (por exemplo,1paraOK,2paraERROR). - Envie todos os valores de atributo como
stringValue.
Forma de resposta
Uma 200 OK resposta significa que o Agente 365 processou o pedido. Isso não garante que todo trecho tenha sido encaminhado a um destino. Inspecione tanto partialSuccess quanto results.
A matriz results informa o resultado para cada span em cada destino aplicável:
-
sent- o span foi encaminhado ao destino. -
rejected- o span não foi roteado. Oreasoncampo explica o motivo. -
not_routed- o destino não foi selecionado para o intervalo. Oreasoncampo explica o motivo.
Por exemplo, um span roteado com sucesso pode retornar:
{
"partialSuccess": {
"rejectedSpans": 0,
"errorMessage": ""
},
"results": [
{
"spanId": "0123456789abcdef",
"sinks": {
"flashpoint": {
"status": "sent"
},
"sentinel": {
"status": "sent"
},
"esp": {
"status": "sent"
}
}
}
]
}
Se o locatário não for elegível, a solicitação ainda poderá retornar 200 OK. Nesse caso, results indica que os intervalos foram rejeitados:
{
"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 decisões de roteamento da solicitação inteira, partialSuccess.rejectedSpans pode permanecer 0 mesmo quando results mostra que todos os spans foram rejeitados. Não use partialSuccess nem o status HTTP sozinho como prova de ingestão. Os nomes dos campos usarão camelCase na transmissão. Veja Limites e condições de descarte para conhecer outros motivos pelos quais a telemetria pode não aparecer.
A menor solicitação possível
O teste mais simples de ponta a ponta envia um único span invoke_agent. Esse span é o menor corpo de dados que chega ao Microsoft Defender.
Etapa 1. Obtenha um token de portador. Para S2S, utilize credenciais do cliente com o escopo 9b975845-388f-4429-889e-eab1ef63949c/.default (consulte Receitas de autenticação para a receita completa).
Etapa 2. Envie um único span via POST:
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
Etapa 3. Aguarde 200 OK, depois inspecione results conforme descrito em formato da resposta. Confirme que os destinos aplicáveis têm o status de sent.
Etapa 4. Confirme que os dados realmente chegaram. Um 200 OK não é prova de ingestão; veja Verificando a ingestão para o fluxo de verificação. Para enviar um arquivo de corpo já salvo via POST, substitua --data @- <<EOF ... EOF por --data @./otlp-request.json.
Exemplo de execução do agente
Um usuário do Microsoft Teams pergunta: "Como está o clima em Seattle?". Seu agente chama uma função GetWeather, pede a um LLM para formatar a resposta e responde. Essa única execução consiste em quatro spans:
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 definidos para toda a execução, aplicados em todos os spans:
| Attribute | Valor de exemplo |
|---|---|
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
Esses atributos em toda a execução não se propagam automaticamente. Você deve definir gen_ai.conversation.id, microsoft.channel.name e microsoft.session.id em cada span.
Span A: invoke_agent (raiz)
{
"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 (chamada de 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 */
]
}
Trecho 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 */
]
}
Enviar telemetria
Use um SDK do OTel
A maioria dos parceiros envia rastreamento por meio de um SDK do OTel, em vez de construir chamadas HTTP manualmente. O SDK cuida do envio em lote, das tentativas de reenvio e da codificação OTLP/HTTP+JSON para você. Defina o endpoint do exportador e injete o cabeçalho Authorization.
O endpoint do exportador é a própria URL da rota, incluindo a string de consulta:
https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1
(Use /observability/... em vez de /observabilityService/... para a rota 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}"},
)
Pacote: 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}` },
});
Pacote: @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;
}));
Pacote: OpenTelemetry.Exporter.OpenTelemetryProtocol.
Manual HTTP
Se você não puder ou não quiser usar um SDK do OTel, crie a solicitação OTLP/HTTP+JSON manualmente e envie-a via POST. A especificação OpenTelemetry OTLP/HTTP+JSON define a estrutura do corpo:
{
"resourceSpans": [{
"resource": { "attributes": [ ... ] }, // optional
"scopeSpans": [{
"scope": { "name": "<your-instrumentation>", "version": "1.0.0" },
"spans": [ <span>, <span>, ... ]
}]
}]
}
Cada <span> é um objeto cujos campos obrigatórios são traceId, spanId, name, kind, startTimeUnixNano, endTimeUnixNano, attributes e, para spans não raiz, parentSpanId. Para regras de codificação (tempos codificados como string, hexadecimal traceId / spanId, inteiro / kindstatus.code, todos os valores dos atributos como stringValue), veja Endpoints e Codificação do corpo da solicitação.
O conjunto de atributos a ser definido em cada span é especificado em Contratos de mensagem. Para a lista completa de atributos, veja Referência de atributos. Consulte o Exemplo de execução do agente para ver um exemplo funcional de ponta a ponta com o token de portador no cabeçalho e o corpo em linha.
Você pode enviar todos os spans de uma execução em um único corpo de POST (preferido - uma solicitação, um rastreamento) ou em vários POSTs. O servidor reconstrói a execução a partir de traceId + parentSpanId + gen_ai.conversation.id, de modo que cada span carregue informações suficientes para ser correlacionado de qualquer forma.
Contratos de mensagens
Esta seção define quais spans você pode emitir e quais atributos se aplicam a cada um. Para a especificação detalhada de cada atributo, consulte a Referência de atributo.
Tipos de operação
Cada span que você enviar deve ter gen_ai.operation.name definido como um destes quatro valores (não diferencia maiúsculas de minúsculas). O servidor elimina qualquer intervalo com valor faltante ou não reconhecido e o conta em partialSuccess.rejectedSpans.
gen_ai.operation.name |
Meaning | A pegadinha mais pesquisada no Google |
|---|---|---|
invoke_agent |
Uma invocação de um agente. A "raiz" de uma execução de agente. | Necessária para que a execução apareça nas exibições de atividade do agente no Microsoft Defender ou no centro de administração do Microsoft 365. Sem ela, a telemetria só chega à busca avançada do Microsoft Defender (CloudAppEvents). |
execute_tool |
Uma chamada à ferramenta ou função realizada por um agente. | -- |
chat |
Uma chamada de inferência de um modelo de linguagem grande (LLM). |
Use o literal chat, NÃO inference. |
output_messages |
Uma mensagem de saída final emitida. | -- |
Hierarquia de span e agrupamento de execução
O Agent 365 reconstrói uma execução a partir do grafo padrão do span OTLP (traceId, spanId, parentSpanId) mais os atributos de toda a execução provenientes da Referência de atributo.
Seis regras:
-
Sempre defina
parentSpanIdem cada span que não seja raiz. Sem ele, você não consegue reconstruir a estrutura da árvore da run. -
Reutilize o mesmo
traceIdem cada span de uma execução. -
Defina
gen_ai.conversation.idem cada span com o mesmo valor. Esse valor é a chave primária de junção para "todos os spans desta execução". Não é propagado automaticamente. -
Defina
microsoft.channel.nameem cada span com o mesmo valor. Spans de ferramenta sem canal ou conversa podem herdá-los do paiinvoke_agentapenas se o pai estiver na mesma requisição OTLP, então defina-os você mesmo em cada span. -
Defina
microsoft.session.idem cada span quando tiver uma sessão lógica. - Para chamadas entre agentes em que o agente filho está em uma requisição separada, reutilize o mesmo
gen_ai.conversation.ide use os atributosmicrosoft.a365.caller.agent.*(veja Referência de atributos) para capturar o contexto do agente chamador.
A árvore de quatro segmentos no exemplo de execução do agente é a forma canônica.
Formatos comuns de execução
| Forma | Spans a emitir | Notes |
|---|---|---|
| Chatbot com agente único (sem ferramentas, sem trecho de LLM) | Apenas um invoke_agent |
Defina atributos para toda a execução, além de gen_ai.input.messages e gen_ai.output.messages. Idêntico a Menor solicitação possível. |
| Agente com ferramentas (mais comum) |
invoke_agent raiz + chat, execute_tool, output_messages filhos |
Todos os filhos compartilham o traceId da raiz e definem parentSpanId = root.spanId. Todos carregam os mesmos atributos de toda a execução. Consulte Exemplo de execução do agente para ver um exemplo completo. |
| Agente para agente | Cada agente emite seu próprio invoke_agent |
Reutilize o mesmo gen_ai.conversation.id para ambos os agentes. No invoke_agent do destino, defina gen_ai.execution.type = "Agent2Agent" e os atributos microsoft.a365.caller.agent.* ( appId do agente de chamada, nome, appId do blueprint, id do usuário e email). Se o agente de chamada não tiver registro no Entra, use microsoft.a365.caller.agent.platform.id e gen_ai.caller.agent.type. |
Checklist para integração à produção
Revise esta lista de verificação antes de entrar em produção.
| Categoria | Verificação |
|---|---|
| Auth | Seu aplicativo Entra (ou blueprint) está registrado e você pode emitir tokens para ele. |
| Auth | Seu aplicativo recebeu Agent365.Observability.OtelWrite (função de aplicativo para S2S, escopo para acesso delegado). |
| Auth | Cada agente tem seu próprio appId do Entra, usado como {agentId} na URL. Para identidades derivadas de blueprint, esse appId é a identidade do agente, não o appId do blueprint. Se o agente não tiver nenhum registro do Entra, consulte Escolher valores. |
| Auth | Um administrador de inquilinos concede consentimento para Agent365.Observability.OtelWrite. Sem o consentimento, tokens são emitidos sem a função ou o escopo, e as solicitações são rejeitadas com 403. |
| Licenciamento | Pelo menos um usuário no locatário do cliente tem uma licença Microsoft 365 E7 ou Microsoft Agent 365 atribuída (atribuição, não apenas presença do SKU no locatário). Sem uma licença atribuída, o results da resposta mostram que os intervalos foram rejeitados. Consulte Pré-requisitos. |
| Spans | Cada span define os elementos essenciais de toda a execução (Hierarquia de span e agrupamento de execução). |
| Spans | Spans invoke_agent definem gen_ai.input.messages e gen_ai.output.messages. |
| Spans | Spans execute_tool definem gen_ai.tool.name, gen_ai.tool.type, gen_ai.tool.call.id, gen_ai.tool.call.arguments, gen_ai.tool.call.result. |
| Spans | Spans chat definem gen_ai.request.model e gen_ai.provider.name (e, de modo ideal, gen_ai.usage.input_tokens / gen_ai.usage.output_tokens - codificados como cadeia de caracteres). |
| Spans | Todos os spans que não são raiz definem parentSpanId; todos os spans em uma execução compartilham o mesmo traceId. |
| Conteúdo | O corpo da solicitação tem 1 MB ou menos. |
| Verificação | Você inspeciona tanto partialSuccess quanto results em cada resposta e registra rejeições. |
| Verificação | Você executou o fluxo de verificação em Verificando a ingestão para validar suas primeiras execuções. |
Próximas Etapas
- Referência de atributo – especificação por atributo e diretrizes de seleção de valor.
- Solução de problemas – verificação de ingestão, armadilhas comuns e respostas de erro.