ThunderPhone 2.0 уже доступний.Самостійне підключення — від 2 центів за хвилину.Прочитати анонс

Function Tools

Інструменти функцій

Надайте своїм AI-агентам інструменти функцій для виклику зовнішніх API під час розмови — отримання даних клієнтів, бронювання зустрічей, оновлення записів — із типізованими параметрами.

Функціональні інструменти дають змогу вашим AI-агентам викликати зовнішні API під час телефонних дзвінків. Використовуйте їх, щоб шукати дані клієнтів, перевіряти доступність, бронювати зустрічі або виконувати будь-які дії, які підтримує ваш бекенд.

Як це працює

  1. Визначте інструменти за допомогою схеми (які аргументи приймає інструмент)
  2. Надайте конфігурацію endpoint (куди ThunderPhone викликає ваш API) або не вказуйте її, щоб отримувати виклики інструментів на вебхук вашої організації
  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 Schema для аргументів інструмента

Конфігурація endpoint

ПолеТипОбов’язковеОпис
urlрядокТакURL endpoint вашого API
methodрядокНіHTTP-метод (за замовчуванням: POST)
headersоб’єктНіКористувацькі заголовки, які потрібно додати

Два шляхи виклику

Який запит отримає ваш сервер, залежить від того, чи має інструмент endpoint:

Інструмент з endpointІнструмент без endpoint
Куди надсилається запитБезпосередньо до endpoint.urlНа застарілий URL вебхука вашої організації
ТілоЛише аргументи інструментаОбгортка telephony.tool / web.tool
ЗаголовкиВаші endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature
Ключ підписуСекрет вебхука організаціїСекрет вебхука організації

Обидва шляхи є блокувальними — AI очікує на результат посеред речення. Час очікування за замовчуванням — 20 с; задайте timeout на верхньому рівні інструмента, щоб дозволити довше виконання, до максимуму платформи 180 с. Забезпечте швидку роботу обробників. Можна використовувати обидва варіанти: під час дзвінка, коли організація має URL вебхука, інструменти з endpoint викликаються безпосередньо, а решта використовують вебхук.

Прямі виклики кінцевих точок

Коли ШІ викликає інструмент, що має 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 — 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 — діє той самий контракт відповіді, що й для прямих викликів кінцевих точок. Запит підписується секретом вебхука організації на основі необробленого тіла, як і будь-який інший вебхук.


Перевірка підпису

Прямі виклики інструментів підписуються так само, як вебхуки:

  • HMAC-SHA256 для точних байтів тіла запиту (канонічний JSON — відсортовані ключі, без зайвих пробілів)
  • З використанням секрету вебхука вашої організації
  • Інструменти 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 });
});

Повні рецепти — зокрема для випадку з порожнім тілом і застереження щодо відсутності секрету — наведено в розділі Перевірка підписів вебхуків.


Приклад: повний процес бронювання

Ось набір інструментів для повної системи запису на прийом:

{
  "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 лише за справжньої потреби. Перед викликом інструмента ШІ запитає користувача про обов’язкову інформацію.


Пов’язані матеріали