Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Scopri come integrare l'osservabilità dell'agente con l'Agente 365 inviando telemetria direttamente tramite OpenTelemetry (OTLP/HTTP+JSON). Questo approccio aiuta gli agenti che non possono utilizzare l'SDK Agent 365 o la distribuzione Microsoft OpenTelemetry a inviare telemetria in modo efficiente e sicuro. Prima di iniziare, leggi i concetti di osservabilità di Agent 365 per capire il modello, i flussi di autenticazione e dove compaiono i tuoi dati.
Importante
Il percorso OTel diretto è l'eccezione, non l'impostazione predefinita. Usarlo solo se si dispone già di una pipeline OpenTelemetry, il framework non può usare Agent 365 SDK o l'agente si trova in un linguaggio non ancora supportato dall'SDK, ad esempio Java. Per tutti gli altri utenti, il percorso consigliato è Microsoft OpenTelemetry Distro, che fornisce un SDK di osservabilità unificato in Agent 365, Microsoft Foundry, Monitoraggio di Azure e altro ancora. Il precedente Observability SDK continua a funzionare senza modifiche di rilievo, ma non è più consigliato per le nuove integrazioni; verranno fornite indicazioni sulla migrazione per gli utenti dell'SDK esistenti.
Prerequisites
Verificare che le configurazioni seguenti siano presenti prima di qualsiasi flusso di telemetria.
| Chi | What |
|---|---|
| Amministratore tenant | Registrarsi ad Agent 365 e fornire il consenso per l'app dell'agente. Vedi Introduzione ad Agent 365. Senza un tenant idoneo, l'ingestione può restituire 200 OK anche se i results della risposta mostrano che gli span sono stati rifiutati. |
| Amministratore tenant |
Assegna una licenza Microsoft 365 E7 o Microsoft Agent 365 ad almeno un utente del tenant. La sola presenza dello SKU non è sufficiente. L'assegnazione a un utente avvia il flusso di lavoro back-end Defender che abilita l'inserimento. Senza una licenza assegnata, l'inserimento può restituire 200 OK pur rifiutando gli intervalli. |
| Amministratore tenant | Concedere il consenso del tenant. Vedere Concedere agli agenti l'accesso alle risorse di Microsoft 365. Senza di esso, i token vengono emessi senza il ruolo/ambito e le richieste restituiscono 403. |
| Il team di sviluppo | Registra la tua app (app Microsoft Entra standard o blueprint). Vedi Identità dell'agente. |
| Il team di sviluppo | Aggiungi Agent365.Observability.OtelWrite sotto Autorizzazioni API (il ruolo app per S2S, l'ambito per l'accesso delegato). Per i progetti modello, vedere Configurare le autorizzazioni ereditabili. Coordinarsi con il team di onboarding di Agent 365 per abilitare l'autorizzazione. |
Ricette di autenticazione
Tutte e quattro le ricette usano l'endpoint standard del token di Microsoft Entra:
| Campo | Value |
|---|---|
| Endpoint token | https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/token |
Risorsa (aud nel token restituito) |
9b975845-388f-4429-889e-eab1ef63949c (accetta api://9b975845-388f-4429-889e-eab1ef63949canche ) |
| Ambito S2S | 9b975845-388f-4429-889e-eab1ef63949c/.default |
| Ambito OBO | 9b975845-388f-4429-889e-eab1ef63949c/Agent365.Observability.OtelWrite |
Le seguenti ricette mostrano HTTP grezzo per chiarezza. In produzione, usa Microsoft. Identity.Web o un'altra libreria MSAL, che gestisce l'aggiornamento dei token e la cache.
Quale ricetta ho bisogno?
| Modello di app personale | Il mio flusso OAuth | Vai a |
|---|---|---|
| Registrazione dell'app standard Microsoft Entra | S2S (credenziali del client) | S2S, app Microsoft Entra standard |
| Registrazione dell'app standard Microsoft Entra | OBO (delegato) | OBO, app Microsoft Entra standard |
| Identità dell'agente derivata da blueprint | S2S (credenziali del client) | S2S, identità dell'agente derivato da Blueprint |
| Identità dell'agente derivata da blueprint | Assistente IA/OBO | OBO, identità dell'agente derivata da Blueprint |
S2S, app standard di Microsoft Entra
Invia una richiesta POST all'endpoint del token del tenant con grant_type=client_credentials. Autenticare l'app usando un segreto client, un certificato (asserzione JWT firmata) o un'identità gestita o credenziali federate.
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
Il token restituito ha appid/azp = {your-app-id}, contenente roles, Agent365.Observability.OtelWrite e .aud = 9b975845-... Usalo nel percorso /observabilityService/.../traces.
Per l'autenticazione basata su certificato, sostituire client_secret={secret} con client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={signed-jwt}.
S2S, identità dell'agente derivata dal blueprint
Le identità degli agenti non hanno credenziali specifiche. Il modello di identità dell'agente contiene le credenziali (FIC dell'identità gestita, certificato o segreto client) e genera token per conto delle sue identità figlie dell'agente tramite uno scambio in due fasi. Per altre informazioni, consulta il flusso OAuth per app autonome.
Il blueprint esegue l'autenticazione e ottiene un token di scambio di identità federato
T1:-
{blueprint-credential}è il token MSI del blueprint, il token JWT firmato con certificato o l'asserzione exchange-token segreto, in base alla configurazione del 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-
L'identità dell'agente viene scambiata
T1con il token di risorsa di Agent 365 Observability: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- Il token restituito ha
appid/azp={agent-identity-app-id}, contenenteroles,Agent365.Observability.OtelWritee .aud=9b975845-... - Usa questo token sul percorso
/observabilityService/.../traces. - L'URL
{agentId}è l'appId dell'identità dell'agente, non l'appId del blueprint.
- Il token restituito ha
OBO, app standard di Microsoft Entra
Ricevere il token Tc in ingresso dell'utente dal chiamante upstream (Bearer o PFAT), quindi scambiarlo:
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
Per l'autenticazione del certificato, sostituire client_secret={secret} con la stessa client_assertion_type + client_assertion coppia di in S2S.
Il token restituito ha appid/azp = {your-app-id}, contenente scp, Agent365.Observability.OtelWrite e .aud = 9b975845-... Usalo nel percorso /observability/.../traces. Un token di aggiornamento viene restituito insieme; memorizzare nella cache e riutilizzarlo invece di riesecuzione dello scambio in ogni chiamata.
OBO, identità dell'agente derivata dal progetto (incluso assistente IA)
Esistono tre passaggi principali del flusso On-Behalf-Of. Per altre informazioni, vedi Flussi OAuth dell'agente: per conto del flusso.
Ricevi il token utente
Tc. Per un collega di intelligenza artificiale, questo token rappresenta il proprio account utente dell'agente; in caso contrario, rappresenta il chiamante umano.Il blueprint esegue l'autenticazione e ottiene
T1, come avviene nel flusso di identità dell'agente derivato dal blueprint S2S.L'identità dell'agente scambia
T1eTccon un token di risorsa delegato: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
Il token restituito ha appid/azp = {agent-identity-app-id}, scp contenente Agent365.Observability.OtelWritee rappresenta l'utente dell'agente. Usalo nel percorso /observability/.../traces. L'URL {agentId} è l'appId dell'identità dell'agente, non l'appId del blueprint. Un token di aggiornamento viene restituito insieme; memorizzare nella cache e riutilizzarlo.
Attestazioni richieste nel token restituito
Percorso S2S (/observabilityService/...) - token solo applicazione:
| Richiesta di rimborso | Valore obbligatorio |
|---|---|
aud |
9b975845-388f-4429-889e-eab1ef63949c (o api://9b975845-...) |
roles |
Deve contenere Agent365.Observability.OtelWrite |
appid (v1) o azp (v2) |
Deve essere uguale a URL {agentId} |
scp |
Deve essere assente |
Instradamento delegato (/observability/...): token delegato dall'utente (Bearer o PFAT):
| Richiesta di rimborso | Valore obbligatorio |
|---|---|
aud |
9b975845-388f-4429-889e-eab1ef63949c (o api://9b975845-...) |
scp |
Deve contenere Agent365.Observability.OtelWrite |
appid / azp |
Deve essere uguale a URL {agentId} |
Il percorso delegato accetta sia i token Bearer sia i token MSAuth1.0 PFAT. I chiamanti diretti devono usare Bearer. Se non si sa quale si ha, utilizzare Bearer.
Endpoints
Due percorsi; scegliere in base al modo in cui il servizio esegue l'autenticazione, non in base alle operazioni che l'utente sta eseguendo:
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
Intestazioni:
Authorization: Bearer <token> # or MSAuth1.0 ... for delegated PFAT
Content-Type: application/json
Parametri URL
-
{tenantId}: GUID del tenant del cliente. Il server considera questo valore come autorevole. Se i tuoi span sono impostatimicrosoft.tenant.ide non corrispondono, il server rifiuta la richiesta. -
{agentId}- appId dell'applicazione chiamante (anche OAuthclient_id). Per le identità derivate dal blueprint, questo valore è l'identità dell'agente appId, non il blueprint appId. Deve corrispondere all'attestazioneappidoazpdel tuo token. -
api-version=1-Obbligatorio.
Verifica l'idoneità del locatario
Le integrazioni di terze parti integrate che utilizzano il modello di autenticazione S2S possono verificare se un tenant cliente è idoneo all'osservabilità dell'Agent 365 prima di abilitare un'integrazione o inviare telemetria. Questo controllo può aiutare le integrazioni a evitare di inviare telemetrie per inquilini attualmente non idonei.
Usa lo stesso token solo app descritto nell'autenticazione S2S.
Il token deve contenere il ruolo dell'app Agent365.Observability.OtelWrite e la sua tid rivendicazione deve corrispondere {tenantId} all'URL della richiesta.
GET https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/eligibility?api-version=1
Authorization: Bearer <access-token>
Una risposta positiva contiene il risultato dell'idoneità:
{
"enabled": true
}
Gestisci la risposta come segue:
| Condizione | Meaning | Azione del client |
|---|---|---|
200 OK, enabled: true |
Il tenant è idoneo all'osservabilità. | L'integrazione può inviare telemetria. |
200 OK, enabled: false |
L'inquilino attualmente non è idoneo all'osservabilità. | Non inviare telemetria. Verifica che l'inquilino soddisfi i prerequisiti e ricontrolla dopo che il suo stato cambia. Se la telemetria viene comunque inviata, l'endpoint di ingestione può restituire 200 OK pur rifiutando gli span. |
400 Bad Request |
{tenantId} è vuoto o invalido. |
Correggi l'ID inquilino prima di riprovare. |
401 Unauthorized |
Il token di accesso è mancante o non valido. | Acquisire un token valido per la risorsa Agent 365 Observability. |
403 Forbidden |
Il token non ha il ruolo richiesto nell'app, oppure il suo tenant non corrisponde {tenantId}. |
Correggi il permesso, il consenso o la discrepanza tra inquilini prima di riprovare. |
429 Too Many Requests |
Il chiamante ha superato il limite di idoneità richiesto. | Onora Retry-After e riprova con un passo indietro e un nervosismo. |
503 Service Unavailable |
Non si poteva determinare l'idoneità. La risposta non ha corpo. | Rispetta Retry-After: 30 e riprova. Non trattare questa risposta come enabled: false. |
Codifica del corpo della richiesta
Il corpo usa il formato OTLP/HTTP+JSON standard: un ExportTraceServiceRequest con resourceSpans → scopeSpans → spans. Tenere presenti i dettagli seguenti:
- Invia
traceId(16 byte) espanId(8 byte) come stringhe esadecimali minuscole. -
startTimeUnixNanoeendTimeUnixNanosono stringhe che contengono nanosecondi dell'epoca Unix. -
kindè il valore intero OTLP enum (ad esempio,1perINTERNAL).status.codeè l'enum intero (ad esempio,1perOK,2perERROR). - Invia tutti i valori degli attributi come
stringValue.
Forma della risposta
Una 200 OK risposta significa che l'Agente 365 ha elaborato la richiesta. Non garantisce che ogni intervallo sia stato instradato verso una destinazione. Ispeziona sia partialSuccess che results.
L'array results riporta il risultato per ogni campata in ogni destinazione applicabile:
-
sent- lo span è stato instradato alla destinazione. -
rejected: l'intervallo non è stato instradato. Ilreasoncampo spiega il perché. -
not_routed- la destinazione non è stata selezionata per l'intervallo. Ilreasoncampo spiega il perché.
Ad esempio, uno span instradato con successo può restituire:
{
"partialSuccess": {
"rejectedSpans": 0,
"errorMessage": ""
},
"results": [
{
"spanId": "0123456789abcdef",
"sinks": {
"flashpoint": {
"status": "sent"
},
"sentinel": {
"status": "sent"
},
"esp": {
"status": "sent"
}
}
}
]
}
Se l'inquilino non è idoneo, la richiesta può comunque essere restituita 200 OK. In tal caso, results indica che gli intervalli sono stati rifiutati:
{
"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"
}
}
}
]
}
Per le decisioni di instradamento dell'intera richiesta, partialSuccess.rejectedSpans può rimanere 0 anche quando results mostra che tutti gli span sono stati rifiutati. Non usare partialSuccess o il solo stato HTTP come prova dell'ingestione. I nomi dei campi sono in camelCase nel formato trasmesso. Vedi Limiti e condizioni di caduta per altri motivi la telemetria potrebbe non comparire.
Richiesta più piccola possibile
Il test end-to-end più semplice invia un singolo invoke_agent span. Questo intervallo è la più piccola entità che arriva in Microsoft Defender.
Passaggio 1: Ottenere un Bearer token. Per S2S, usare le credenziali client con ambito 9b975845-388f-4429-889e-eab1ef63949c/.default (vedere Ricette di autenticazione per la ricetta completa).
Passaggio 2: POST un singolo intervallo:
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
Passaggio 3. Aspetta 200 OK, poi ispeziona results come descritto nella forma di risposta. Verifica che le destinazioni applicabili abbiano lo stato sent.
Passaggio 4: Verificare che i dati siano effettivamente atterrati. Un 200 OK non è una prova di ingestione; vedi Verificare l'ingestione per il flusso di verifica. Per eseguire invece il POST di un file del corpo salvato, sostituisci --data @- <<EOF ... EOF con --data @./otlp-request.json.
Esempio di esecuzione dell'agente
Un utente su Microsoft Teams chiede "Qual è il meteo a Seattle?". L'agente chiama una GetWeather funzione, chiede a un LLM di formattare la risposta e risponde. L'esecuzione singola è di quattro intervalli:
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
Attributi a livello di esecuzione impostati in ogni intervallo:
| Attribute | Valore di esempio |
|---|---|
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
Questi attributi a livello di run non si propagano automaticamente. Devi impostare gen_ai.conversation.id, microsoft.channel.name e microsoft.session.id su ogni intervallo.
Span A: invoke_agent (radice)
{
"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 */
]
}
Intervallo B: chat (chiamata a 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 */
]
}
Campata 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 */
]
}
Intervallo 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 */
]
}
Inviare dati di telemetria
Usa un SDK OTel
La maggior parte dei partner invia tracce tramite un SDK OTel anziché usare un’implementazione HTTP scritta manualmente. L'SDK gestisce automaticamente l'invio in batch, i tentativi e la codifica OTLP/HTTP+JSON. Impostare l'endpoint di esportazione e inserire l'intestazione Authorization .
L'endpoint dell'esportatore coincide con l'URL del percorso stesso, inclusa la stringa di query:
https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1
Usare /observability/... invece di /observabilityService/... per la route delegata.
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}"},
)
Pacchetto: 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}` },
});
Pacchetto: @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;
}));
Pacchetto: OpenTelemetry.Exporter.OpenTelemetryProtocol.
Manuale HTTP
Se non è possibile o non si vuole usare un SDK OTel, compilare manualmente la richiesta OTLP/HTTP+JSON e PUBBLICArla. La specifica OpenTelemetry OTLP/HTTP+JSON definisce la forma del corpo:
{
"resourceSpans": [{
"resource": { "attributes": [ ... ] }, // optional
"scopeSpans": [{
"scope": { "name": "<your-instrumentation>", "version": "1.0.0" },
"spans": [ <span>, <span>, ... ]
}]
}]
}
Ogni <span> è un oggetto i cui campi obbligatori sono traceId, spanId, name, kind, startTimeUnixNano, endTimeUnixNano, attributes e (per gli span non radice) parentSpanId. Per le regole di codifica (tempi codificati per stringhe, esadecimaletraceId / spanId, intero / kindstatus.code, tutti i valori degli attributi come stringValue), vedi Endpoint e codifica del corpo delle richieste.
Il set di attributi da impostare su ogni intervallo è definito nei contratti di messaggio. Per l'elenco completo degli attributi, vedi Riferimento agli attributi. Fai riferimento ad Esempio di esecuzione dell'agente per un esempio di lavoro end-to-end con il token di connessione nell'intestazione e nel corpo inline.
È possibile inviare tutti gli intervalli di un'esecuzione in un singolo corpo POST (preferibile, una richiesta, una traccia) o tra più POST. Il server ricostruisce l'esecuzione da traceId + parentSpanId + gen_ai.conversation.id, quindi ogni span contiene informazioni sufficienti per poter essere correlato in entrambe le direzioni.
Contratti di messaggio
Questa sezione definisce quali span è possibile emettere e quali attributi applicare a ciascuno. Per le specifiche complete, attributo per attributo, consulta il riferimento degli attributi.
Tipi di operazione
Ogni span inviato deve avere gen_ai.operation.name impostato su uno di questi quattro valori (senza distinzione tra maiuscole e minuscole). Il server elimina qualsiasi span con un valore mancante o non riconosciuto e lo conta in partialSuccess.rejectedSpans.
gen_ai.operation.name |
Meaning | Trucco più cercato su Google |
|---|---|---|
invoke_agent |
Un'invocazione di un agente. La "radice" di un'esecuzione dell'agente. | Necessario affinché l'esecuzione venga visualizzata nelle visualizzazioni dell'attività dell'agente di Microsoft Defender o nell'interfaccia di amministrazione di Microsoft 365. In assenza di questo, i dati di telemetria confluiscono solo in Ricerca avanzata di Microsoft Defender (CloudAppEvents). |
execute_tool |
Una chiamata di strumento/funzione eseguita da un agente. | -- |
chat |
Chiamata di inferenza LLM. |
Usare il valore letterale chat, NON inference. |
output_messages |
Messaggio di output finale emesso. | -- |
Gerarchia degli span e raggruppamento delle esecuzioni
Agent 365 ricostruisce un'esecuzione dal grafico dell'intervallo OTLP standard (traceId, spanId, parentSpanId) più gli attributi a livello di esecuzione del riferimento attributo.
Sei regole:
-
Imposta sempre
parentSpanIdsu ogni span non root. Senza di essa, non puoi ricostruire la struttura ad albero della corsa. -
Riutilizza lo stesso
traceIdin ogni segmento di una sequenza. -
Impostata
gen_ai.conversation.idsu ogni intervallo con lo stesso valore. Questo valore è la chiave di join primaria per "tutti gli span in questa esecuzione". Non si propaga automaticamente. -
Impostata
microsoft.channel.namesu ogni intervallo con lo stesso valore. Gli span degli strumenti che mancano dal canale o dalla conversazione possono ereditarli dal genitoreinvoke_agentsolo se il genitore è nella stessa richiesta OTLP, quindi impostali tu stesso su ogni span. -
Imposta
microsoft.session.idsu ogni intervallo quando si dispone di una sessione logica. - Per le chiamate da agente a agente in cui l'agente figlio è in una richiesta separata, riutilizzare lo stesso
gen_ai.conversation.ide usare gli attributimicrosoft.a365.caller.agent.*(vedere riferimento degli attributi) per catturare il contesto dell'agente chiamante.
L'albero a quattro intervalli nell'esempio di esecuzione dell'agente è la forma canonica.
Forme di esecuzione comuni
| Forma | Intervalli da generare | Notes |
|---|---|---|
| Chatbot con agente singolo (senza strumenti, nessun intervallo LLM) | Un invoke_agent solo |
Impostare gli attributi a livello di esecuzione più gen_ai.input.messages e gen_ai.output.messages. Identica alla richiesta più piccola possibile. |
| Agente con strumenti (più comuni) | Radice invoke_agent + chat, execute_tool, output_messages figli |
Tutti gli elementi figlio condividono il valore traceId della radice e impostano parentSpanId = root.spanId. Tutti contengono gli stessi attributi a livello di esecuzione. Vedere Esempio di esecuzione dell'agente per un esempio completo. |
| Da agente a agente | Ogni agente genera il proprio invoke_agent |
Riutilizza lo stesso gen_ai.conversation.id per entrambi gli agenti. In invoke_agent di destinazione, imposta gen_ai.execution.type = "Agent2Agent" e gli attributi microsoft.a365.caller.agent.* (appId dell'agente chiamante, nome, modello appId, ID utente ed e-mail). Se l'agente chiamante non ha una registrazione Entra, utilizzare invece microsoft.a365.caller.agent.platform.id e gen_ai.caller.agent.type. |
Checklist per l'avvio in produzione
Consulta questa lista di controllo prima di passare in produzione.
| Categoria | Controlla |
|---|---|
| Auth | L'app Entra (o il blueprint) è registrata ed è possibile coniare i token. |
| Auth | La tua applicazione ottiene Agent365.Observability.OtelWrite (ruolo applicazione per S2S, ambito per autorizzazioni delegate). |
| Auth | Ogni agente ha il proprio ID app di Entra come nell'URL. Per le identità derivate da blueprint, si tratta dell'appId dell'identità dell'agente, non dell'appId del blueprint. Se l'agente non dispone di una registrazione in Entra, vedi Scelta dei valori. |
| Auth | Un amministratore del tenant concede il consenso a Agent365.Observability.OtelWrite. Senza consenso, i token vengono emessi senza il ruolo o l'ambito e le richieste vengono rifiutate con 403. |
| Licenze | Almeno un utente nel tenant del cliente ha una licenza Microsoft 365 E7 o Microsoft Agent 365 assegnata (assegnazione, non solo presenza di SKU nel tenant). Senza una licenza assegnata, i results della risposta mostrano che gli intervalli sono stati rifiutati. Vedere Prerequisiti. |
| Intervalli | Ogni span imposta gli elementi essenziali comuni all’intera esecuzione (gerarchia degli span e raggruppamento delle esecuzioni). |
| Intervalli | Intervalli invoke_agent impostati gen_ai.input.messages e gen_ai.output.messages. |
| Intervalli |
execute_tool insieme di intervalli gen_ai.tool.name, gen_ai.tool.type, gen_ai.tool.call.id, gen_ai.tool.call.arguments, gen_ai.tool.call.result. |
| Intervalli | Intervalli chat impostati su gen_ai.request.model e gen_ai.provider.name (e idealmente gen_ai.usage.input_tokens / gen_ai.usage.output_tokens, codificati come stringa). |
| Intervalli | Tutti gli intervalli non radice hanno lo stesso parentSpanId; tutti gli intervalli in una sequenza condividono lo stesso traceId. |
| Payload | Il corpo della richiesta è ≤ 1 MB. |
| Verifica | Esamini sia partialSuccess sia results in ogni risposta e registri i rifiuti. |
| Verifica | Hai eseguito il flusso di verifica in Verifica dell'acquisizione rispetto alle tue prime esecuzioni. |
Passaggi successivi
- Informazioni di riferimento sugli attributi: indicazioni per la specifica per attributo e la selezione di valori.
- Risoluzione dei problemi - Verifica dell'acquisizione, degli errori comuni e delle risposte agli errori.