دمج إمكانية مراقبة العامل باستخدام OTel المباشر

تعلم كيفية دمج ملاحظة الوكيل مع الوكيل 365 عن طريق إرسال بيانات التليمترية مباشرة عبر OpenTelemetry (OTLP/HTTP+JSON). يساعد هذا النهج الوكلاء الذين لا يستطيعون استخدام توزيعة Microsoft OpenTelemetry Distro على إرسال البيانات بكفاءة وأمان. قبل البدء، اقرأ مفاهيم الملاحظة في Agent 365 لفهم النموذج، وتدفقات المصادقة، ومكان ظهور بياناتك.

Important

مسار OTel المباشر هو الاستثناء، وليس الافتراضي. استخدمه فقط إذا كان لديك بالفعل خط أنابيب OpenTelemetry، أو إذا كان إطار عملك لا يستطيع استخدام توزيعة Microsoft OpenTelemetry، أو إذا كان وكيلك في لغة لا تدعمها التوزيعة بعد (مثل Java). بالنسبة لأي شخص آخر، المسار الموصى به هو Microsoft OpenTelemetry Distro، والذي يوفر SDK موحدا للمراقبة عبر Agent 365، Microsoft Foundry، Azure Monitor، والمزيد. لا يزال SDK قابلية الملاحظة Agent 365 المهمل يعمل مع التكاملات الحالية، لكنه غير موصى به للتكاملات الجديدة.

Prerequisites

تأكد من تطبيق الإعدادات التالية قبل إرسال أي بيانات تتبع الاستخدام.

من What
مسؤول المستأجر سجل في Agent 365 وامنح أي موافقة مطلوبة لتطبيق الوكيل الخاص بك. راجع البدء باستخدام Agent 365. في حال عدم وجود مستأجر مؤهل، قد تُرجع عملية الاستيعاب 200 OK رغم أن قيمة results في الاستجابة تُظهر أن المقاطع قد رُفضت.
مسؤول المستأجر تعيين ترخيص Microsoft 365 E7 أو Microsoft Agent 365 إلى مستخدم واحد على الأقل ضمن المستأجر. وجود وحدة SKU بحد ذاته لا يكفي. يؤدي تعيينه إلى مستخدم إلى بدء سير عمل Defender في الواجهة الخلفية الذي يُمكّن من استيعاب البيانات. من دون ترخيص مُسند، يمكن أن تُرجِع عملية الاستيعاب 200 OK مع رفض المقاطع.
مسؤول المستأجر امنح إذن المستأجر عندما يتطلب مسارك Agent365.Observability.OtelWrite. مثيلات الوكيل المسجلة التي تُصدِّر عبر مسار S2S لا تحتاج إلى موافقة إمكانية المراقبة. لكن ينطبق ذلك على تصدير المسارات المفوضة وهويات S2S غير المسجلة. راجع وصول عوامل Grant إلى موارد Microsoft 365. بدون الموافقة المطلوبة، تصدر الرموز بدون الدور أو النطاق، وتعود 403 الطلبات.
فريق التطوير الخاص بك سجل تطبيقك (تطبيق Microsoft Entra القياسي أو blueprint)، وأكمل تسجيل Agent 365 لمثيلات الوكيل المشتقة من blueprint. انظر هوية الوكيل.
فريق التطوير الخاص بك أضف Agent365.Observability.OtelWrite فقط عندما يحتاج مسارك إلى ذلك: دور التطبيق لهويات S2S غير المسجلة ونطاق تفويض ل OBO. للمخططات التي لا تزال بحاجة إلى تصدير مفوض، انظر تكوين الأذونات القابلة للوراثة. قم بالتنسيق مع فريق إعداد 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 / زميل فريق الذكاء الاصطناعي OBO، هوية الوكيل المشتقة من Blueprint

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. تسجيلات التطبيقات القياسية ليست مثيلات وكيل مسجلة في Agent 365، لذا يحتاج الرمز المميز إلى دور التطبيق هذا.

للمصادقة المستندة إلى الشهادة، استبدل 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 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
    
    • الرمز المسترجع له appid = azp/{agent-identity-app-id}، ولا يحتوي على scp، وaud = 9b975845-.... بالنسبة لمثيل وكيل مسجل في Agent 365، لا يحتاج الرمز إلى الدور Agent365.Observability.OtelWrite.
    • إذا لم يكن مثيل الوكيل مسجلاً لدى Agent 365، ترفض الخدمة رمز الوصول نفسه الخاص بالتطبيق فقط ومن دون أدوار مع 403 insufficient_scope. الهويات غير المسجلة تحتاج إلى Agent365.Observability.OtelWrite app role.
    • استخدم هذا الرمز على المسار /observabilityService/.../traces.
    • عنوان URL {agentId} هو معرف العامل appId، وليس معرف تطبيق المخطط.

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. عنوان URL {agentId} هو معرف العامل appId، وليس معرف تطبيق المخطط. يتم إرجاع رمز تحديث معه؛ خزّنه مؤقتًا وأعِد استخدامه. يتطلب المسار المفوض النطاق المفوض وموافقة مسؤول المستأجر.

المطالبات المطلوبة في الرمز المميز المُعاد

مسار S2S (/observabilityService/...) - رمز مميز للتطبيق فقط:

المطلب القيمة المطلوبة
aud 9b975845-388f-4429-889e-eab1ef63949c (أو api://9b975845-...)
roles بالنسبة إلى مثيل وكيل مسجل في Agent 365، لا يلزم ذلك. بالنسبة لهوية غير مسجلة، يجب أن تحتوي على Agent365.Observability.OtelWrite.
appid (v1) أو azp (v2) يجب أن يساوي URL {agentId}
scp يجب أن يكون غائبا

المسار المفوض (/observability/...) - الرمز المميز المفوض من قبل المستخدم (Bearer أو PFAT):

المطلب القيمة المطلوبة
aud 9b975845-388f-4429-889e-eab1ef63949c (أو api://9b975845-...)
scp يجب أن يحتوي على Agent365.Observability.OtelWrite
appid / azp يجب أن يساوي URL {agentId}

يقبل المسار المُفوَّض كِلا الرمزين المميزين 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} - المعرف الفريد العمومي لمستأجر العميل. يعامل الخادم هذه القيمة كقيمة موثوقة. إذا عيّنت نطاقاتك microsoft.tenant.id ولم تتطابق، فسيرفض الخادم الطلب.
  • {agentId} - appId الخاص بتطبيق الاستدعاء (أيضا OAuth client_id). بالنسبة إلى الهويات المشتقة من المخطط التفصيلي، فهذه القيمة هي appId الخاص بـ هوية الوكيل، وليست appId الخاص بالمخطط التفصيلي. يجب أن تتطابق مع مطالبة appid أو azp الخاصة بالرمز المميز لديك.
  • api-version=1 -مطلوب.

تحقق من أهلية المستأجرين

يمكن للتكاملات المدمجة من طرف ثالث التي تستخدم نموذج المصادقة S2S التحقق مما إذا كان المستأجر العميل مؤهلا لملاحظة الوكيل 365 قبل تمكين التكامل أو إرسال بيانات التليمترية. يمكن أن يساعد هذا الفحص التكاملات على تجنب إرسال بيانات عن بعد للمستأجرين غير المؤهلين حاليا.

استخدم نفس الرمز الخاص بالتطبيق فقط الموصوف في مصادقة S2S. يجب أن يحتوي الرمز على Agent365.Observability.OtelWrite دور التطبيق، ويجب أن يتطابق {tenantId} ادعائه tid في عنوان URL الخاص بالطلب.

GET https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/eligibility?api-version=1
Authorization: Bearer <access-token>

الإجابة الناجحة تحتوي على نتيجة الأهلية:

{
  "enabled": true
}

تعامل مع الرد كما يلي:

Status المعنى إجراء العميل
200 OK، enabled: true المستأجر مؤهل للملاحظة. يمكن للتكامل إرسال بيانات التليمترية.
200 OK، enabled: false المستأجر غير مؤهل حاليا للملاحظة. لا ترسل بيانات عن بعد. تحقق من أن المستأجر يستوفي المتطلبات المسبقة، وتحقق مرة أخرى بعد تغير الحالة. إذا أُرسلت بيانات القياس عن بُعد على أي حال، يمكن لنقطة نهاية الاستيعاب أن تُرجع 200 OK مع رفض مقاطع التتبّع.
400 Bad Request {tenantId} فارغ أو غير صالح. صحح رقم تعريف المستأجر قبل إعادة المحاولة.
401 Unauthorized رمز الوصول مفقود أو غير صالح. احصل على رمز صالح لمورد Agent 365 Observability.
403 Forbidden الرمز المميز يفتقر إلى دور التطبيق المطلوب، أو أن مستأجره لا يتطابق مع {tenantId}. صحح عدم تطابق الإذن أو الموافقة أو المستأجر قبل إعادة المحاولة.
429 Too Many Requests تجاوز المتصل الحد الأقصى لطلبات التحقق من الأهلية. احترم Retry-After وحاول مرة أخرى مع التوقف والارتباك.
503 Service Unavailable لم يتم تحديد الأهلية. لا تحتوي الاستجابة على محتوى. احترم Retry-After: 30 وحاول مرة أخرى. لا تعامل هذا الرد على أنه enabled: false.

طلب ترميز النص الأساسي

يستخدم الجسم تنسيق OTLP/HTTP+JSON القياسي: ExportTraceServiceRequest مع resourceSpans → scopeSpans → spans. ضع في اعتبارك التفاصيل التالية:

  • أرسل traceId (16 بايت) و spanId (8 بايت) كسلاسل سداسية صغيرة بحروف.
  • startTimeUnixNano و endTimeUnixNanoهي سلاسل تحمل نانوثواني عصر يونكس.
  • kind هي القيمة الصحيحة لعدد OTLP (على سبيل المثال، 1 ل INTERNAL). status.code هو العدد الصحيح (على سبيل المثال، 1 ل OK، 2 ل ERROR).
  • أرسل جميع قيم السمات ك stringValue.

شكل الاستجابة

200 OK الرد يعني أن العميل 365 عالج الطلب. لا يضمن أن كل امتداد تم توجيهه إلى وجهة. افحص كلا الاثنين partialSuccess و results.

تبلغ المصفوفة results عن النتائج لكل امتداد في كل وجهة ذات صلة:

  • sent - تم توجيه الامتداد إلى الوجهة.
  • rejected - لم يتم توجيه الامتداد. المجال reason يفسر السبب.
  • not_routed - لم يتم تحديد الوجهة لـ span. المجال reason يفسر السبب.

على سبيل المثال، يمكن أن يعود الامتداد الذي تم توجيهه بنجاح:

{
  "partialSuccess": {
    "rejectedSpans": 0,
    "errorMessage": ""
  },
  "results": [
    {
      "spanId": "0123456789abcdef",
      "sinks": {
        "flashpoint": {
          "status": "sent"
        },
        "sentinel": {
          "status": "sent"
        },
        "esp": {
          "status": "sent"
        }
      }
    }
  ]
}

إذا لم يكن المستأجر مؤهلا، يمكن للطلب أن يعود 200 OK. في هذه الحالة، results يظهر أن الامتدادات قد تم رفضها:

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

بالنسبة لقرارات توجيه الطلب الكامل، partialSuccess.rejectedSpans يمكن أن تبقى 0 حتى عندما results تظهر أن كل امتداد تم رفضه. لا تستخدم partialSuccess أو رمز حالة HTTP وحده كدليل على الاستيعاب. تكون أسماء الحقول بصيغة camelCase في البيانات المنقولة. انظر الحدود وشروط السقوط لأسباب أخرى قد لا تظهر التليمترية.

أصغر طلب ممكن

يرسل أبسط اختبار من طرف إلى طرف امتدادا واحدا invoke_agent . هذا الـspan هو أصغر عنصر يصل إلى 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، ثم افحص results كما هو موضح في شكل الاستجابة. تأكد من أن الوجهات المعنية لها حالة sent.

الخطوة 4. تأكد من وصول البيانات بالفعل. لا تُعد استجابة 200 OK دليلاً على الاستيعاب؛ راجع التحقق من الاستيعاب للاطلاع على آلية التحقق. لنشر ملف نص محفوظ بدلا من ذلك، استبدل --data @- <<EOF ... EOF ب --data @./otlp-request.json.

مثال تشغيل العامل

يسأل مستخدم على Microsoft Teams "ما هو الطقس في سياتل؟". يستدعي وكيلك دالة GetWeather ، ويطلب من LLM تنسيق الإجابة والردود. يتكوّن هذا التنفيذ الواحد من أربعة نطاقات:

graph TD
    A["<b>invoke_agent</b> · spanId=A · parentSpanId=∅<br/><i>root - the run itself</i>"]
    B["<b>chat</b> · spanId=B · parentSpanId=A<br/><i>LLM picks the tool / formats reply</i>"]
    C["<b>execute_tool</b> · spanId=C · parentSpanId=A<br/><i>the GetWeather call</i>"]
    D["<b>output_messages</b> · spanId=D · parentSpanId=A<br/><i>final reply emitted to the user</i>"]
    A --> B
    A --> C
    A --> D

تعيين سمات على مستوى المقطع في كل مقطع:

Attribute قيمه المثال
traceId 0102030405060708090a0b0c0d0e0f10
gen_ai.conversation.id 19:abc@thread.tacv2
microsoft.session.id session-1234
microsoft.channel.name msteams
gen_ai.agent.id <AGENT_APP_ID>
gen_ai.agent.name WeatherBot
microsoft.a365.agent.blueprint.id <BLUEPRINT_APP_ID>
user.id <entra-user-objectid>
client.address 10.1.2.80
server.address weatherbot.example.com
server.port 443

Important

هذه السمات على مستوى التشغيل لا تُورَّث تلقائيًا. يجب أن تضبط gen_ai.conversation.id، microsoft.channel.name، و microsoft.session.id على كل امتداد.

Span A: invoke_agent (الجذر)

{
  "traceId": "0102030405060708090a0b0c0d0e0f10",
  "spanId": "1111111111111111",
  "parentSpanId": "",
  "name": "invoke_agent",
  "kind": 1,
  "startTimeUnixNano": "1736175600000000000",
  "endTimeUnixNano":   "1736175601500000000",
  "status": { "code": 1 },
  "attributes": [
    { "key": "gen_ai.operation.name",   "value": { "stringValue": "invoke_agent" } },
    { "key": "gen_ai.execution.type",   "value": { "stringValue": "HumanToAgent" } },
    { "key": "gen_ai.input.messages",   "value": { "stringValue": "[{\"role\":\"user\",\"content\":\"What's the weather in Seattle?\"}]" } },
    { "key": "gen_ai.output.messages",  "value": { "stringValue": "[{\"role\":\"assistant\",\"content\":\"It's 65F and partly cloudy in Seattle.\"}]" } },
    { "key": "user.email",              "value": { "stringValue": "alice@contoso.com" } }
    /* plus all the run-wide attributes listed above */
  ]
}

Span B: chat (استدعاء LLM)

{
  "traceId": "0102030405060708090a0b0c0d0e0f10",
  "spanId": "2222222222222222",
  "parentSpanId": "1111111111111111",
  "name": "chat",
  "kind": 1,
  "startTimeUnixNano": "1736175600200000000",
  "endTimeUnixNano":   "1736175600900000000",
  "status": { "code": 1 },
  "attributes": [
    { "key": "gen_ai.operation.name",      "value": { "stringValue": "chat" } },
    { "key": "gen_ai.request.model",       "value": { "stringValue": "gpt-4o" } },
    { "key": "gen_ai.provider.name",       "value": { "stringValue": "openai" } },
    { "key": "gen_ai.usage.input_tokens",  "value": { "stringValue": "42" } },
    { "key": "gen_ai.usage.output_tokens", "value": { "stringValue": "23" } }
    /* plus all the run-wide attributes */
  ]
}

النطاق 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 */
  ]
}

إرسال بيانات القياس عن بُعد

استخدم مجموعة تطوير تطبيقات OTel

يرسل معظم الشركاء تتبعات من خلال OTel SDK بدلا من HTTP المدلفة يدويا. يعالج SDK الإرسال في دفعات وإعادة المحاولة وترميز OTLP/HTTP+JSON نيابة عنك. عيّن نقطة نهاية المُصدِّر وأدرج الترويسة Authorization.

نقطة نهاية المُصدِّر هي عنوان URL للمسار نفسه، بما في ذلك سلسلة الاستعلام:

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

(استخدم /observability/... بدلا من /observabilityService/... للمسار المفوض.)

Python

from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

exporter = OTLPSpanExporter(
    endpoint="https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1",
    headers={"Authorization": f"Bearer {token}"},
)

الحزمة: opentelemetry-exporter-otlp-proto-http.

Node.js / TypeScript

import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";

const exporter = new OTLPTraceExporter({
  url: "https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1",
  headers: { Authorization: `Bearer ${token}` },
});

الحزمة: @opentelemetry/exporter-trace-otlp-http.

.NET

using OpenTelemetry.Exporter;

services.AddOpenTelemetry().WithTracing(b => b
    .AddOtlpExporter(o =>
    {
        o.Endpoint = new Uri("https://agent365.svc.cloud.microsoft/observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces?api-version=1");
        o.Headers = $"Authorization=Bearer {token}";
        o.Protocol = OtlpExportProtocol.HttpJson;
    }));

الحزمة: OpenTelemetry.Exporter.OpenTelemetryProtocol.

HTTP اليدوي

إذا كنت لا تستطيع أو لا تريد استخدام OTel SDK، فنشئ طلب OTLP/HTTP+JSON بنفسك وانشره. تحدد مواصفة OpenTelemetry OTLP/HTTP+JSON شكل الجسم:

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

كل <span> كائن حقوله المطلوبة هي traceIdو spanIdnameو kindstartTimeUnixNanoendTimeUnixNanoattributes(للامتدادات غير الجذرية). parentSpanId لقواعد الترميز (أوقات ترميز بالسلاسل النصية، سداسيtraceId / spanId، عددstatus.codekind / صحيح، جميع قيم السمات ك stringValue)، انظر نقاط النهايةوترميز جسم الطلب.

يتم تعريف مجموعة السمات التي يجب تعيينها على كل امتداد في تعاقدات الرسائل. للاطلاع على قائمة السمات الكاملة، انظر مرجع السمات. راجع مثال تشغيل العامل للاطّلاع على مثال عملي متكامل من البداية إلى النهاية يتضمن رمز Bearer المميز في الترويسة والمحتوى مضمّنًا.

يمكنك إرسال جميع نطاقات التتبّع الخاصة بعملية تشغيل واحدة ضمن جسم طلب POST واحد (وهو الخيار المفضّل: طلب واحد، أثر تتبّع واحد) أو عبر عدة طلبات POST. يقوم الخادم بإعادة إنشاء التشغيل من traceId + parentSpanId + gen_ai.conversation.id، لذلك كل امتداد يحمل ما يكفي ليتم ربطه بأي من الطريقتين.

عقود الرسائل

يحدّد هذا القسم النطاقات التي يمكنك إنشاؤها والسمات الخاصة بكلٍ منها. للحصول على مواصفات السمة حسب السمة الكاملة، راجع مرجع السمة.

أنواع العمليات

يجب أن يحتوي كل نطاق ترسله على gen_ai.operation.name مضبوطًا على إحدى هذه القيم الأربع (دون تمييز بين الأحرف الكبيرة والصغيرة). يقوم الخادم بإسقاط أي امتداد يحتوي على قيمة مفقودة أو غير معترف بها ويحسبها في partialSuccess.rejectedSpans.

gen_ai.operation.name المعنى أكثر مشكلة جرى البحث عنها على Google
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 عبر كل span ضمن تشغيل نصي واحد.
  3. اضبط gen_ai.conversation.id على كل امتداد بنفس القيمة. هذه القيمة هي مفتاح الربط الأساسي لـ"جميع النطاقات في هذا التشغيل". لا يتم نشره تلقائيا.
  4. اضبط microsoft.channel.name على كل امتداد بنفس القيمة. يمكن لنطاقات الأداة التي تفتقد إلى القناة أو المحادثة أن ترثهما من النطاق الأب invoke_agentفقط إذا كان النطاق الأب ضمن طلب OTLP نفسه، لذا عيّنهما بنفسك في كل نطاق.
  5. اضبط microsoft.session.id على كل امتداد عندما يكون لديك جلسة عمل منطقية.
  6. بالنسبة إلى استدعاءات من وكيل إلى وكيل حيث يكون الوكيل الفرعي في طلب منفصل، أعِد استخدام العنصر نفسه gen_ai.conversation.id واستخدم سمات microsoft.a365.caller.agent.* (راجع مرجع السمات) لالتقاط سياق الوكيل المستدعي.

شجرة الامتدادات الأربعة في مثال تشغيل العامل هي الشكل المتعارف عليه.

أشكال التشغيل الشائعة

شكل امتدادات للانبعاث Notes
روبوت الدردشة أحادي العامل (لا توجد أدوات، ولا نطاق LLM) واحد 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 (أو المخطط) الخاص بك، ويمكنك إصدار الرموز المميزة له.
المصادقه إذا استخدمت هوية مشتقة من Blueprint على مسار S2S، فإن مثيل الوكيل مسجل لدى Agent 365. المثيل المسجل لا يحتاج إلى دور التطبيق Agent365.Observability.OtelWrite.
المصادقه إذا استخدمت هوية غير مسجلة في مسار S2S، يُمنَح تطبيقك Agent365.Observability.OtelWrite دور التطبيق.
المصادقه إذا استخدمت المسار المفوض، يمنح تطبيقك النطاق المفوض.Agent365.Observability.OtelWrite
المصادقه كل عامل لديه معرف تطبيق Entra الخاص به كما هو الحال {agentId} في عنوان URL. بالنسبة للهويات المشتقة من المخطط، فإن معرف التطبيق هذا هو معرف هوية العامل، وليس معرف تطبيق المخطط. إذا لم يكن لدى العامل تسجيل Entra، فشاهد انتقاء القيم.
المصادقه يمنح مسؤول المستأجر الموافقة لـ Agent365.Observability.OtelWrite عندما يتطلب المسار دور التطبيق أو النطاق المفوض. بدون الموافقة المطلوبة، تصدر الرموز بدون الدور أو النطاق وتُرفض الطلبات برمز 403.
الترخيص تم تعيين ترخيص Microsoft 365 E7 أو Microsoft Agent 365 لمستخدم واحد على الأقل في مستأجر العميل (أي التعيين الفعلي، وليس مجرد وجود SKU في المستأجر فقط). بدون ترخيص مخصص، تظهر الردود results أن المقاطع قد رفضت. انظر المتطلبات المسبقة.
النطاقات يحدّد كل امتداد العناصر الأساسية على مستوى التشغيل بأكمله (التسلسل الهرمي للامتدادات وتجميعات التشغيل).
النطاقات 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 - ترميز السلسلة).
النطاقات تُعيِّن جميع النطاقات غير الجذرية parentSpanId؛ وتشترك جميع النطاقات ضمن تشغيل في traceId نفسه.
الحمولة نص الطلب ≤ 1 ميغابايت.
التحقق تقوم بفحص كلًا من partialSuccess وresults في كل استجابة وتُسجّل حالات الرفض.
التحقق قمت بتشغيل تدفق التحقق في التحقق من الاستيعاب مقابل عمليات التشغيل الأولى.

الخطوات التالية