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

Function Tools

כלי פונקציות

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

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

איך זה עובד

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

סכימת הכלי

כל כלי פועל לפי המבנה הזה:

{
  "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 עבור ארגומנטי הכלי

תצורת ה-endpoint

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

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

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

כלי עם endpointכלי ללא endpoint
יעד הבקשהישירות אל endpoint.urlכתובת ה-webhook הישנה של הארגון שלכם
גוף הבקשהארגומנטי כלי בלבדמעטפת telephony.tool / web.tool
כותרותendpoint.headers שלכם + X-ThunderPhone-Call-ID + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature
מפתח חתימההסוד של ה-webhook בארגוןהסוד של ה-webhook בארגון

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

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

כאשר סוכן הבינה המלאכותית מפעיל כלי שיש לו endpoint, ‏ThunderPhone שולחת בקשה לכתובת ה-URL שלכם:

כותרות בקשה

POST /appointments/search HTTP/1.1
Host: api.example.com
Content-Type: application/json
X-ThunderPhone-Signature: abc123...
X-ThunderPhone-Call-ID: 987654321
X-Api-Key: your-api-key

כותרות מותאמות אישית מתוך endpoint.headers שלכם תמיד נכללות כפי שהן, בנוסף לשתי כותרות במרחב השמות של ThunderPhone:

  • X-ThunderPhone-Signature — HMAC-SHA256 של הבתים המדויקים של גוף הבקשה, עם מפתח שהוא סוד הוובהוק של הארגון שלכם
  • X-ThunderPhone-Call-ID — מזהה השיחה הנוכחית

הערך Content-Type: application/json מוגדר אלא אם endpoint.headers שלכם דורסים אותו — ערך Content-Type מותאם אישית מקבל עדיפות.

גוף הבקשה

עבור POST / PUT / PATCH, הגוף מכיל בלבד את ארגומנטי הכלי (ללא מעטפת), בסריאליזציה קנונית (מפתחות ממוינים, מפרידים קומפקטיים):

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

עבור GET / DELETE, הארגומנטים נשלחים כ-פרמטרי שאילתה והגוף ריק — החתימה מחושבת אז על מחרוזת בתים ריקה. ראו אימות חתימות וובהוק.

תגובה

החזירו תגובת 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 — אותו חוזה תגובה כמו בקריאות ישירות לנקודת קצה. הבקשה חתומה עם סוד הוובהוק של הארגון על הגוף הגולמי, כמו כל וובהוק אחר.


אימות חתימה

קריאות ישירות לכלים נחתמות באותו אופן כמו webhooks:

  • HMAC-SHA256 על פני בתים מדויקים של גוף הבקשה (ה-JSON הקנוני — מפתחות ממוינים, ללא רווחים נוספים)
  • באמצעות סוד ה-webhook של הארגון שלכם
  • כלי GET / DELETE חותמים על מחרוזת בתים ריקה
Python
import hmac
import hashlib
 
def verify_tool_call(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)
 
@app.post("/appointments/search")
async def search_appointments(request: Request):
    body = await request.body()
    signature = request.headers.get("X-ThunderPhone-Signature", "")
 
    if not verify_tool_call(body, signature, WEBHOOK_SECRET):
        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
app.post('/appointments/search', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-thunderphone-signature'] || '';
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');
 
  if (!signature ||
      signature.length !== expected.length ||
      !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
    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 });
});

מתכונים מלאים — כולל המקרה של גוף ריק וההסתייגות לגבי היעדר סוד — זמינים ב-אימות חתימות webhook.


דוגמה: תהליך הזמנה מלא

הנה מערך כלים למערכת מלאה להזמנת תורים:

{
  "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 רק כשזה באמת נחוץ. הבינה המלאכותית תבקש מהמשתמש את המידע הנדרש לפני הקריאה לכלי.


קשור