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

Function Tools

أدوات الدوال

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

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

آلية العمل

  1. عرّف الأدوات باستخدام مخطط (الوسيطات التي تقبلها الأداة)
  2. وفّر إعداد endpoint (المكان الذي يستدعي فيه ThunderPhone واجهة برمجة التطبيقات لديك) — أو اتركه فارغًا لتلقي استدعاءات الأدوات عبر ويبهوك مؤسستك
  3. أثناء المكالمة، يحدد الذكاء الاصطناعي وقت استخدام الأداة بناءً على المحادثة
  4. يستدعي ThunderPhone نقطة النهاية لديك باستخدام وسيطات الأداة
  5. تُعاد استجابة واجهة برمجة التطبيقات لديك إلى الذكاء الاصطناعي لمتابعة المحادثة
الإمكانيةمكان التشغيلالإعداد
الأدوات المضمنةThunderPhoneتعليمات الموجّه؛ تحتاج بعض الأدوات أيضًا إلى إعداد وكيل
اتصالات التطبيقاتThunderPhone وموفر الخدمة المتصلاربط الحساب وأرفق الإجراءات المعتمدة
اتصالات API وأدوات الدوالواجهة HTTP API لديكعرّف نقطة النهاية والمخطط، أو تلقَّ استدعاءات الدوال عبر ويبهوك
خوادم MCPخادم MCP بعيدأضف الخادم، واكتشف أدواته، وأرفقه بالوكيل

مخطط الأداة

تتبع كل أداة هذه البنية:

{
  "type": "function",
  "function": {
    "name": "search_appointments",
    "description": "Find available appointment slots for a given date",
    "parameters": {
      "type": "object",
      "properties": {
        "date": {
          "type": "string",
          "description": "Date in YYYY-MM-DD format"
        },
        "service": {
          "type": "string",
          "description": "Type of service (e.g., 'consultation', 'follow-up')"
        }
      },
      "required": ["date"]
    }
  },
  "endpoint": {
    "url": "https://api.example.com/appointments/search",
    "method": "POST",
    "headers": {
      "X-Api-Key": "your-api-key"
    }
  },
  "timeout": 120
}

إعداد الأداة

الحقلالنوعمطلوبالوصف
timeoutرقملاالحد الأقصى لوقت التنفيذ بالثواني (الافتراضي: 20، الحد الأقصى: 180)

تعريف الدالة

الحقلالنوعمطلوبالوصف
nameسلسلة نصيةنعممعرّف فريد للأداة
descriptionسلسلة نصيةنعميشرح للذكاء الاصطناعي متى يستخدم هذه الأداة
parametersكائننعممخطط JSON لوسيطات الأداة

إعداد نقطة النهاية

الحقلالنوعمطلوبالوصف
urlسلسلة نصيةنعمعنوان URL لنقطة نهاية API لديك
methodسلسلة نصيةلاطريقة HTTP (الافتراضية: POST)
headersكائنلارؤوس مخصصة لتضمينها

مسارا الاستدعاء

يعتمد الطلب الذي يتلقاه خادمك على ما إذا كانت الأداة تحتوي على endpoint:

الأداة مع endpointالأداة من دون endpoint
وجهة الطلبمباشرةً إلى endpoint.urlعنوان URL القديم لخطاف الويب الخاص بمؤسستك
النصتنسيق الطلب المحدد (الوسيطات المجردة افتراضيًا)غلاف telephony.tool / web.tool
الرؤوسendpoint.headers الخاص بك + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature-V2 + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature-V2 + X-ThunderPhone-Signature
مفتاح التوقيعالسرّ الخاص بخطاف الويب للمؤسسةالسرّ الخاص بخطاف الويب للمؤسسة

كلا المسارين حاجبان — ينتظر الذكاء الاصطناعي النتيجة في منتصف الجملة. المهلة الافتراضية هي 20 ثانية؛ اضبط timeout في المستوى الأعلى للأداة للسماح بمدة تنفيذ أطول، حتى الحد الأقصى للمنصة البالغ 180 ثانية. أبقِ المعالجات سريعة. يمكن الجمع بين المسارين: في مكالمة تكون لمؤسستها عنوان URL للويبهوك، تُستدعى الأدوات التي تحتوي على endpoint مباشرةً، بينما تعود الأدوات الأخرى إلى الويبهوك.

استدعاءات نقطة النهاية المباشرة

عندما يستدعي الذكاء الاصطناعي أداة لها endpoint، يرسل ThunderPhone طلبًا إلى عنوان URL الخاص بك:

رؤوس الطلب

POST /appointments/search HTTP/1.1
Host: api.example.com
Content-Type: application/json
X-ThunderPhone-Signature-V2: t=1767225600,v1=5f2c...
X-ThunderPhone-Signature: abc123...
X-ThunderPhone-Call-ID: 987654321
X-Api-Key: your-api-key

تُضمَّن الرؤوس المخصصة من endpoint.headers دائمًا كما هي، بالإضافة إلى هذه الرؤوس ذات نطاق ThunderPhone:

  • X-ThunderPhone-Signature-V2 — HMAC-SHA256 مؤرخ زمنيًا للطريقة والمسار والاستعلام والنص، باستخدام سر webhook الخاص بمؤسستك. تحقّق من هذا الرأس وارفض الطلبات التي يزيد عمرها على 5 دقائق؛ راجع التحقق من تواقيع webhook
  • X-ThunderPhone-Signature — HMAC-SHA256 قديم للبايتات الدقيقة لنص الطلب، بالمفتاح نفسه، ولا يزال يُرسل لعمليات التحقق الحالية
  • X-ThunderPhone-Call-ID — معرّف المكالمة الحالية

يُضبط Content-Type: application/json ما لم تتجاوزه endpoint.headers الخاصة بك — تكون الأولوية لـ Content-Type المخصص.

تنسيق الطلب

يحتوي كل اتصال بواجهة برمجة التطبيقات على إعداد request_format. اختر vapi أو retell عندما يجب أن تستمر أداة مستوردة في استدعاء نقطة نهاية مُنشأة لتلك المنصة. تستخدم الاتصالات الجديدة والحالية standard افتراضيًا.

بالنسبة إلى POST / PUT / PATCH، يُسلسل ThunderPhone الغلاف المحدد بصيغة معيارية (مفاتيح مرتبة وفواصل مضغوطة). يغطي كلا التوقيعين هذه البايتات بالضبط.

قياسي

يرسل standard وسيطات الأداة فقط، دون غلاف. هذا هو الإعداد الافتراضي ويحافظ على نص طلب ThunderPhone الأصلي بايتًا ببايت:

{"date":"2025-01-02","service":"consultation"}

Vapi

يرسل vapi رسالة الخادم tool-calls الخاصة بـ Vapi بالصيغة التي توثقها Vapi. يكون call.id هو معرّف مكالمة ThunderPhone. ويكون معرّف استدعاء الأداة id فريدًا لهذا الاستدعاء، ويُعاد استخدامه لمطابقة نتيجة نقطة النهاية. يظهر الاستدعاء في كلٍّ من toolCallList و toolWithToolCallList، مع function.arguments ككائن JSON:

{
  "message": {
    "type": "tool-calls",
    "timestamp": 1725000000123,
    "call": { "id": "987654321" },
    "toolCallList": [
      {
        "id": "call_00112233445566778899aabbccddeeff",
        "type": "function",
        "function": {
          "name": "search_appointments",
          "arguments": { "date": "2025-01-02", "service": "consultation" }
        }
      }
    ],
    "toolWithToolCallList": [
      {
        "type": "function",
        "function": { "name": "search_appointments" },
        "toolCall": {
          "id": "call_00112233445566778899aabbccddeeff",
          "type": "function",
          "function": {
            "name": "search_appointments",
            "arguments": { "date": "2025-01-02", "service": "consultation" }
          }
        }
      }
    ]
  }
}

لا تُرسل الحقول الخاصة بـ Vapi فقط، مثل assistant وartifact وكائن call الكامل.

أعِد غلاف استجابة Vapi مع معرّف استدعاء الأداة المطابق:

{
  "results": [
    {
      "toolCallId": "call_00112233445566778899aabbccddeeff",
      "result": "{\"available_slots\":[\"9:00 AM\",\"2:00 PM\"]}"
    }
  ]
}

يمنح ThunderPhone الذكاء الاصطناعي سلسلة result غير المغلفة. كما يقبل قيمة JSON للتوافق مع نقاط النهاية التي تُعيد قيمة بالفعل. يُعاد error بدلًا من result إلى الذكاء الاصطناعي كخطأ في الأداة. إذا أعادت نقطة النهاية غلاف Vapi غير صالح أو غير مطابق، يسجل ThunderPhone تحذيرًا ويعود إلى تحليل الاستجابة القياسي بدلًا من إخفاق المكالمة.

Retell

يرسل retell الطلب الموثق لدالة مخصصة في Retell:

{
  "name": "search_appointments",
  "call": { "call_id": "987654321" },
  "args": { "date": "2025-01-02", "service": "consultation" }
}

يتضمن كائن call الحقل call_id فقط. لا يتضمن ThunderPhone الحقول الخاصة بـ Retell التي لا يمكنه توفيرها بدقة عند الإرسال، مثل agent_id أو transcript أو transcript_object أو metadata أو المتغيرات الديناميكية. يقبل Retell أي نص استجابة؛ ويمرره ThunderPhone باستخدام معالجة الاستجابة القياسية.

بالنسبة إلى GET / DELETE، تُرسل الوسيطات باعتبارها معلمات استعلام ويكون النص فارغًا بغض النظر عن request_format. يغطي توقيع V2 سلسلة الاستعلام كما أُرسلت؛ بينما يُحتسب التوقيع القديم على سلسلة البايتات الفارغة. راجع التحقق من توقيعات خطاف الويب.

الاستجابة

أعِد استجابة JSON بنتيجة الأداة:

{
  "available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
  "timezone": "America/Los_Angeles"
}

تُنسق الاستجابة وتُقدَّم إلى الذكاء الاصطناعي لمتابعة المحادثة. تُغلَّف الاستجابات غير التابعة لـ JSON بصيغة {"data": "<text>"}؛ وتُبلَّغ مهلات الانتظار وإخفاقات الاتصال إلى الذكاء الاصطناعي كأخطاء، لكي يتمكن الوكيل من الاعتذار والمتابعة بدلًا من التوقف.

توزيع وضع خطاف الويب

تُوزَّع الأدوات التي لا تحتوي على endpoint إلى عنوان URL لخطاف الويب القديم لمؤسستك كطلب موقّع من telephony.tool (مكالمات هاتفية) أو web.tool (مكالمات ويب). بخلاف إشعارات التدقيق التي تُسلَّم إلى نقاط نهاية خطاف الويب بعد التنفيذ، فإن هذا الطلب هو التنفيذ — استجابة HTTP الخاصة بك هي نتيجة الأداة.

{
  "type": "telephony.tool",
  "data": {
    "call_id": 987654321,
    "tool_name": "search_appointments",
    "arguments": { "date": "2026-04-21" },
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  }
}

يحمل web.tool ‏origin_domain بدلًا من from_number / to_number. استجب بنتيجة الأداة بتنسيق JSON — وفق عقد الاستجابة نفسه المستخدم في استدعاءات نقاط النهاية المباشرة. يُوقَّع الطلب بسر خطاف الويب الخاص بالمؤسسة، مع رأسي التوقيع كليهما، مثل كل خطاف ويب آخر.


التحقق من التوقيع

تُوقَّع استدعاءات الأدوات المباشرة بالطريقة نفسها التي تُوقَّع بها خطافات الويب، باستخدام سر خطاف الويب الخاص بمؤسستك:

  • يوقّع X-ThunderPhone-Signature-V2 الطابع الزمني والطريقة والمسار والاستعلام كما أُرسلت، وبايتات النص الأساسية الدقيقة. ارفض الطلبات التي يكون طابعها الزمني متقدماً أو متأخراً بأكثر من 5 دقائق عن ساعتك.
  • يوقّع X-ThunderPhone-Signature (القديم) بايتات النص الأساسية فقط، وسلسلة البايتات الفارغة لِـ GET / DELETE. ولا يزال يُرسل دون تغيير.

تتحقق مساعدات SDK من رأس V2، بما في ذلك نافذة الـ 5 دقائق:

Python
import json
 
from fastapi import FastAPI, HTTPException, Request
from thunderphone import verify_signature
 
app = FastAPI()
 
@app.post("/appointments/search")
async def search_appointments(request: Request):
    body = await request.body()
    query = request.scope.get("query_string", b"").decode("latin-1")
    path = request.url.path + (f"?{query}" if query else "")
 
    if not verify_signature(
        request.headers.get("X-ThunderPhone-Signature-V2"),
        secret=WEBHOOK_SECRET,
        method=request.method,
        path=path,
        body=body,
    ):
        raise HTTPException(status_code=401)
 
    data = json.loads(body)
    date = data["date"]
 
    # Look up availability
    slots = await get_available_slots(date)
 
    return {"available_slots": slots}
Node.js
import express from "express";
import { verifySignature } from "@thunderphone/sdk";
 
app.post('/appointments/search', express.raw({type: 'application/json'}), (req, res) => {
  const ok = verifySignature({
    header: req.header('X-ThunderPhone-Signature-V2'),
    secret: WEBHOOK_SECRET,
    method: req.method,
    path: req.originalUrl,
    body: req.body,
  });
  if (!ok) return res.status(401).send('Invalid signature');
 
  const { date, service } = JSON.parse(req.body);
 
  // Look up availability
  const slots = getAvailableSlots(date, service);
 
  res.json({ available_slots: slots });
});

تتوفر الوصفات الكاملة — السلسلة الموقّعة، ومثال عملي، وتعليمة برمجية بدون SDK، وحالة GET / DELETE، والتنبيه المتعلق بعدم وجود سر — في التحقق من توقيعات خطافات الويب.


مثال: تدفق حجز كامل

إليك مجموعة من الأدوات لنظام حجز مواعيد متكامل:

{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "search_appointments",
        "description": "Find available appointment slots",
        "parameters": {
          "type": "object",
          "properties": {
            "date": { "type": "string", "description": "YYYY-MM-DD" },
            "service": { "type": "string" }
          },
          "required": ["date"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/search",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "book_appointment",
        "description": "Book an appointment at a specific time",
        "parameters": {
          "type": "object",
          "properties": {
            "date": { "type": "string", "description": "YYYY-MM-DD" },
            "time": { "type": "string", "description": "HH:MM format" },
            "customer_name": { "type": "string" },
            "customer_phone": { "type": "string" }
          },
          "required": ["date", "time", "customer_name"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/book",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "cancel_appointment",
        "description": "Cancel an existing appointment",
        "parameters": {
          "type": "object",
          "properties": {
            "confirmation_number": { "type": "string" }
          },
          "required": ["confirmation_number"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/cancel",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    }
  ]
}

أفضل الممارسات

اكتب أوصافًا واضحة

يساعد حقل description الذكاء الاصطناعي على فهم متى يستخدم الأداة. حدّد بوضوح ما الذي تفعله ومتى يكون استخدامها مناسبًا.

عالج الأخطاء بسلاسة

أرجع رسائل خطأ يمكن للذكاء الاصطناعي فهمها: {"error": "No slots available for that date"} بدلًا من أخطاء 500 العامة.

حافظ على إيجاز الاستجابات

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

استخدم الحقول المطلوبة بحكمة

علّم الحقول بأنها required فقط عند الضرورة الفعلية. سيطلب الذكاء الاصطناعي من المستخدم المعلومات المطلوبة قبل استدعاء الأداة.


ذات صلة