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

אינטגרציית **כלי** היא נקודת קצה חוזרת לשימוש מסוג HTTP שסוכן יכול
להפעיל במהלך שיחה. אתם מספקים ל-ThunderPhone תיאור סכמת JSON
של הכלי יחד עם כתובת URL של נקודת קצה; הסוכן מחליט מתי לקרוא לה
על סמך השיחה, ו-ThunderPhone שולחת את בקשת ה-HTTP היוצאת מהשרתים שלה
ומחזירה את התגובה לסוכן.

<Note>
  לוח הבקרה מכסה את רוב צורכי הכלים ללא API זה: **חיבורים
  → אפליקציות** מחבר את Slack, HubSpot, Salesforce, Google Calendar,
  Google Sheets ו-Cal.com בכמה לחיצות OAuth; **חיבורים →
  ממשקי API** הופך כל API מסוג HTTP לפעולת סוכן (הדביקו פקודת cURL
  ואשף AI ייצור טיוטה של הכלי, עם בדיקת בקשה מובנית); וכן
  **חיבורים → MCP** מוסיף שרתי MCP. ראו
  [חיבורים](/he/guides/concepts). מדריך זה עוסק ב-API הגולמי
  שמתחת לממשק ממשקי ה-API.
</Note>

מדריך זה מציג יצירה של כלי לחיפוש מזג אוויר מקצה לקצה.

## המבנה של כלי

שני חלקים:

1. **הסכמה** — הגדרת פונקציה בסגנון OpenAI
   (`{type: "function", function: {name, description, parameters}}`)
   שמסבירה ל-LLM מה הכלי עושה ואילו ארגומנטים הוא מקבל.
2. **נקודת הקצה** — כתובת ה-URL שאליה שרתי ThunderPhone שולחים קריאה כאשר
   ה-LLM מחליט להשתמש בכלי. הבקשה היא JSON POST עם הארגומנטים
   שנבחרו על ידי ה-LLM כגוף הבקשה.

## 1. בחרו עורך

<CardGroup cols={2}>
  <Card title="לוח הבקרה" icon="window-maximize">
    פתחו את **חיבורים → ממשקי API**, צרו או ערכו את חיבור ה-API,
    העבירו את עורך הפרמטרים ל-**JSON**, והוסיפו שם את הפורמט.
  </Card>
  <Card title="API לאינטגרציות" icon="plug">
    צרו את המפרט באמצעות `POST /v1/integrations`, או עדכנו אותו באמצעות
    `PATCH /v1/integrations/{id}`.
  </Card>
</CardGroup>

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

## 2. צרו את האינטגרציה

```bash
curl -X POST https://api.thunderphone.com/v1/integrations \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Weather API",
    "spec": {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Return the current weather for a zip code.",
        "parameters": {
          "type": "object",
          "properties": {
            "zip": { "type": "string", "description": "5-digit US ZIP code" }
          },
          "required": ["zip"]
        }
      }
    },
    "endpoint_url":    "https://api.example.com/weather",
    "endpoint_method": "GET",
    "headers": [
      { "key": "X-Api-Key", "value": "your-provider-key" }
    ]
  }'
```

שמרו את ה־`id` שהוחזר (UUID). ערכי כותרות הם לכתיבה בלבד: התגובות
מפרטות רק את שמות הכותרות, ו־`PATCH` מאוחר יותר יכול לשלוח כותרת ללא
`value` כדי לשמור את הערך המאוחסן.

<Tip>
  השקיעו מחשבה אמיתית ב-`description` של הכלי ושל כל
  פרמטר. ה-LLM משתמש במחרוזות האלה בזמן ריצה כדי להחליט אם
  וכיצד לקרוא לכלי. תיאורים מעורפלים → קריאות מעורפלות לכלי.
</Tip>

### הצהירו על `format: "email"` בפרמטרים של כתובות דוא"ל

פרמטר שמקבל כתובת דוא"ל צריך לציין זאת בסכמה שלו:

```json
"email": { "type": "string", "format": "email", "description": "The caller's email address" }
```

`format` הוא יותר מרמז. עבור סכמת דוא"ל שנפתרה, לפני שנקודת
הקצה שלכם נקראת ThunderPhone מסיר רווחים מתחילת הערך ומסופו, ממיר
את הדומיין לאותיות קטנות, הופך את המילים האנגליות העצמאיות `at`,
`dot`, `underscore`, `dash` ו-`hyphen` לתווים שלהן, ומסיר רווחים
ישירות סביב `@`, `.`, `_` ו-`-`. למילים יש אותה משמעות בין אם
התמלול כבר מכיל `@` מילולי ובין אם לא:
`"john dot smith at gmail dot com"` הופך ל-
`john.smith@gmail.com`.

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

כתובת דוא"ל אופציונלית שלא סופקה אינה משתנה. גם `null`, מחרוזת ריקה
או מחרוזת שמכילה רווחים בלבד אינם משתנים כשהמאפיין אופציונלי או
מאפשר ערך ריק; אותם ערכים נדחים עבור כתובת דוא"ל נדרשת שאינה מאפשרת
ערך ריק.

הפניות סכמה מקומיות כגון `#/$defs/email` ו-`#/definitions/email`,
וכן `anyOf`, `oneOf` ו-`allOf`, נבדקות עם מגבלות מחזור ועומק. `$ref`
שאינו מקומי או שאינו ניתן לפענוח הוא מגבלת אכיפה ידועה והוא מועבר
ללא שינוי, וכך גם קריאה שתצלום המצב של הכלי שלה אינו כולל סכמה
שניתן להשתמש בה. שמרו סכמות דוא"ל מקומיות כשאתם צריכים שהשער יחול.

פרמטרים ללא פורמט דוא"ל נאכף מועברים בדיוק כפי שהמודל הפיק אותם.

הפורמטים הנתמכים הם `date-time`, `time`, `date`, `duration`,
`email`, `hostname`, `ipv4`, `ipv6` ו-`uuid`; כיום רק `email` מנורמל
ונאכף.

## 3. בדקו את נקודת הקצה בסביבת חול

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

```bash
curl -X POST https://api.thunderphone.com/v1/integrations/test-request \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url":    "https://api.example.com/weather?zip=94110",
    "method": "GET",
    "headers": { "X-Api-Key": "your-provider-key" }
  }'
```

```json Response
{
  "ok": true,
  "status": 200,
  "elapsed_ms": 187,
  "response_headers": { "content-type": "application/json" },
  "response_preview": "{\"temperature_f\": 64, ...}"
}
```

בדיקה זו גם מחזקת את הגנות ה-SSRF של ThunderPhone — בקשות אל localhost
או אל טווחי IP פרטיים מחזירות `400 code=url_not_allowed`.

## 4. קשרו את האינטגרציה לסוכן

צרפו באמצעות `integration_ids` בעת יצירה או עדכון של סוכן:

```bash
curl -X PATCH https://api.thunderphone.com/v1/agents/12 \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "integration_ids": ["f9b5a1a4-..."]
  }'
```

באפשרותכם לקשר אינטגרציות רבות לסוכן אחד. ההנחיה של הסוכן יכולה
להפנות אליהן לפי שם — "השתמשו ב-`get_weather` כשהמתקשר שואל
על תנאי מזג האוויר" — או שהוא יכול לגלות אותן במשתמע מתוך
תיאורי הסכימה.

## 5. ממשו את נקודת הקצה

כאשר הסוכן מפעיל את הכלי, ThunderPhone שולח בקשת POST חתומה אל
ה-`endpoint_url` שלכם:

```
POST /weather HTTP/1.1
Host: api.example.com
X-Api-Key: your-provider-key
X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<HMAC-SHA256 hex>
X-ThunderPhone-Signature: <HMAC-SHA256 hex>
X-ThunderPhone-Call-ID: 987654321
Content-Type: application/json

{"zip": "94110"}
```

השרת שלכם מחזיר JSON שמועבר בחזרה ל-LLM:

```json
{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}
```

ה-LLM מקבל את התגובה ומסכם אותה בשפה טבעית עבור המתקשר.

<Warning>
  החתימה מחושבת על גוף הבקשה הגולמי באמצעות אותו
  `secret` של נקודת הקצה שלכם ל-webhook. **אמתו אותה** — נקודות קצה
  של כלים חשופות לאינטרנט ונתונות לאותם סיכוני התחזות כמו
  webhooks. ראו
  [אימות חתימות webhook](/he/guides/verify-webhook-signatures).
</Warning>

## 6. בדקו את התהליך

הפעילו [סשן מיקרופון](/api-reference/mic-sessions) מול הסוכן
ושאלו את השאלה שהכלי שלכם מטפל בה ("מה מזג האוויר ב-94110?").
תמליל השיחה מציג את כל התהליך מקצה לקצה:

```json
{
  "call_id": 987654321,
  "transcripts": [
    { "role": "user",
      "content": "What's the weather in 94110?" },
    { "role": "tool_call",
      "content": "{\"tool_call\": \"get_weather\", \"arguments\": {\"zip\": \"94110\"}}" },
    { "role": "tool_response",
      "content": "{\"tool_name\": \"get_weather\", \"response\": {\"temperature_f\": 64, \"condition\": \"Partly cloudy\"}}" },
    { "role": "agent",
      "content": "It's 64 degrees and partly cloudy." }
  ]
}
```

באפשרותכם למשוך זאת דרך
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript);
זרם האירועים הגולמי (עם תזמון לכל רשומה והיסטי שמע) נמצא ב-
[`GET /v1/calls/{call_id}/history`](/api-reference/calls#get-history).

בממשקי רשימות השיחות והניתוח, ThunderPhone מדווח כעת על שיחות בדיקה בנפרד מתעבורה אמיתית. בדיקות ודימויים של Browser Talk יכולים להשתמש מחדש במספר טלפון אמיתי ועשויים להיראות כשיחות נכנסות, אך הם אינם נספרים בסיכומי שיחות הייצור, בציונים או במדדי תקלות.

## טעויות נפוצות

<AccordionGroup>
  <Accordion title="הסוכן לעולם לא מפעיל את הכלי">
    ה-LLM מחליט לפי תיאור הכלי. אם שאלת המתקשר אינה תואמת לתיאור,
    המודל לא יפעיל את הכלי. דייקו את התיאור (הוסיפו מילים נרדפות
    וניסוחים נפוצים) או ציינו זאת במפורש בהנחיית הסוכן ("כאשר
    המתקשר שואל על מזג האוויר, השתמשו ב-`get_weather`.").
  </Accordion>

  <Accordion title="הכלי מחזיר יותר מדי נתונים">
    תגובות הגדולות מ-6 kB נחתכות בתצוגה המקדימה של התמליל. החזירו
    רק את השדות שה-LLM זקוק להם — לא את כל הרשומה שלכם.
  </Accordion>

  <Accordion title="פסקי זמן">
    לנקודות קצה של כלים יש פסק זמן ברירת מחדל של 10 שניות. אם אתם זקוקים ליותר זמן,
    טפלו בכך באופן אסינכרוני: החזירו `{"status": "pending", "request_id": "..."}`
    והציגו את התוצאה באמצעות קריאה נפרדת לכלי.
  </Accordion>

  <Accordion title="ניהול גרסאות">
    כל `PATCH` של אינטגרציה יוצר מהדורה חדשה. בדקו את
    [`GET /v1/integrations/{id}/versions`](/api-reference/integrations#version-history)
    כדי לראות מי שינה מה. אם שברתם את הסכימה של כלי, תוכלו
    לחזור לאחור ידנית באמצעות PATCH של תמונת מצב ישנה.
  </Accordion>
</AccordionGroup>

---

## השלבים הבאים

<CardGroup cols={2}>
  <Card title="הפניית אינטגרציות" icon="plug" href="/api-reference/integrations">
    CRUD, העברה, היסטוריית גרסאות.
  </Card>
  <Card title="מפרט Function Tools" icon="screwdriver-wrench" href="/he/tools/overview">
    דקדוק מלא של סכמת JSON וחוזה נקודת הקצה החתומה.
  </Card>
  <Card title="אימות חתימות" icon="shield-check" href="/he/guides/verify-webhook-signatures">
    החילו את תבנית חתימת ה-webhook על נקודות קצה של כלים.
  </Card>
  <Card title="API של תמליל והיסטוריה" icon="phone" href="/api-reference/calls">
    בדקו את כל מחזור ההלוך ושוב של קריאת כלי.
  </Card>
</CardGroup>
