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

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

## כיצד זה עובד

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

| יכולת | מקום ההרצה | הגדרה |
| --- | --- | --- |
| [כלים מובנים](/he/guides/built-in-tools) | ThunderPhone | הוראות בהנחיה; כלים מסוימים דורשים גם הגדרת סוכן |
| [חיבורי אפליקציות](/he/guides/connect-apps) | ThunderPhone והספק המחובר | חברו את החשבון וצרפו פעולות מאושרות |
| [חיבורי API](/he/guides/api-connections) וכלי פונקציה | ממשק ה-HTTP API שלכם | הגדירו את נקודת הקצה והסכמה, או קבלו קריאות פונקציה באמצעות וובהוק |
| [שרתי MCP](/he/guides/mcp-servers) | שרת MCP מרוחק | הוסיפו את השרת, גלו את הכלים שלו וצרפו אותו לסוכן |

---

## סכמת הכלי

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

```json
{
  "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` | אובייקט | לא | כותרות מותאמות אישית שיש לכלול |

<Note>
  תצורת ה-`endpoint` **אינה** נשלחת למודל ה-AI — היא משמשת רק את ThunderPhone לביצוע הקריאה לכלי.
</Note>

---

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

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

| | כלי **עם** `endpoint` | כלי **ללא** `endpoint` |
|---|---|---|
| יעד הבקשה | ישירות אל `endpoint.url` | [כתובת ה-webhook מדור קודם](/api-reference/organizations#legacy-single-url-webhook) של הארגון שלכם |
| גוף הבקשה | פורמט הבקשה שנבחר (ארגומנטים בלבד כברירת מחדל) | מעטפת `telephony.tool` / `web.tool` |
| כותרות | `endpoint.headers` שלכם + `X-ThunderPhone-Call-ID` + `X-ThunderPhone-Signature-V2` + `X-ThunderPhone-Signature` | `Content-Type` + `X-ThunderPhone-Signature-V2` + `X-ThunderPhone-Signature` |
| מפתח חתימה | סוד ה-webhook של הארגון | סוד ה-webhook של הארגון |

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

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

כאשר ה-AI מפעיל כלי שיש לו `endpoint`, ThunderPhone שולח
בקשה לכתובת ה-URL שלכם:

### כותרות בקשה

```http
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](/he/guides/verify-webhook-signatures)
- `X-ThunderPhone-Signature` — HMAC-SHA256 מדור קודם של בתים מדויקים
  מגוף הבקשה, עם אותו מפתח, שעדיין נשלח עבור מאמתים קיימים
- `X-ThunderPhone-Call-ID` — מזהה השיחה הנוכחית

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

<Warning>
  החתימה משתמשת כסוד במפתח ה-webhook ברמת הארגון מתוך
  [`GET /v1/webhook`](/api-reference/organizations#legacy-single-url-webhook).
  אם הארגון שלכם מעולם לא הגדיר webhook מדור קודם, אין
  סוד וקריאות לכלים כוללות **רק** את `X-ThunderPhone-Call-ID` — מטפל
  שנכשל באופן קשיח כאשר חסרה חתימה ידחה אותן.
  הגדירו את ה-webhook מדור קודם כדי לקבל סוד, או הוסיפו סוד משותף משלכם
  ב-`endpoint.headers`.
</Warning>

### פורמט בקשה

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

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

#### Standard

`standard` שולח רק את ארגומנטי הכלי, ללא מעטפת. זוהי ברירת המחדל, והיא משמרת את גוף הבקשה המקורי של ThunderPhone בית אחר בית:

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

#### Vapi

`vapi` שולח את [הודעת השרת `tool-calls` של Vapi](https://docs.vapi.ai/tools/custom-tools)
במבנה המתועד על ידי Vapi. הערך `call.id` הוא מזהה השיחה של ThunderPhone. מזהה
ה-`id` של קריאת הכלי ייחודי להפעלה ונעשה בו שימוש חוזר להתאמה לתוצאת
נקודת הקצה. השיחה מופיעה גם ב-`toolCallList` וגם ב-`toolWithToolCallList`,
כאשר `function.arguments` הוא אובייקט JSON:

```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 עם מזהה קריאת הכלי התואם:

```json
{
  "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](https://docs.retellai.com/build/single-multi-prompt/custom-function):

```json
{
  "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](/he/guides/verify-webhook-signatures).

### תגובה

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

```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`
(שיחות ווב) חתומה. בניגוד ל-[התראות ביקורת](/he/webhooks/events)
שנשלחות לנקודות קצה של webhook לאחר הביצוע, בקשה זו **היא**
הביצוע — תגובת ה-HTTP שלכם היא תוצאת הכלי.

```json
{
  "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 אחר.

<Note>
  [נקודות קצה של webhook](/he/webhooks/endpoints) שנרשמו כמנויים
  מקבלות בנוסף התראת `telephony.tool` / `web.tool` שאינה חוסמת
  **לאחר** כל ביצוע של כלי (בכל נתיב שהריץ אותו), כולל
  תגובת הכלי — שימושי ליומני ביקורת. עיינו ב-
  [קטלוג האירועים](/he/webhooks/events).
</Note>

---

## אימות חתימה

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

- `X-ThunderPhone-Signature-V2` חותמת על חותמת הזמן, השיטה, הנתיב
  והמחרוזת לשאילתה כפי שנשלחו, וכן על הבייטים המדויקים של הגוף. דחו בקשות שחותמת
  הזמן שלהן רחוקה ביותר מ-5 דקות מהשעון שלכם.
- `X-ThunderPhone-Signature` (מדור קודם) חותמת רק על הבייטים של הגוף, ועל
  מחרוזת בייטים ריקה עבור `GET` / `DELETE`. היא עדיין נשלחת, ללא שינוי.

עזרי ה-SDK בודקים את כותרת V2, כולל חלון הזמן של 5 דקות:

<CodeGroup>
```python 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}
```

```javascript 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 });
});
```
</CodeGroup>

מתכונים מלאים — המחרוזת החתומה, דוגמה מפורטת, קוד ללא ה-SDK, המקרה של `GET` / `DELETE` וההסתייגות לגבי היעדר סוד — נמצאים ב-[אימות חתימות וובהוק](/he/guides/verify-webhook-signatures).

---

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

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

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

---

## שיטות מומלצות

<AccordionGroup>
  <Accordion title="כתבו תיאורים ברורים">
    השדה `description` מסייע ל-AI להבין **מתי** להשתמש בכלי. פרטו במדויק מה הוא עושה ומתי מתאים להשתמש בו.
  </Accordion>

  <Accordion title="טפלו בשגיאות בצורה מסודרת">
    החזירו הודעות שגיאה שה-AI יכול להבין: `{"error": "No slots available for that date"}` במקום שגיאות 500 כלליות.
  </Accordion>

  <Accordion title="שמרו על תשובות תמציתיות">
    החזירו רק את מה שה-AI צריך כדי להמשיך את השיחה. מטענים גדולים מאטים את זמני התגובה.
  </Accordion>

  <Accordion title="השתמשו בשדות חובה בתבונה">
    סמנו שדות כ-`required` רק כאשר הם נחוצים באמת. ה-AI יבקש מהמשתמש את המידע הנדרש לפני קריאה לכלי.
  </Accordion>
</AccordionGroup>

---

## קשור

<CardGroup cols={2}>
  <Card title="כלים מובנים" icon="wrench" href="/he/guides/built-in-tools">
    הפעילו פעולות שיחה המנוהלות על ידי הפלטפורמה ללא הגדרת נקודת קצה.
  </Card>
  <Card title="חיבורי אפליקציות" icon="plug" href="/he/guides/connect-apps">
    כלים המנוהלים על ידי הפלטפורמה עבור HubSpot, Salesforce, Slack, Google
    Calendar, Google Sheets ו-Cal.com — ללא צורך בנקודת קצה.
  </Card>
  <Card title="שרתי MCP" icon="server" href="/he/guides/mcp-servers">
    חברו שרת MCP ואפשרו לסוכן לקרוא לכלים שלו.
  </Card>
  <Card title="חיבורי API" icon="code" href="/he/guides/api-connections">
    אינטגרציות REST לשימוש חוזר שאפשר לחבר לסוכנים.
  </Card>
  <Card title="אימות חתימות webhook" icon="shield-check" href="/he/guides/verify-webhook-signatures">
    מסייע אימות אחד עבור webhooks וקריאות לכלים.
  </Card>
</CardGroup>
