ThunderPhone 2.0 באוויר.בשירות עצמי, החל מ-2¢/דקה.קראו את הודעת ההשקה

Function Tools

כלי פונקציות

ציידו את סוכני ה-AI שלכם בכלי פונקציות שקוראים לממשקי API חיצוניים במהלך השיחה — אחזרו נתוני לקוחות, קבעו פגישות, עדכנו רשומות — עם פרמטרים בעלי טיפוס.

כלי פונקציה מאפשרים לסוכני ה-AI שלכם להפעיל ממשקי API חיצוניים במהלך שיחות טלפון. השתמשו בהם כדי לחפש נתוני לקוחות, לבדוק זמינות, לקבוע פגישות או לבצע כל פעולה שה-Backend שלכם תומך בה.

כיצד זה עובד

  1. הגדירו כלים באמצעות סכמה (אילו ארגומנטים הכלי מקבל)
  2. ספקו הגדרת endpoint (לאן ThunderPhone קורא ל-API שלכם) — או השמיטו אותה כדי לקבל קריאות לכלים בוובהוק של הארגון שלכם
  3. במהלך שיחה, ה-AI מחליט מתי להשתמש בכלי על סמך השיחה
  4. ThunderPhone קורא לנקודת הקצה שלכם עם ארגומנטי הכלי
  5. תגובת ה-API שלכם מוזנת בחזרה ל-AI כדי להמשיך את השיחה
יכולתמקום ההרצההגדרה
כלים מובנים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מחרוזתכןמסביר ל-AI מתי להשתמש בכלי זה
parametersאובייקטכןסכמת JSON עבור ארגומנטי הכלי

תצורת נקודת קצה

שדהסוגנדרשתיאור
urlמחרוזתכןכתובת נקודת הקצה של ה-API שלכם
methodמחרוזתלאשיטת HTTP (ברירת מחדל: POST)
headersאובייקטלאכותרות מותאמות אישית שיש לכלול

שני נתיבי הפעלה

הבקשה שהשרת שלכם מקבל תלויה בשאלה אם לכלי יש endpoint:

כלי עם endpointכלי ללא endpoint
יעד הבקשהישירות אל endpoint.urlכתובת ה-webhook מדור קודם של הארגון שלכם
גוף הבקשהפורמט הבקשה שנבחר (ארגומנטים בלבד כברירת מחדל)מעטפת 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
מפתח חתימהסוד ה-webhook של הארגוןסוד ה-webhook של הארגון

שני הנתיבים הם חוסמים — ה-AI ממתין באמצע משפט לתוצאה. זמן הקצוב המוגדר כברירת מחדל הוא 20 שניות; הגדירו את timeout ברמה העליונה של הכלי כדי לאפשר ביצוע ארוך יותר, עד למרב הפלטפורמה של 180 שניות. שמרו על מטפלים מהירים. אפשר לשלב: בשיחה שבה לארגון יש כתובת וובהוק, כלים עם endpoint נקראים ישירות והיתר חוזרים לוובהוק.

קריאות ישירות לנקודת קצה

כאשר ה-AI מפעיל כלי שיש לו 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 מותאם אישית מקבל עדיפות.

פורמט בקשה

לכל חיבור API יש הגדרת request_format. בחרו ב-vapi או retell כאשר כלי מיובא צריך להמשיך לקרוא לנקודת קצה שנבנתה עבור אותה פלטפורמה. חיבורים חדשים וקיימים מוגדרים כברירת מחדל ל-standard.

עבור POST / PUT / PATCH, ThunderPhone מסדרת את המעטפת שנבחרה באופן קנוני (מפתחות ממוין, מפרידים קומפקטיים). שתי החתימות מכסות את הבתים המדויקים האלה.

Standard

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 מספקת לסוכן ה-AI את מחרוזת ה-result ללא המעטפת. היא מקבלת גם ערך JSON לצורך תאימות עם נקודות קצה שכבר מחזירות ערך כזה. error במקום result מוחזר לסוכן ה-AI כשגיאת כלי. אם נקודת הקצה מחזירה מעטפת 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 מכסה את מחרוזת השאילתה כפי שנשלחה; החתימה הישנה מחושבת על פני מחרוזת הבתים הריקה. ראו אימות חתימות webhook.

תגובה

החזירו תגובת JSON עם תוצאת הכלי:

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

התגובה מעוצבת ומסופקת ל-AI כדי להמשיך את השיחה. תגובות שאינן JSON נעטפות בתור {"data": "<text>"}; זמני קצובה וכשלי חיבור מדווחים ל-AI כשגיאות, כדי שהסוכן יוכל להתנצל ולהמשיך במקום להיתקע.

ניתוב במצב webhook

כלים ללא endpoint מנותבים לכתובת ה-webhook מדור קודם של הארגון שלכם בתור בקשת telephony.tool (שיחות טלפון) או web.tool (שיחות ווב) חתומה. בניגוד ל-התראות ביקורת שנשלחות לנקודות קצה של webhook לאחר הביצוע, בקשה זו היא הביצוע — תגובת ה-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 — אותו חוזה תגובה כמו בקריאות ישירות לנקודת קצה. הבקשה נחתמת באמצעות סוד ה-webhook של הארגון, עם שתי כותרות החתימה, כמו כל webhook אחר.


אימות חתימה

קריאות ישירות לכלים נחתמות באותו אופן כמו וובהוקים, באמצעות סוד הוובהוק של הארגון שלכם:

  • 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 מסייע ל-AI להבין מתי להשתמש בכלי. פרטו במדויק מה הוא עושה ומתי מתאים להשתמש בו.

טפלו בשגיאות בצורה מסודרת

החזירו הודעות שגיאה שה-AI יכול להבין: {"error": "No slots available for that date"} במקום שגיאות 500 כלליות.

שמרו על תשובות תמציתיות

החזירו רק את מה שה-AI צריך כדי להמשיך את השיחה. מטענים גדולים מאטים את זמני התגובה.

השתמשו בשדות חובה בתבונה

סמנו שדות כ-required רק כאשר הם נחוצים באמת. ה-AI יבקש מהמשתמש את המידע הנדרש לפני קריאה לכלי.


קשור