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

Developer cookbook

בניית שילוב כלי (API)

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

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

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

המבנה של כלי

שני חלקים:

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

1. בחרו עורך

לוח הבקרה

פתחו את חיבורים → ממשקי API, צרו או ערכו את חיבור ה-API, העבירו את עורך הפרמטרים ל-JSON, והוסיפו שם את הפורמט.

API לאינטגרציות

צרו את המפרט באמצעות POST /v1/integrations, או עדכנו אותו באמצעות PATCH /v1/integrations/{id}.

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

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

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 כדי לשמור את הערך המאוחסן.

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

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

"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 כדי לאשר קישוריות:

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" }
  }'
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 בעת יצירה או עדכון של סוכן:

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:

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

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

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

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

{
  "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; זרם האירועים הגולמי (עם תזמון לכל רשומה והיסטי שמע) נמצא ב- GET /v1/calls/{call_id}/history.

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

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

הסוכן לעולם לא מפעיל את הכלי

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

הכלי מחזיר יותר מדי נתונים

תגובות הגדולות מ-6 kB נחתכות בתצוגה המקדימה של התמליל. החזירו רק את השדות שה-LLM זקוק להם — לא את כל הרשומה שלכם.

פסקי זמן

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

ניהול גרסאות

כל PATCH של אינטגרציה יוצר מהדורה חדשה. בדקו את GET /v1/integrations/{id}/versions כדי לראות מי שינה מה. אם שברתם את הסכימה של כלי, תוכלו לחזור לאחור ידנית באמצעות PATCH של תמונת מצב ישנה.


השלבים הבאים