Narzędzia funkcji
Wyposaż swoich agentów AI w narzędzia funkcji, które wywołują zewnętrzne interfejsy API w trakcie rozmowy — pobierają dane klientów, umawiają wizyty, aktualizują rekordy — z parametrami typowanymi.
Narzędzia funkcji umożliwiają Twoim agentom AI wywoływanie zewnętrznych interfejsów API podczas rozmów telefonicznych. Używaj ich do wyszukiwania danych klientów, sprawdzania dostępności, umawiania wizyt lub wykonywania dowolnych działań obsługiwanych przez Twój backend.
Jak to działa
- Definiujesz narzędzia za pomocą schematu (jakie argumenty narzędzie akceptuje)
- Podajesz konfigurację
endpoint(gdzie ThunderPhone wywołuje Twoje API) — lub pomijasz ją, aby odbierać wywołania narzędzi na webhooku organizacji - Podczas rozmowy AI decyduje, kiedy użyć narzędzia, na podstawie rozmowy
- ThunderPhone wywołuje Twój endpoint z argumentami narzędzia
- Odpowiedź Twojego API jest przekazywana z powrotem do AI, aby kontynuować rozmowę
Schemat narzędzia
Każde narzędzie ma następującą strukturę:
{
"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
}Konfiguracja narzędzia
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
timeout | liczba | Nie | Maksymalny czas wykonania w sekundach (domyślnie: 20, maksymalnie: 180) |
Definicja funkcji
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
name | ciąg znaków | Tak | Unikalny identyfikator narzędzia |
description | ciąg znaków | Tak | Wyjaśnia AI, kiedy użyć tego narzędzia |
parameters | obiekt | Tak | Schemat JSON dla argumentów narzędzia |
Konfiguracja endpointu
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
url | ciąg znaków | Tak | Adres URL endpointu Twojego API |
method | ciąg znaków | Nie | Metoda HTTP (domyślnie: POST) |
headers | obiekt | Nie | Niestandardowe nagłówki do uwzględnienia |
Dwie ścieżki wywołania
To, jakie żądanie otrzyma Twój serwer, zależy od tego, czy narzędzie ma
endpoint:
Narzędzie z endpoint | Narzędzie bez endpoint | |
|---|---|---|
| Dokąd trafia żądanie | Bezpośrednio do endpoint.url | Na starszy adres URL webhooka Twojej organizacji |
| Treść | Same argumenty narzędzia | Obwiednia telephony.tool / web.tool |
| Nagłówki | Twoje endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature | Content-Type + X-ThunderPhone-Signature |
| Klucz podpisu | Sekret webhooka organizacji | Sekret webhooka organizacji |
Obie ścieżki są blokujące — AI czeka w środku zdania na
wynik. Domyślny limit czasu wynosi 20 s; ustaw timeout na najwyższym poziomie
narzędzia, aby zezwolić na dłuższe wykonanie, maksymalnie do limitu platformy
wynoszącego 180 s. Zadbaj o szybkie działanie handlerów. Możesz używać obu:
w rozmowie, której organizacja ma adres URL webhooka, narzędzia z endpoint są
wywoływane bezpośrednio, a pozostałe korzystają z webhooka.
Bezpośrednie wywołania endpointów
Gdy AI wywołuje narzędzie z endpoint, ThunderPhone wysyła
żądanie na Twój adres URL:
Nagłówki żądania
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-keyNiestandardowe nagłówki z endpoint.headers są zawsze dołączane
dosłownie, wraz z dwoma nagłówkami z przestrzeni nazw ThunderPhone:
X-ThunderPhone-Signature— HMAC-SHA256 dokładnych bajtów treści żądania, z kluczem będącym Twoim sekretem webhooka organizacjiX-ThunderPhone-Call-ID— ID bieżącego połączenia
Content-Type: application/json jest ustawiany, chyba że
endpoint.headers go zastąpi — niestandardowy Content-Type ma pierwszeństwo.
Treść żądania
Dla POST / PUT / PATCH treść zawiera wyłącznie argumenty
narzędzia (bez otoczki), serializowane kanonicznie (posortowane klucze,
zwięzłe separatory):
{"date":"2025-01-02","service":"consultation"}Dla GET / DELETE argumenty są wysyłane jako parametry zapytania,
a treść jest pusta — podpis jest wtedy obliczany na pustym ciągu bajtów.
Zobacz
Weryfikowanie podpisów webhooków.
Odpowiedź
Zwróć odpowiedź JSON z wynikiem narzędzia:
{
"available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
"timezone": "America/Los_Angeles"
}Odpowiedź jest formatowana i przekazywana AI, aby kontynuować
rozmowę. Odpowiedzi inne niż JSON są opakowywane jako {"data": "<text>"};
przekroczenia czasu i błędy połączenia są zgłaszane AI jako błędy, dzięki czemu
agent może przeprosić i przejść dalej zamiast się zatrzymać.
Dystrybucja w trybie webhooka
Narzędzia bez endpoint są kierowane na starszy adres URL webhooka
Twojej organizacji jako podpisane żądanie telephony.tool (połączenia telefoniczne)
lub web.tool (połączenia internetowe). W przeciwieństwie do
powiadomień audytowych dostarczanych do endpointów webhooków
po wykonaniu, to żądanie jest wykonaniem — Twoja odpowiedź HTTP stanowi
wynik narzędzia.
{
"type": "telephony.tool",
"data": {
"call_id": 987654321,
"tool_name": "search_appointments",
"arguments": { "date": "2026-04-21" },
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}web.tool zawiera origin_domain zamiast from_number /
to_number. Odpowiedz wynikiem narzędzia jako JSON — obowiązuje ten sam
kontrakt odpowiedzi co dla bezpośrednich wywołań endpointów. Żądanie jest
podpisywane sekretem webhooka organizacji na podstawie nieprzetworzonej treści,
tak jak każdy inny webhook.
Weryfikacja podpisu
Bezpośrednie wywołania narzędzi są podpisywane tak samo jak webhooki:
- HMAC-SHA256 na dokładnych bajtach treści żądania (kanoniczny JSON — posortowane klucze, bez dodatkowych białych znaków)
- Z użyciem sekretu webhooka organizacji
- Narzędzia
GET/DELETEpodpisują pusty ciąg bajtów
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}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 });
});Pełne przykłady — w tym przypadek pustej treści oraz zastrzeżenie dotyczące braku sekretu — znajdziesz w sekcji Weryfikowanie podpisów webhooków.
Przykład: kompletny proces rezerwacji
Oto zestaw narzędzi dla kompletnego systemu rezerwacji wizyt:
{
"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" }
}
}
]
}Najlepsze praktyki
Pisz jasne opisy
Pole description pomaga AI zrozumieć, kiedy użyć narzędzia. Precyzyjnie określ, co robi i kiedy należy go użyć.
Odpowiednio obsługuj błędy
Zwracaj komunikaty o błędach, które AI może zrozumieć: {"error": "No slots available for that date"} zamiast ogólnych błędów 500.
Zachowuj zwięzłość odpowiedzi
Zwracaj tylko to, czego AI potrzebuje, aby kontynuować rozmowę. Duże ładunki danych spowalniają czas odpowiedzi.
Rozważnie używaj pól wymaganych
Oznaczaj pola jako required tylko wtedy, gdy jest to naprawdę konieczne. AI poprosi użytkownika o wymagane informacje przed wywołaniem narzędzia.
Powiązane
Narzędzia zarządzane przez platformę dla HubSpot, Salesforce, Slack, Kalendarza Google, Arkuszy Google i Cal.com — nie wymagają punktu końcowego.
Podłącz serwer MCP i pozwól agentowi wywoływać jego narzędzia.
Wielokrotnego użytku integracje REST, które możesz podłączać do agentów.
Jedno narzędzie pomocnicze do weryfikacji webhooków i wywołań narzędzi.