> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thunderphone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# כלי פונקציות

> אפשרו לסוכני ה-AI שלכם לקרוא לממשקי API חיצוניים במהלך שיחות

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

## איך זה עובד

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

<Note>
  כלי פונקציה הם הנתיב לשימוש ב-API משלכם. ThunderPhone כולל גם
  כלים המנוהלים על ידי הפלטפורמה ואינם דורשים endpoint:
  [חיבורי אפליקציות](/he/guides/connect-apps) (HubSpot, Salesforce, Slack,
  Google Calendar, Google Sheets, Cal.com),
  [חיבורי API](/he/guides/api-connections), וכן
  [שרתי MCP](/he/guides/mcp-servers).
</Note>

***

## סכימת כלי

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

```json theme={null}
{
  "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"
    }
  }
}
```

### הגדרת פונקציה

| שדה           | סוג    | נדרש | תיאור                         |
| ------------- | ------ | ---- | ----------------------------- |
| `name`        | string | כן   | מזהה ייחודי לכלי              |
| `description` | string | כן   | מסביר ל-AI מתי להשתמש בכלי זה |
| `parameters`  | object | כן   | סכימת JSON עבור ארגומנטי הכלי |

### תצורת Endpoint

| שדה       | סוג    | נדרש | תיאור                          |
| --------- | ------ | ---- | ------------------------------ |
| `url`     | string | כן   | כתובת ה-endpoint של ה-API שלכם |
| `method`  | string | לא   | שיטת HTTP (ברירת מחדל: `POST`) |
| `headers` | object | לא   | כותרות מותאמות אישית שיש לכלול |

<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` | `Content-Type` + `X-ThunderPhone-Signature`                                                    |
| מפתח חתימה | סוד ה-webhook של הארגון                                                         | סוד ה-webhook של הארגון                                                                        |

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

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

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

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

```http theme={null}
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 של הבתים המדויקים של גוף הבקשה,
  עם מפתח שהוא **סוד ה-webhook של הארגון** שלכם
* `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>

### גוף הבקשה

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

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

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

### תגובה

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

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

```json theme={null}
{
  "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>

***

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

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

* HMAC-SHA256 על בתים מדויקים של גוף הבקשה (ה-JSON הקנוני — מפתחות ממוינים, ללא רווחים נוספים)
* עם המפתח של סוד ה-webhook של הארגון שלכם
* כלים מסוג `GET` / `DELETE` חותמים על מחרוזת בתים ריקה

<CodeGroup>
  ```python Python theme={null}
  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}
  ```

  ```javascript Node.js theme={null}
  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 });
  });
  ```
</CodeGroup>

המתכונים המלאים — כולל המקרה של גוף ריק וההסתייגות לגבי היעדר סוד — נמצאים ב-[אימות חתימות webhook](/he/guides/verify-webhook-signatures).

***

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

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

```json theme={null}
{
  "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` עוזר לבינה המלאכותית להבין **מתי** להשתמש בכלי. פרטו במדויק מה הוא עושה ומתי מתאים להשתמש בו.
  </Accordion>

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

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

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

***

## קשור

<CardGroup cols={2}>
  <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>
