Open in
Інструменти функцій
Надайте своїм ШІ-агентам інструменти функцій, які викликають зовнішні API під час розмови — отримують дані клієнтів, бронюють зустрічі, оновлюють записи — із типізованими параметрами.
Інструменти функцій дають вашим AI-агентам змогу викликати зовнішні API під час телефонних дзвінків. Використовуйте їх для пошуку даних клієнтів, перевірки доступності, бронювання зустрічей або виконання будь-яких дій, які підтримує ваш бекенд.
Як це працює
- Визначте інструменти за допомогою схеми (які аргументи приймає інструмент)
- Надайте конфігурацію
endpoint(куди ThunderPhone викликає ваш API) — або не вказуйте її, щоб отримувати виклики інструментів на вебхуку вашої організації - Під час дзвінка AI вирішує, коли використовувати інструмент, на основі розмови
- ThunderPhone викликає вашу кінцеву точку з аргументами інструменту
- Відповідь вашого API передається AI для продовження розмови
| Можливість | Де виконується | Налаштування |
|---|---|---|
| Вбудовані інструменти | ThunderPhone | Інструкції в промпті; для деяких інструментів також потрібне налаштування агента |
| Підключення застосунків | ThunderPhone і підключений провайдер | Підключіть обліковий запис і додайте схвалені дії |
| Підключення API та інструменти функцій | Ваш HTTP API | Визначте кінцеву точку та схему або отримуйте виклики функцій через вебхук |
| Сервери MCP | Віддалений сервер MCP | Додайте сервер, знайдіть його інструменти та підключіть його до агента |
Схема інструменту
Кожен інструмент має таку структуру:
{
"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 для аргументів інструменту |
Конфігурація кінцевої точки
| Поле | Тип | Обов’язково | Опис |
|---|---|---|---|
url | рядок | Так | URL кінцевої точки вашого API |
method | рядок | Ні | HTTP-метод (за замовчуванням: POST) |
headers | об’єкт | Ні | Власні заголовки, які потрібно включити |
Два шляхи виклику
Який запит отримає ваш сервер, залежить від того, чи має інструмент
endpoint:
Інструмент з endpoint | Інструмент без endpoint | |
|---|---|---|
| Куди надходить запит | Безпосередньо до endpoint.url | Застаріла URL-адреса вебхука вашої організації |
| Тіло | Вибраний формат запиту (за замовчуванням — лише аргументи) | Обгортка 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 |
| Ключ підпису | Секрет вебхука організації | Секрет вебхука організації |
Обидва шляхи є блокувальними — AI очікує результат посеред речення.
Стандартний тайм-аут становить 20 с; установіть timeout верхнього рівня
інструменту, щоб дозволити довше виконання, до максимальних 180 с
платформи. Забезпечуйте швидку роботу обробників. Можна використовувати змішаний підхід:
під час дзвінка, для організації якого налаштовано URL вебхука, інструменти з endpoint
викликаються безпосередньо, а решта повертаються до вебхука.
Прямі виклики endpoint
Коли ШІ викликає інструмент, що має endpoint, ThunderPhone надсилає
запит на вашу URL-адресу:
Заголовки запиту
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 із позначкою часу для методу, шляху, параметрів запиту й тіла, підписаний вашим секретом вебхука організації. Перевіряйте цей заголовок і відхиляйте запити, яким понад 5 хвилин; див. Перевірка підписів вебхуківX-ThunderPhone-Signature— застарілий HMAC-SHA256 точних байтів тіла запиту з тим самим ключем, який і далі надсилається для наявних засобів перевіркиX-ThunderPhone-Call-ID— Ідентифікатор поточного дзвінка
Content-Type: application/json встановлюється, якщо його не
перевизначено у вашому endpoint.headers — користувацький Content-Type
має пріоритет.
Формат запиту
Кожне API-підключення має налаштування request_format. Виберіть vapi або
retell, якщо імпортований інструмент має й надалі викликати ендпойнт, створений для
цієї платформи. Для нових і наявних підключень за замовчуванням використовується standard.
Для POST / PUT / PATCH ThunderPhone серіалізує вибраний
конверт канонічно (відсортовані ключі, компактні роздільники). Обидва підписи
охоплюють саме ці байти.
Standard
standard надсилає лише аргументи інструмента без обгортки. Це значення за замовчуванням, яке зберігає оригінальне тіло запиту ThunderPhone байт у байт:
{"date":"2025-01-02","service":"consultation"}Vapi
vapi надсилає серверне повідомлення tool-calls Vapi
у форматі, задокументованому Vapi. call.id — це ID виклику ThunderPhone. ID
виклику інструмента id є унікальним для виклику та повторно використовується для зіставлення
результату ендпойнта. Виклик відображається і в toolCallList, і в
toolWithToolCallList, а function.arguments є 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 з відповідним ID виклику інструмента:
{
"results": [
{
"toolCallId": "call_00112233445566778899aabbccddeeff",
"result": "{\"available_slots\":[\"9:00 AM\",\"2:00 PM\"]}"
}
]
}ThunderPhone передає ШІ розгорнутий рядок result. Також підтримується
значення JSON для сумісності з ендпойнтами, які вже його повертають. error
замість result повертається ШІ як помилка інструмента. Якщо ендпойнт повертає
некоректний або невідповідний конверт Vapi, ThunderPhone записує
попередження в журнал і повертається до стандартного аналізу відповіді замість того, щоб завершити
виклик помилкою.
Retell
retell надсилає запит, задокументований для користувацької функції Retell:
{
"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
охоплює рядок запиту в надісланому вигляді; застарілий підпис обчислюється для
порожнього рядка байтів. Див.
Перевірка підписів вебхуків.
Відповідь
Поверніть 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 (вебвиклики). На відміну від
сповіщень аудиту, що доставляються до endpoint вебхуків
після виконання, цей запит є виконанням — ваша 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 — за тим самим контрактом відповіді, що й для прямих викликів кінцевих точок. Запит підписано секретом вебхука організації та містить обидва заголовки підпису, як і кожен інший вебхук.
Перевірка підпису
Прямі виклики інструментів підписуються так само, як вебхуки, з використанням секрету вебхуків вашої організації:
X-ThunderPhone-Signature-V2підписує позначку часу, метод, шлях і параметри запиту в надісланому вигляді, а також точні байти тіла. Відхиляйте запити, позначка часу яких відрізняється від вашого часу більш ніж на 5 хвилин.X-ThunderPhone-Signature(застарілий) підписує лише байти тіла; дляGET/DELETEвикористовується порожній рядок байтів. Він досі надсилається без змін.
Допоміжні функції SDK перевіряють заголовок V2, зокрема 5-хвилинне вікно:
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}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 });
});Повні приклади — підписуваний рядок, покроковий приклад, код без SDK, випадок GET / DELETE і застереження щодо відсутності секрету — наведено в розділі Перевірка підписів вебхуків.
Приклад: повний процес запису
Ось набір інструментів для повноцінної системи запису на прийом:
{
"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 лише за справжньої потреби. Перед викликом інструмента ШІ запитає в користувача обов’язкову інформацію.
Пов’язані матеріали
Налаштовуйте дії з викликами, якими керує платформа, без визначення кінцевої точки.
Інструменти під керуванням платформи для HubSpot, Salesforce, Slack, Google Calendar, Google Sheets і Cal.com — кінцева точка не потрібна.
Підключіть сервер MCP і дозвольте агенту викликати його інструменти.
Багаторазові REST-інтеграції, які можна підключати до агентів.
Єдиний допоміжний засіб перевірки для вебхуків і викликів інструментів.