שילוב תצפיות של סוכן באמצעות OTel ישיר

מדריך זה מנחה אותך מקצה לקצה דרך שליחת טלמטריית סוכן ל-Agent 365 ישירות דרך OpenTelemetry (OTLP/HTTP+JSON). לפני שתתחיל, קרא את מושגי הצפייה של Agent 365 כדי להבין את המודל, את זרימת האימות ואת המשטחים שבהם הנתונים שלך נוחתים.

חשוב

נתיב OTel הישיר הוא היוצא מן הכלל, לא ברירת המחדל. השתמש בו רק אם כבר יש לך צינור OpenTelemetry, המסגרת שלך אינה יכולה להשתמש ב-Agent 365 SDK, או שהסוכן שלך הוא בשפה שה-SDK עדיין לא תומך בה (כגון Java). עבור כל השאר, הנתיב המומלץ הוא Microsoft OpenTelemetry Distro, המספק SDK מאוחד לצפייה ב-Agent 365, Microsoft Foundry, Azure Monitor ועוד. ערכת הObservability SDK הקודמת ממשיכה לפעול מבלי לשבש שינויים, אך אינה מומלצת עוד עבור אינטגרציות חדשות; הנחיות הגירה למשתמשי SDK קיימים יגיעו בקרוב.

‏‫דרישות מוקדמות‬

ודא שהתצורות הבאות קיימות לפני כל זרימת טלמטריה.

WHO מה
מנהל דיירים הירשמו ל-Agent 365 ותנו הסכמה לאפליקציית הסוכן שלכם. ראה הצטרפות ל-Agent 365. ללא דייר מורשה, הבליעה נשמטת בשקט - הבקשה חוזרת 200 OK עִם partialSuccess: null אבל הנתונים אף פעם לא מופיעים במורד הזרם.
מנהל דיירים הקצהרישיון Microsoft 365 E7 או Microsoft Agent 365 למשתמש אחד לפחות בדייר. נוכחות ה-SKU אינה מספיקה. הקצאה למשתמש מפעילה את זרימת העבודה של מגן אחורי המאפשרת בליעה. ללא רישיון שהוקצה, בקשות 200 OK עִם partialSuccess: null מחזירות עם והנתונים נמחקים באופן שקט.
מנהל דיירים מתן הסכמה לדייר. ראה מתן גישה לסוכן למשאבי Microsoft 365. בלעדיו, מונפקים אסימונים ללא התפקיד/היקף והבקשות מחזירות 403.
צוות הפיתוח שלך רשום את האפליקציה שלך (אפליקציית Microsoft Entra סטנדרטית או תוכנית אב). לִרְאוֹת התחל עם פיתוח Agent 365.
צוות הפיתוח שלך לְהוֹסִיף Agent365.Observability.OtelWrite תַחַת הרשאות API(תפקיד אפליקציה עבור S2S, טווח להאצלה). לתוכניות, ראה הגדרת הרשאות הניתנות בירושה. תאם עם צוות ההטמעה של Agent 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, אפליקציית Microsoft Entra סטנדרטית

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

האסימון שהוחזר appid/azp = {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 של אפליקציה אוטונומית.

  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 עבור אסימון משאב 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
    
    • האסימון שהוחזר appid/azp = {agent-identity-app-id}, roles מֵכִיל Agent365.Observability.OtelWrite, ו aud = 9b975845-....
    • השתמש באסימון הזה על /observabilityService/.../traces מַסלוּל.
    • כתובת האתר {agentId}הוא ה- מזהה אפליקציה של זהות סוכן, לא מזהה האפליקציה של התוכנית.

OBO, אפליקציית Microsoft Entra הסטנדרטית

קבלת האסימון הנכנס של המשתמש 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.

לאסימון המוחזר יש appid/azp = {your-app-id}, scp המכיל Agent365.Observability.OtelWriteו-aud = 9b975845-.... השתמש בו על ה/observability/.../traces מַסלוּל. אסימון רענון מוחזר לצד; מטמון ושימוש חוזר בו במקום להריץ מחדש את החילוף בכל שיחה.

OBO, זהות סוכן שמקורה בתוכנית (כולל חבר צוות של בינה מלאכותית)

ישנם שלושה שלבים עיקריים בזרימה מטעם החברה. למידע נוסף, ראה זרימות OAuth של סוכן: מטעם הזרימה.

  1. קבל את אסימון המשתמשTc. עבור חבר צוות המבוסס על בינה מלאכותית, אסימון זה מייצג את חשבון המשתמש של הסוכן עצמו; אחרת, הוא מייצג את המתקשר האנושי.

  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}הוא ה- מזהה אפליקציה של זהות סוכן, לא מזהה האפליקציה של התוכנית. אסימון רענון מוחזר לצד; שמור אותו במטמון ומשתמש בו שוב.

תביעות נדרשות על האסימון המוחזר

S2S מַסלוּל (/observabilityService/...) - אסימון לאפליקציה בלבד:

טענה ערך נדרש
aud 9b975845-388f-4429-889e-eab1ef63949c (או api://9b975845-...)
roles חייב להכיל Agent365.Observability.OtelWrite
appid (v1) אוֹ azp (v2) חייב להיות שווה לכתובת URL {agentId}
scp חייב להיעדר

מסלול שהוקצה (/observability/...)‎ - אסימון שהוקצה על ידי המשתמש (נושא או PFAT);

טענה ערך נדרש
aud 9b975845-388f-4429-889e-eab1ef63949c (או api://9b975845-...)
scp חייב להכיל Agent365.Observability.OtelWrite
appid / azp חייב להיות שווה לכתובת URL {agentId}

המסלול המוקצה מקבל את שניהם Bearer ו MSAuth1.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} - של אפליקציית השיחות מזהה אפליקציה (גם ה-OAuth client_id). עבור זהויות הנגזרות מתוכנית אב, זהו ה- זהות הסוכן מזהה האפליקציה, לא מזהה האפליקציה של התבנית. חייב להיות שווה ל- appid / azp תביעה על האסימון שלך.
  • api-version=1 - נדרש.

בקשת קידוד גוף

הגוף הוא בצורת OTLP/HTTP+JSON הסטנדרטית: ExportTraceServiceRequest עִם resourceSpansscopeSpansspans. קחו בחשבון את הפרטים הבאים:

  • traceId (16 בתים) ו spanId (8 בתים) נשלחים כמחרוזות הקסדצימליות קטנות.
  • startTimeUnixNano / endTimeUnixNano הם מחרוזות ננו-שניות של אפוק יוניקס.
  • kind הוא ערך הספירה השלם של OTLP (לדוגמהe 1 עֲבוּר INTERNAL); status.code הוא מספר השלם (לדוגמה 1 עֲבוּר OK, 2 עֲבוּר ERROR).
  • כל ערכי המאפיינים נשלחים כ stringValue.

צורת תגובה

שיחה חוזרת מוצלחת 200 OK:

{ "partialSuccess": null }

אם חלק מהטווחים נדחו על ידי המסנן לפי טווח:

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

שמות השדות הם גמל קייס על החוט. תמיד לבדוק partialSuccess: 200 עם כל הטווחים שלך נדחים היא תוצאה אמיתית שאתה חייב לחשוף. מגבלות ותנאי שחרורמפרט את מקרי השחרור השקטים שבהם 200 חוזר עם partialSuccess: null למרות שלא הופיעו נתונים במורד הזרם.

הבקשה הקטנה ביותר האפשרית

הבדיקה הפשוטה ביותר מקצה לקצה שולחת בדיקה אחתinvoke_agent לְהַקִיף. טווח זה הוא הגוף הקטן ביותר שנוחת ב-Microsoft Defender.

שלב 1. קבל אסימון Bearer. עבור 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 בסדר הוא לא הוכחת בליעה; אימות הקליטה עובר על תהליך האימות. כדי לפרסם קובץ גוף שנשמר במקום זאת, החלף --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

חשוב

תכונות כלל-ריצה אלו הן לא מופץ באופן אוטומטי. עליך להגדיר gen_ai.conversation.id, microsoft.channel.name, ו microsoft.session.id על כל טווח בעצמך.

לְהַקִיף 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 */
  ]
}

לְהַקִיף 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 */
  ]
}

טווח 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 */
  ]
}

טווח 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 */
  ]
}

שליחת טלמטריה

שימוש ב-SDK של OTel

רוב השותפים שולחים עקבות דרך SDK של OTel במקום 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 בעצמך ושלח אותה באמצעות POST. צורת הגוף מוגדרת על ידי OpenTelemetry מפרט OTLP/HTTP+JSON‏‎ ‎‏:v

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

כֹּל <span> הוא אובייקט ששדות חובה שלו הם traceId, spanId, name, kind, startTimeUnixNano, endTimeUnixNano, attributes, ו-(עבור שרתים שאינם שורש משתרע) parentSpanId. לִרְאוֹת נקודות קצה ו בקשת קידוד גוףעבור כללי הקידוד (זמנים מקודדים במחרוזות, הקסדצימליים traceId / spanId, integer kind / status.code, כל ערכי המאפיינים כ stringValue).

קבוצת התכונות שיש להגדיר בכל טווח מוגדרת בחוזה הודעותs. לִרְאוֹת הפניה לתכונה לרשימת המאפיינים המלאה. עיין ב- סוכן run example עבור דוגמת עבודה מקצה לקצה עם אסימון ה-Bearer בכותרת והגוף בתוך השורה.

ניתן לשלוח את כל טווחי הריצה בגוף POST יחיד (רצוי - בקשה אחת, מעקב אחד) או על פני מספר POSTs. השרת בונה מחדש את הריצה מ traceId + parentSpanId + gen_ai.conversation.id, כך שכל טווח נושא מספיק כדי להיות מתואם בכל כיוון.

חוזי הודעות

סעיף זה מגדיר אילו טווחים ניתן לפלוט ואילו מאפיינים נכנסים לכל אחד מהם. למפרט המלא של כל מאפיין, עיינו ב הפניה לתכונה.

סוגי פעולה

כל פרק שאתה שולח חייב לשאת gen_ai.operation.name מוגדר לאחד מארבעת הערכים הללו (לא תלוי רישיות). כל טווח עם ערך חסר או לא מזוהה נשמט בשקט ונספר ב- partialSuccess.rejectedSpans.

gen_ai.operation.name משמעות הכי הרבה חיפושים בגוגל
invoke_agent קריאה של סוכן. ה"שורש" של ריצת סוכן. נדרש כדי שההפעלה תופיע בתצוגות פעילות סוכן של Microsoft Defender או במרכז הניהול של Microsoft 365. בלעדיו, הטלמטריה מגיעה רק בציד מתקדם של Microsoft Defender (CloudAppEvents).
execute_tool קריאה לכלי/פונקציה המבוצעת על ידי סוכן. --
chat קריאת הסקה של תואר שני במשפטים (LLM). השתמש במילולי chat, לֹא inference.
output_messages הודעת פלט סופית שנפלטה. --

היררכיית טווח וקיבוץ ריצות

Agent 365 משחזר ריצה מגרף הטווח הסטנדרטי של OTLP (traceId, spanId, parentSpanId) בנוסף לתכונות הרחבות מה- הפניה לתכונה.

שישה כללים:

  1. תמיד מוגדר parentSpanId על כל מרווח שאינו שורש. בלעדיו, לא ניתן לשחזר את מבנה העץ של הריצה.
  2. שימוש חוזר באותו traceId על פני כל טווח בריצה.
  3. מַעֲרֶכֶת gen_ai.conversation.id בכל טווח עם אותו ערך. זהו מפתח הצירוף הראשי עבור "כל הטווחים בריצה זו". זה לא מופץ באופן אוטומטי.
  4. מַעֲרֶכֶת microsoft.channel.name בכל טווח עם אותו ערך. טווחי כלים שחסרים בערוץ/שיחה יכולים לרשת אותם מההורה שלהם invoke_agentרק אם ההורה נמצא באותה בקשת OTLP, לכן הגדר אותם בכל span בעצמך.
  5. מַעֲרֶכֶת microsoft.session.id בכל טווח כאשר יש לך סשן לוגי.
  6. עבור קריאות בין סוכן לסוכן שבהן סוכן הצאצא נמצא בבקשה נפרדת, יש להשתמש שוב באותו gen_ai.conversation.id ולהשתמש ב- microsoft.a365.caller.agent.* תכונות (ראה תְכוּנָה הפניה) כדי ללכוד את ההקשר של המתקשר-סוכן.

עץ ארבעת הטרשים ב דוגמה להפעלת סוכן היא הצורה הקנונית.

צורות ריצה נפוצות

צורה טווחי פליטה הערות
צ'אטבוט של סוכן תוכנית Bot של צ'אט (בלי כלים, בלי טווח לימודי משפטים) אֶחָד invoke_agent רַק הגדר תכונות כלל-ריצה פלוס gen_ai.input.messages ו gen_ai.output.messages. זהה להבקשה הקטנה ביותר האפשרית.
סוכן עם כלים (הנפוץ ביותר) invoke_agent שׁוֹרֶשׁ + chat, execute_tool, output_messages יְלָדִים כל הילדים חולקים את השורש traceId ולהגדיר parentSpanId = root.spanId. לכולם יש את אותן תכונות לכל היקף הריצה. לִרְאוֹת דוגמה להפעלת סוכן לדוגמה מלאה.
סוכן לסוכן כל סוכן פולט את שלו invoke_agent שימוש חוזר באותו gen_ai.conversation.id בין שני הסוכן. על המטרה invoke_agent, מַעֲרֶכֶת gen_ai.execution.type = "Agent2Agent" וה- microsoft.a365.caller.agent.* תכונות (של סוכן הקריאה appId, שם, תוכנית appId,מזהה משתמש וכתובת דוא"ל). אם לסוכן המתקשר אין רישום Entra, השתמש ב- microsoft.a365.caller.agent.platform.id ו gen_ai.caller.agent.type במקום זאת.

רשימת בדיקה לקליטה

עברו על רשימת הבדיקה הזו לפני שתתחילו לייצור.

קטגוריה בדוק
אישור אפליקציית Entra שלך (או תוכנית הבניה) רשומה ואתה יכול להטמיע עבורה אסימונים.
אישור האפליקציה שלך אושרה Agent365.Observability.OtelWrite (תפקיד אפליקציה עבור S2S, היקף להאצלה).
אישור לכל סוכן יש את ה-Entra שלו מזהה אפליקציה כְּמוֹ {agentId} בכתובת האתר. עבור זהויות הנגזרות מ-blueprint, appId זה הוא appId של זהות הסוכן, ולא appId של ה-blueprint. אם לסוכן אין רישום Entra, ראה בחירת ערכים.
אישור מנהל דייר אישר הסכמה עֲבוּר Agent365.Observability.OtelWrite. ללא הסכמה, מונפקים אסימונים ללא התפקיד/היקף ובקשות נדחות עם 403.
רישוי לפחות משתמש אחד בדייר הלקוח יש ‏רישיון Microsoft 365 E7 או Microsoft Agent 365 הוקצה(הקצאה, לא רק נוכחות של SKU בטנה). ללא רישיון שהוקצה, ההטמעה מבוטלת בשקט. לִרְאוֹת דרישות קדם
ספנס כל טווח קובע את היסודות לכל אורך הריצה (היררכיית טווח וקיבוץ ריצות).
ספנס 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.arguments, gen_ai.tool.call.result.
ספנס chat סט טווחים gen_ai.request.model ו gen_ai.provider.name (ובאופן אידיאלי gen_ai.usage.input_tokens / gen_ai.usage.output_tokens - מקודד מחרוזות).
ספנס כל טווחי ה-"non-root" מוגדרים parentSpanId; כל הטווחים בריצה חולקים את אותו הדבר traceId.
מטען גוף הבקשה הוא ≤ 1 MB.
אימות אתה מנתח partialSuccess על כל תגובה ודחיות רישום.
אימות הפעלת את תהליך האימות ב אימות הקליטה נגד הריצות הראשונות שלך.

‏‫השלבים הבאים‬