ThunderPhone 2.0 متاح الآن.خدمة ذاتية، ابتداءً من 2 سنت/دقيقة.اقرأ الإعلان

Developer cookbook

إنشاء تكامل أداة (API)

اسمح لوكيلك باستدعاء واجهات API الخاصة بك أثناء المحادثة — للبحث في قاعدة بيانات، أو إنشاء تذكرة، أو الاستعلام عن طلب.

تكامل أداة هو نقطة نهاية HTTP قابلة لإعادة الاستخدام يمكن لوكيل استدعاؤها أثناء مكالمة. تمنح ThunderPhone وصفًا بمخطط JSON للأداة بالإضافة إلى عنوان URL لنقطة النهاية؛ ويقرر الوكيل متى يستدعيها بناءً على المحادثة، ثم تجري ThunderPhone طلب HTTP الصادر من خوادمها وتعيد الاستجابة إلى الوكيل.

يشرح هذا الدليل إنشاء أداة للبحث عن الطقس من البداية إلى النهاية.

بنية الأداة

جزآن:

  1. المخطط — تعريف دالة بأسلوب OpenAI ({type: "function", function: {name, description, parameters}}) يوضح لـ LLM ما الذي تفعله الأداة وما الوسائط التي تقبلها.
  2. نقطة النهاية — عنوان URL الذي تستدعيه خوادم ThunderPhone عندما يقرر LLM استخدام الأداة. يكون الطلب JSON POST مع الوسائط التي اختارها LLM في النص.

1. اختر محررًا

لوحة التحكم

افتح الاتصالات → واجهات API، وأنشئ اتصال API أو حرّره، وبدّل محرر المعلمات إلى JSON، ثم أضف التنسيق هناك.

واجهة API للتكاملات

أنشئ المواصفة باستخدام POST /v1/integrations، أو حدّثها باستخدام PATCH /v1/integrations/{id}.

ينشئ كلا المسارين تكاملًا محفوظًا. اربط هذا التكامل بالوكيل بعد حفظه. لا تحتوي واجهة Agents API على حقل tools مضمّن قابل للكتابة. يستخدم هذا الدليل مسار واجهة API للتكاملات.

2. أنشئ التكامل

curl -X POST https://api.thunderphone.com/v1/integrations \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Weather API",
    "spec": {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Return the current weather for a zip code.",
        "parameters": {
          "type": "object",
          "properties": {
            "zip": { "type": "string", "description": "5-digit US ZIP code" }
          },
          "required": ["zip"]
        }
      }
    },
    "endpoint_url":    "https://api.example.com/weather",
    "endpoint_method": "GET",
    "headers": [
      { "key": "X-Api-Key", "value": "your-provider-key" }
    ]
  }'

احفظ id المُعاد (وهو UUID). قيم الترويسات للكتابة فقط: تعرض الاستجابات أسماء الترويسات فقط، ويمكن لطلب PATCH لاحق إرسال ترويسة دون value للاحتفاظ بالقيمة المخزنة.

أعلِن format: "email" في مَعلمات العنوان

يجب أن توضّح المَعلمة التي تتلقى عنوان بريد إلكتروني ذلك في مخططها:

"email": { "type": "string", "format": "email", "description": "The caller's email address" }

format أكثر من مجرد تلميح. بالنسبة إلى مخطط بريد إلكتروني محلول، وقبل استدعاء نقطة النهاية، يزيل ThunderPhone المسافات الزائدة من القيمة، ويحوّل النطاق إلى أحرف صغيرة، ويحوّل الكلمات الإنجليزية المستقلة at وdot وunderscore وdash وhyphen إلى رموزها، ويزيل المسافات البيضاء الموجودة مباشرة حول @ و. و_ و-. تحمل الكلمات المعنى نفسه سواء احتوى النص المفرغ مسبقاً على رمز @ حرفي أم لا: يتحوّل "john dot smith at gmail dot com" إلى john.smith@gmail.com.

يُرفض أي فراغ داخلي آخر بدلاً من وصله بصمت. كلمات الفواصل المنطوقة متاحة بالإنجليزية فقط؛ وتفشل الصيغ المتباعدة غير الإنجليزية أو غير المعروفة بشكل مغلق. تُقبل أسماء النطاقات الدولية الصحيحة وأجزاء المحلية SMTPUTF8. يبقى إدخال Punycode بتنسيق Punycode، ويبقى إدخال النطاقات Unicode بتنسيق Unicode بعد تسوية المحلل، لذا تتلقى واجهة برمجة التطبيقات لديك التمثيل الاصطلاحي الذي قدّمه المتصل. إذا كانت القيمة النهائية غير صالحة، فإن الأداة لا تُستدعى. يتلقى الوكيل invalid_email_argument لإخباره بتأكيد التهجئة مع المتصل وإعادة إرسال العنوان الحرفي.

لا يتغير البريد الإلكتروني الاختياري المحذوف. كذلك، لا تتغير null أو السلسلة الفارغة أو السلسلة التي تتكون من مسافات بيضاء فقط عندما تكون الخاصية اختيارية أو تقبل القيم الفارغة؛ وتُرفض القيم نفسها لبريد إلكتروني مطلوب لا يقبل القيم الفارغة.

تُفحص مراجع المخطط المحلية مثل #/$defs/email و #/definitions/email، إلى جانب anyOf وoneOf وallOf، مع حدود للحلقات والعمق. يُعد $ref غير المحلي أو غير القابل للحل حداً معروفاً للإنفاذ ويُمرر دون تغيير، وكذلك الاستدعاء الذي لا تحتوي لقطة أداته على مخطط قابل للاستخدام. أبقِ مخططات البريد الإلكتروني محلية عندما تحتاج إلى تطبيق البوابة.

تُمرر المَعلمات التي لا تحتوي على تنسيق بريد إلكتروني مفروض تماماً كما أنشأها النموذج.

التنسيقات المدعومة هي date-time وtime وdate وduration، وemail وhostname وipv4 وipv6 وuuid؛ ولا يُسوّى ويُفرض اليوم سوى email.

3. اختبر نقطة النهاية في بيئة الاختبار المعزولة

قبل ربط التكامل بوكيل، أرسل طلباً موقّعاً من خوادم ThunderPhone لتأكيد الاتصال:

curl -X POST https://api.thunderphone.com/v1/integrations/test-request \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url":    "https://api.example.com/weather?zip=94110",
    "method": "GET",
    "headers": { "X-Api-Key": "your-provider-key" }
  }'
Response
{
  "ok": true,
  "status": 200,
  "elapsed_ms": 187,
  "response_headers": { "content-type": "application/json" },
  "response_preview": "{\"temperature_f\": 64, ...}"
}

يعزّز هذا الاختبار أيضاً وسائل الحماية من SSRF في ThunderPhone — إذ تُرجع الطلبات إلى localhost أو نطاقات عناوين IP الخاصة 400 code=url_not_allowed.

4. اربط التكامل بوكيل

أرفق عبر integration_ids عند إنشاء وكيل أو تحديثه:

curl -X PATCH https://api.thunderphone.com/v1/agents/12 \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "integration_ids": ["f9b5a1a4-..."]
  }'

يمكنك ربط عدة تكاملات بوكيل واحد. يمكن لموجّه الوكيل الإشارة إليها بالاسم — «استخدم get_weather عندما يسأل المتصل عن الأحوال الجوية» — أو يمكنه اكتشافها ضمنيًا من أوصاف المخطط.

5. نفّذ نقطة النهاية

عندما يستدعي الوكيل الأداة، يرسل ThunderPhone طلب POST موقّعًا إلى endpoint_url الخاص بك:

POST /weather HTTP/1.1
Host: api.example.com
X-Api-Key: your-provider-key
X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<HMAC-SHA256 hex>
X-ThunderPhone-Signature: <HMAC-SHA256 hex>
X-ThunderPhone-Call-ID: 987654321
Content-Type: application/json

{"zip": "94110"}

يستجيب خادمك بتنسيق JSON يُعاد تمريره إلى LLM:

{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}

يستوعب LLM تلك الاستجابة ويقول للمتصل ملخصًا بصياغة بشرية.

6. اختبر الدورة

شغّل جلسة ميكروفون مع الوكيل واطرح السؤال الذي تعالجه أداتك («كيف هو الطقس في 94110؟»). يعرض النص المفرغ للمكالمة الرحلة الكاملة ذهابًا وإيابًا:

{
  "call_id": 987654321,
  "transcripts": [
    { "role": "user",
      "content": "What's the weather in 94110?" },
    { "role": "tool_call",
      "content": "{\"tool_call\": \"get_weather\", \"arguments\": {\"zip\": \"94110\"}}" },
    { "role": "tool_response",
      "content": "{\"tool_name\": \"get_weather\", \"response\": {\"temperature_f\": 64, \"condition\": \"Partly cloudy\"}}" },
    { "role": "agent",
      "content": "It's 64 degrees and partly cloudy." }
  ]
}

يمكنك جلب ذلك عبر GET /v1/calls/{call_id}/transcript؛ ويتوفر تدفق الأحداث الخام (مع توقيت كل إدخال وإزاحات الصوت) في GET /v1/calls/{call_id}/history.

في واجهات سرد المكالمات والتحليلات، يعرض ThunderPhone الآن مكالمات الاختبار بشكل منفصل عن حركة الاتصال الفعلية. يمكن لاختبارات Browser Talk والمحاكاة إعادة استخدام رقم هاتف حقيقي وقد تبدو واردة، لكنها لا تُحتسب ضمن إجماليات مكالمات الإنتاج أو الدرجات أو مقاييس المشكلات.

أخطاء شائعة

الوكيل لا يستدعي الأداة أبدًا

يقرر LLM بناءً على وصف الأداة. إذا لم يتطابق سؤال المتصل مع الوصف، فلن يستدعي النموذج الأداة. حسّن الوصف (أضف المرادفات والصياغات الشائعة) أو اذكرها صراحةً في موجّه الوكيل («عندما يسأل المتصل عن الطقس، استخدم get_weather.»).

تُرجع الأداة بيانات كثيرة جدًا

تُقتطع الاستجابات التي تتجاوز 6 كيلوبايت في معاينة النص المفرغ. أرجع الحقول التي يحتاجها LLM فقط — وليس الصف كاملًا.

انتهاء المهلات

تحتوي نقاط نهاية الأدوات على مهلة افتراضية مدتها 10 ثوانٍ. إذا كنت تحتاج إلى مدة أطول، عالج الأمر بشكل غير متزامن: أرجع {"status": "pending", "request_id": "..."} واعرض النتيجة عبر استدعاء أداة منفصل.

إدارة الإصدارات

ينشئ كل PATCH للتكامل مراجعة جديدة. افحص GET /v1/integrations/{id}/versions لمعرفة من غيّر ماذا. إذا أفسدت مخطط أداة، يمكنك التراجع يدويًا عبر تنفيذ PATCH لإعادة لقطة أقدم.


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