Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Ce guide vous guide tout au long de l’envoi de la télémétrie de l’agent à l’agent 365 directement via OpenTelemetry (OTLP/HTTP+JSON). Avant de commencer, lisez les concepts d’observabilité d’Agent 365 pour comprendre le modèle, les flux d’authentification et les interfaces dans lesquelles vos données atterrissent.
Important
Le chemin OTel direct est l’exception, et non la valeur par défaut. Utilisez-le uniquement si vous disposez déjà d'un pipeline OpenTelemetry, que votre infrastructure ne peut pas utiliser le Kit de développement logiciel (SDK) Agent 365, ou que votre agent se trouve dans un langage que le Kit de développement logiciel (SDK) ne prend pas encore en charge (par exemple, Java). Pour tous les autres, l’approche recommandée est Microsoft OpenTelemetry Distro, qui fournit un SDK d’observabilité unifié pour Agent 365, Microsoft Foundry, Azure Monitor et plus encore. L’Observability SDK précédent continue de fonctionner sans changement cassant, mais n’est plus recommandé pour les nouvelles intégrations ; des recommandations de migration pour les utilisateurs actuels du SDK seront bientôt disponibles.
Prerequisites
Vérifiez que les configurations suivantes sont en place avant les flux de télémétrie.
| Qui | What |
|---|---|
| Administrateur de locataire | Inscrivez-vous à Agent 365 et accordez votre consentement pour votre application agent. Voir Intégration à l’agent 365. Sans locataire sous licence, l’ingestion est supprimée en mode silencieux : la requête retourne 200 OK avec partialSuccess: null , mais les données ne s’affichent jamais en aval. |
| Administrateur de locataire |
Attribuez une licence Microsoft 365 E7 ou Microsoft Agent 365 à au moins un utilisateur du locataire. La référence SKU présente n’est pas suffisante. L’affectation à un utilisateur démarre le flux de travail principal Defender qui active l’ingestion. Sans licence attribuée, les requêtes renvoient 200 OK avec partialSuccess: null et les données sont supprimées silencieusement. |
| Administrateur de locataire | Accordez le consentement du locataire. Consultez Autoriser les agents à accéder aux ressources Microsoft 365. Sans cela, les jetons sont émis sans le rôle/la portée, et les requêtes renvoient 403. |
| Votre équipe de développement | Inscrivez votre application (application standard Microsoft Entra ou blueprint). Consultez Prise en main du développement Agent 365. |
| Votre équipe de développement | Ajouter Agent365.Observability.OtelWrite dans Autorisations de l’API (rôle d’application pour S2S, portée pour les autorisations déléguées). Pour les blueprints, consultez Configurer les autorisations héritées. Coordonnez-vous avec l’équipe d’intégration Agent 365 pour activer l’autorisation. |
Recettes d’authentification
Les quatre recettes utilisent le point de terminaison standard des jetons Microsoft Entra :
| Champ | Valeur |
|---|---|
| Point de terminaison de jeton | https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/token |
Ressource (aud dans le jeton retourné) |
9b975845-388f-4429-889e-eab1ef63949c (accepte également api://9b975845-388f-4429-889e-eab1ef63949c) |
| Étendue S2S | 9b975845-388f-4429-889e-eab1ef63949c/.default |
| Étendue OBO | 9b975845-388f-4429-889e-eab1ef63949c/Agent365.Observability.OtelWrite |
Les recettes ci-dessous montrent http brut pour plus de clarté. En production, préférez Microsoft. Identity.Web ou une autre bibliothèque MSAL, qui gère l’actualisation et la mise en cache des jetons.
Quelle recette ai-je besoin ?
| Mon modèle d’application | Mon flux OAuth | Accéder à |
|---|---|---|
| Inscription d’application Microsoft Entra standard | S2S (informations d’identification du client) | S2S, application Microsoft Entra standard |
| Inscription d’application Microsoft Entra standard | OBO (délégué) | OBO, application standard Microsoft Entra |
| Identité de l’agent issue d’un modèle | S2S (informations d’identification du client) | Identité de l’agent dérivé de Blueprint S2S |
| Identité de l’agent dérivée du modèle | OBO / Collègue d’IA | OBO, identité d’agent dérivée de Blueprint |
S2S, application Microsoft Entra standard
Un POST vers le point de terminaison de jeton du locataire avec grant_type=client_credentials. Authentifiez l’application à l’aide d’une clé secrète client, d’un certificat (assertion JWT signée) ou d’une identité managée ou d’informations d’identification fédérées.
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
Le jeton retourné a appid/azp = {your-app-id}, roles contenant Agent365.Observability.OtelWriteet .aud = 9b975845-... Utilisez-le sur l’itinéraire /observabilityService/.../traces .
Pour l’authentification basée sur un certificat, remplacez client_secret={secret} par client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={signed-jwt}.
Identité d’agent S2S dérivée de Blueprint
Les identités d’agent n’ont pas d'identifiants propres. Le modèle d’identité de l’agent contient les informations d’identification (identité managée FIC, certificat ou secret client) et émet des jetons pour le compte de ses identités d’agent enfants au moyen d’un échange en deux étapes. Pour plus d’informations, consultez le flux OAuth pour application autonome.
Le plan s’authentifie et obtient un jeton d’échange d’identité fédérée
T1:-
{blueprint-credential}est le jeton MSI du blueprint, le JWT signé par certificat ou l’assertion de jeton d’échange secret par configuration de 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é de l’agent échange
T1contre le jeton de la ressource 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- Le jeton retourné a
appid/azp={agent-identity-app-id},rolescontenantAgent365.Observability.OtelWriteet .aud=9b975845-... - Utilisez ce jeton sur l’itinéraire
/observabilityService/.../traces. - L’URL
{agentId}correspond à l’appId d’identité de l’agent, et non à l’appId du plan directeur.
- Le jeton retourné a
OBO, application Microsoft Entra standard
Recevez le jeton utilisateur entrant Tc de l’appelant en amont (Bearer ou PFAT), puis échangez-le :
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
Pour l’authentification de certificat, remplacez client_secret={secret} par la même client_assertion_type + client_assertion paire que dans S2S.
Le jeton retourné a appid/azp = {your-app-id}, scp contenant Agent365.Observability.OtelWriteet .aud = 9b975845-... Utilisez-le sur l’itinéraire /observability/.../traces . Un jeton d’actualisation est retourné en même temps ; mettez en cache et réutilisez-le au lieu de réexécuter l’échange sur chaque appel.
Identité de l’agent issue du blueprint OBO (y compris le coéquipier IA)
Le flux On-Behalf-Of comporte trois étapes principales. Pour plus d’informations, consultez Les flux OAuth de l’agent : pour le compte du flux.
Recevez le jeton utilisateur
Tc. Pour un coéquipier IA, ce jeton représente le propre compte d’utilisateur de l’agent ; sinon, il représente l’appelant humain.Le blueprint s’authentifie et obtient
T1, identique au flux d’identité de l’agent dérivé du blueprint S2S.L’identité de l’agent échange
T1etTcpour un jeton de ressource délégué :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
Le jeton retourné a appid/azp = {agent-identity-app-id}, scp contenant Agent365.Observability.OtelWriteet représente l’utilisateur de l’agent. Utilisez-le sur l’itinéraire /observability/.../traces . L’URL {agentId} est l’appId de l’identité de l’agent, et non l’appId du plan. Un jeton d’actualisation est retourné en même temps ; mettez en cache et réutilisez-le.
Revendications requises sur le jeton retourné
Route S2S (/observabilityService/...) - jeton d’application uniquement :
| Réclamation | Valeur requise |
|---|---|
aud |
9b975845-388f-4429-889e-eab1ef63949c (ou api://9b975845-...) |
roles |
Doit contenir Agent365.Observability.OtelWrite |
appid (v1) ou azp (v2) |
Doit correspondre à l’URL {agentId} |
scp |
Doit être absent |
Itinéraire délégué (/observability/...) - jeton délégué utilisateur (Bearer ou PFAT):
| Réclamation | Valeur requise |
|---|---|
aud |
9b975845-388f-4429-889e-eab1ef63949c (ou api://9b975845-...) |
scp |
Doit contenir Agent365.Observability.OtelWrite |
appid / azp |
Doit correspondre à l’URL {agentId} |
La route déléguée accepte à la fois les jetons Bearer et MSAuth1.0 PFAT. Les appelants directs doivent utiliser Bearer. Si vous ne savez pas lequel vous avez, utilisez Bearer.
Points de terminaison
Deux itinéraires ; choisissez la façon dont votre service s’authentifie, et non par ce que fait l’utilisateur :
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
En-têtes :
Authorization: Bearer <token> # or MSAuth1.0 ... for delegated PFAT
Content-Type: application/json
Paramètres URL
-
{tenantId}- GUID du tenant client. Le serveur considère cela comme une source faisant autorité ; si vos spans définissentmicrosoft.tenant.idet qu’il n’est pas d’accord, la requête est rejetée. -
{agentId}- appId de l’application appelante (également OAuthclient_id). Pour les identités dérivées du modèle, il s’agit de l’appId de l’identité de l’agent, et non de l’appId du modèle. Doit être égal à laappid/azprevendication de votre jeton. -
api-version=1-Obligatoire.
Encodage du corps de la requête
Le corps suit la structure OTLP/HTTP+JSON standard : un ExportTraceServiceRequest avec resourceSpans → scopeSpans → spans. Gardez à l’esprit les détails suivants :
-
traceId(16 octets) etspanId(8 octets) sont envoyés sous forme de chaînes hexadécimaux minuscules. -
startTimeUnixNano/endTimeUnixNanosont des chaînes contenant des nanosecondes d’époque Unix. -
kindest la valeur entière de l’énumération OTLP (par exemple1pourINTERNAL) ;status.codeest l’énumération entière (par exemple1pourOK,2pourERROR). - Toutes les valeurs d’attribut sont envoyées en tant que
stringValue.
Forme de réponse
Un appel réussi retourne 200 OK:
{ "partialSuccess": null }
Si certains segments ont été rejetés par le filtre par segment :
{
"partialSuccess": {
"rejectedSpans": 2,
"errorMessage": "Dropped 2 non-A365 span(s) ..."
}
}
Les noms de champs sont camelCase sur le fil.
Vérifiez toujours partialSuccess : un code 200 avec tous vos spans rejetés est un résultat réel que vous devez signaler.
Limites et conditions d’abandon répertorie les cas d’abandon silencieux dans lesquels un code 200 est renvoyé avec partialSuccess: null, bien qu’aucune donnée n’apparaisse en aval.
Demande la plus petite possible
Le test de bout en bout le plus simple envoie un unique invoke_agent span. Ce span est le plus petit élément qui arrive dans Microsoft Defender.
Étape 1. Obtenez un jeton Bearer. Pour S2S, utilisez les identifiants client avec la portée 9b975845-388f-4429-889e-eab1ef63949c/.default (voir Recettes d’authentification pour la procédure complète).
Étape 2. POST un seul segment :
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
Étape 3. Attendez 200 OK avec le corps suivant :
{ "partialSuccess": null }
Étape 4. Vérifiez que les données ont réellement atterri. Un code 200 OK ne prouve pas l’ingestion ; Vérifier l’ingestion explique le processus de vérification. Pour effectuer une requête POST avec un fichier de corps de requête enregistré à la place, remplacez --data @- <<EOF ... EOF par --data @./otlp-request.json.
Exemple d’exécution de l’agent
Un utilisateur sur Microsoft Teams demande « Quelle est la météo à Seattle ? ». Votre agent appelle une fonction GetWeather, demande à un LLM de mettre en forme la réponse, puis répond. Cette seule exécution comporte quatre segments :
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
Attributs de l’exécution entière définis sur chaque span :
| Caractéristique | Exemple de valeur |
|---|---|
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
Ces attributs à l’échelle de l’exécution ne sont pas propagés automatiquement. Vous devez définir gen_ai.conversation.id, microsoft.channel.nameet microsoft.session.id sur chaque étendue vous-même.
Étendue A : invoke_agent (racine)
{
"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 */
]
}
Étendue B : chat (appel 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 */
]
}
Étendue 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 */
]
}
Étendue 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 */
]
}
Envoi de données de télémétrie
Utilisation d’un Kit de développement logiciel (SDK) OTel
La plupart des partenaires envoient des traces via un SDK OTel plutôt que via une implémentation HTTP codée à la main. Le Kit de développement logiciel (SDK) gère le traitement par lots, les nouvelles tentatives et l’encodage OTLP/HTTP+JSON pour vous. Définissez le point de terminaison de l’exportateur et injectez l’en-tête Authorization .
Le point de terminaison de l’exportateur est l’URL de routage elle-même, y compris la chaîne de requête :
https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1
(Utilisez /observability/... plutôt que /observabilityService/... pour l’itinéraire délégué.)
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}"},
)
Paquet : 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}` },
});
Paquet : @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;
}));
Paquet : OpenTelemetry.Exporter.OpenTelemetryProtocol.
HTTP manuel
Si vous ne pouvez pas ou ne souhaitez pas utiliser un SDK OTel, générez la requête OTLP/HTTP+JSON vous-même et postez-la. La structure du corps est définie par la spécification OpenTelemetry OTLP/HTTP+JSON :
{
"resourceSpans": [{
"resource": { "attributes": [ ... ] }, // optional
"scopeSpans": [{
"scope": { "name": "<your-instrumentation>", "version": "1.0.0" },
"spans": [ <span>, <span>, ... ]
}]
}]
}
Chaque <span> est un objet dont les champs obligatoires sont traceId, spanId, name, kind, startTimeUnixNano, endTimeUnixNano, attributes et, (pour les spans non racine) parentSpanId. Consultez les points de terminaison et l’encodage du corps de la requête pour les règles d’encodage (heures encodées par chaîne, hexadécimaltraceId / spanId, entierkind / status.code, toutes les valeurs d’attribut en tant que ).stringValue
L’ensemble d’attributs à définir sur chaque étendue est défini dans les contrats de message. Consultez la référence d’attribut pour la liste complète des attributs. Consultez l’exemple d’exécution de l’Agent pour voir un exemple fonctionnel de bout en bout avec le jeton Bearer dans l’en-tête et le corps inclus directement.
Vous pouvez envoyer tous les spans d’un run dans un seul corps de requête POST (de préférence : une requête, une trace) ou dans plusieurs requêtes POST. Le serveur reconstruit l’exécution à partir de traceId + parentSpanId + gen_ai.conversation.id, de sorte que chaque span contient suffisamment d’informations pour être corrélé dans les deux sens.
Contrats de messages
Cette section définit quels spans vous pouvez générer et quels attributs sont associés à chacun d’eux. Pour obtenir la spécification d’attribut par attribut complète, consultez la référence d’attribut.
Types d’opération
Chaque span que vous envoyez doit avoir gen_ai.operation.name défini sur l’une de ces quatre valeurs (sans distinction de casse). Toute étendue avec une valeur manquante ou non reconnue est supprimée en mode silencieux et comptée dans partialSuccess.rejectedSpans.
gen_ai.operation.name |
Sens | Le piège le plus recherché sur Google |
|---|---|---|
invoke_agent |
Appel d’un agent. La « root » d’une exécution d’agent. | Obligatoire pour que l’exécution apparaisse dans les vues d’activité de l’agent de Microsoft Defender ou dans le centre d’administration Microsoft 365. Sans cela, la télémétrie n’est transmise qu’à la fonctionnalité de recherche avancée de Microsoft Defender (CloudAppEvents). |
execute_tool |
Un appel d’outil / de fonction effectué par un agent. | -- |
chat |
Appel d’inférence LLM. |
Utilisez le littéral chat, NOT inference. |
output_messages |
Un message de sortie final émis. | -- |
Hiérarchie des spans et regroupement des runs
Agent 365 reconstruit une exécution à partir du graphe standard des spans OTLP (traceId, spanId, parentSpanId), ainsi que des attributs globaux de l’exécution issus de la référence des attributs.
Six règles :
-
Toujours définir
parentSpanIdsur chaque étendue non racine. Sans cela, il est impossible de reconstituer l’arborescence de l’exécution. -
Réutiliser le même
traceIdpour chaque plage d’un run. -
Définissez
gen_ai.conversation.idsur chaque étendue avec la même valeur. Il s’agit de la clé de jointure principale pour « tous les segments de cette exécution ». Elle n’est pas propagée automatiquement. -
Définissez
microsoft.channel.namesur chaque étendue avec la même valeur. Les spans d’outil auxquels il manque le canal / la conversation ne peuvent en hériter de leur parentinvoke_agentque si ce parent se trouve dans la même requête OTLP ; définissez-les donc vous-même sur chaque span. -
Définissez
microsoft.session.idsur chaque span lorsque vous avez une session logique. - Pour les appels d’agent à agent où l’agent enfant est dans une requête distincte, réutilisez le même
gen_ai.conversation.idet utilisez les attributsmicrosoft.a365.caller.agent.*(voir Référence des attributs) pour capturer le contexte de l’agent appelant.
L’arborescence à quatre étendues de l’exemple d’exécution de l’Agent est la forme canonique.
Types d’exécution courants
| Forme | Étendues à émettre | Remarques |
|---|---|---|
| Chatbot à agent unique (aucun outil, aucune étendue LLM) | Un invoke_agent seul |
Définir les attributs globaux de l’exécution ainsi que gen_ai.input.messages et gen_ai.output.messages. Identique à la demande la plus petite possible. |
| Agent avec outils (le plus courant) |
invoke_agent racine + chat, execute_tool, output_messages enfants |
Tous les enfants partagent la racine traceId et définissent parentSpanId = root.spanId. Tous portent les mêmes attributs pour l’ensemble de l’exécution. Consultez l’exemple d’exécution de l’agent pour obtenir un exemple complet. |
| Agent à agent | Chaque agent émet son propre invoke_agent |
Réutilisez le même gen_ai.conversation.id dans les deux agents. Sur le invoke_agent de la cible, définissez gen_ai.execution.type = "Agent2Agent" et les attributs microsoft.a365.caller.agent.* (le appId de l’agent appelant, le nom, le blueprint appId, l’identifiant utilisateur et l’e-mail). Si l’agent appelant n’a pas d’inscription Entra, utilisez microsoft.a365.caller.agent.platform.id et gen_ai.caller.agent.type à la place. |
Liste de contrôle d’intégration
Exécutez cette liste de contrôle avant d’aller en production.
| Catégorie | Vérifier |
|---|---|
| Authentification | Votre application Entra (ou plan) est enregistrée et vous pouvez générer des jetons pour celle-ci. |
| Authentification | Votre application s’est vu accorder Agent365.Observability.OtelWrite (rôle d’application pour S2S, portée pour l’autorisation déléguée). |
| Authentification | Chaque agent possède son propre ID d’application Entra appId, sous la forme de {agentId} dans l’URL. Pour les identités dérivées du blueprint, cet appId est l’appId d’identité de l’agent, et non l’appId de blueprint. Si l’agent n’a pas d’enregistrement Entra, consultez Choix des valeurs. |
| Authentification | Un administrateur du locataire a donné son consentement pour Agent365.Observability.OtelWrite. Sans consentement, les jetons sont émis sans le rôle/étendue et les demandes sont rejetées avec 403. |
| Gestion des licences | Au moins un utilisateur du locataire client s’est vu attribuer une licence Microsoft 365 E7 ou Microsoft Agent 365 (affectation effective, et pas seulement présence de la référence SKU dans le locataire). Sans licence affectée, l’ingestion est supprimée en mode silencieux. Consultez les Conditions préalables. |
| Travées | Chaque span définit les éléments essentiels communs à l’ensemble du run (Hiérarchie des spans et regroupement des runs). |
| Travées |
invoke_agent ensembles de plages gen_ai.input.messages et gen_ai.output.messages. |
| Travées |
execute_toolétendues définies gen_ai.tool.name, , gen_ai.tool.typegen_ai.tool.call.id, gen_ai.tool.call.arguments, gen_ai.tool.call.result. |
| Travées |
chat définit les étendues gen_ai.request.model et gen_ai.provider.name (et idéalement gen_ai.usage.input_tokens / gen_ai.usage.output_tokens - encodés sous forme de chaîne). |
| Travées | Tous les spans non racine définissent parentSpanId ; tous les spans d’une exécution partagent le même traceId. |
| Charge utile | Le corps de la demande est ≤ 1 Mo. |
| Vérification | Vous analysez partialSuccess dans chaque réponse et consignez les rejets. |
| Vérification | Vous avez exécuté le flux de vérification dans Vérification de l’ingestion sur vos premières exécutions. |
Étapes suivantes
- Informations de référence sur les attributs : spécifications par attribut et conseils de sélection de valeur.
- Résolution des problèmes : vérification de l’ingestion, des pièges courants et des réponses d’erreur.