Alati funkcija
Funkcijski alati omogućuju vašim AI glasovnim agentima pozivanje vanjskih API-ja tijekom telefonskih poziva. Upotrijebite ih za dohvaćanje podataka o korisnicima, provjeru dostupnosti, rezerviranje termina ili izvršavanje bilo koje radnje koju podržava vaš pozadinski sustav.
Kako funkcionira
- Definirate alate sa shemom (koje argumente alat prihvaća)
- Navedete konfiguraciju
endpoint(gdje ThunderPhone poziva vaš API) — ili je izostavite kako biste primali pozive alata na webhook svoje organizacije - Tijekom poziva AI odlučuje kada upotrijebiti alat na temelju razgovora
- ThunderPhone poziva vašu krajnju točku s argumentima alata
- Odgovor vašeg API-ja vraća se AI-ju za nastavak razgovora
Shema alata
Svaki alat slijedi ovu strukturu:
{
"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"
}
}
}
Definicija funkcije
| Polje | Vrsta | Obavezno | Opis |
|---|---|---|---|
name | string | Da | Jedinstveni identifikator alata |
description | string | Da | Objašnjava AI-ju kada upotrijebiti ovaj alat |
parameters | object | Da | JSON shema za argumente alata |
Konfiguracija krajnje točke
| Polje | Vrsta | Obavezno | Opis |
|---|---|---|---|
url | string | Da | URL krajnje točke vašeg API-ja |
method | string | Ne | HTTP metoda (zadano: POST) |
headers | object | Ne | Prilagođena zaglavlja koja treba uključiti |
Dva načina pozivanja
Zahtjev koji vaš poslužitelj prima ovisi o tome ima li alat
endpoint:
Alat s endpoint | Alat bez endpoint | |
|---|---|---|
| Kamo ide zahtjev | Izravno na endpoint.url | Na URL naslijeđenog webhooka vaše organizacije |
| Tijelo | Samo argumenti alata | Omotnica telephony.tool / web.tool |
| Zaglavlja | Vaša endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature | Content-Type + X-ThunderPhone-Signature |
| Ključ za potpisivanje | Tajna webhooka organizacije | Tajna webhooka organizacije |
Oba načina su blokirajuća — AI usred rečenice čeka
rezultat — uz vremensko ograničenje od 20 s. Obraditelji moraju biti brzi. Možete ih kombinirati:
tijekom poziva čija organizacija ima URL webhooka alati s endpoint
pozivaju se izravno, a ostali se vraćaju na webhook.
Izravni pozivi krajnje točke
Kada AI pozove alat koji ima endpoint, ThunderPhone šalje
zahtjev na vaš URL:
Zaglavlja zahtjeva
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
Prilagođena zaglavlja iz vašeg endpoint.headers uvijek se uključuju
doslovno, uz dva zaglavlja u imenskom prostoru ThunderPhonea:
X-ThunderPhone-Signature— HMAC-SHA256 točnih bajtova tijela zahtjeva, s ključem vašeg tajnog ključa webhooka organizacijeX-ThunderPhone-Call-ID— ID trenutačnog poziva
Content-Type: application/json postavlja se osim ako ga vaš
endpoint.headers ne nadjača — prilagođeni Content-Type ima prednost.
Tijelo zahtjeva
Za POST / PUT / PATCH, tijelo sadrži samo argumente alata
(bez omotača), serijalizirane kanonski (sortirani ključevi, kompaktni
razdjelnici):
{"date":"2025-01-02","service":"consultation"}
Za GET / DELETE, argumenti se šalju kao parametri upita,
a tijelo je prazno — potpis se tada izračunava nad praznim nizom
bajtova. Pogledajte
Provjerite potpise webhooka.
Odgovor
Vratite JSON odgovor s rezultatom alata:
{
"available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
"timezone": "America/Los_Angeles"
}
Odgovor se formatira i pruža AI-ju za nastavak
razgovora. Odgovori koji nisu JSON omataju se kao {"data": "<text>"};
vremenska ograničenja i pogreške povezivanja prijavljuju se AI-ju kao
pogreške kako bi se agent mogao ispričati i nastaviti umjesto da zastane.
Distribucija u načinu rada webhooka
Alati bez endpoint šalju se na URL naslijeđenog webhooka vaše
organizacije kao potpisani zahtjev telephony.tool (telefonski pozivi) ili web.tool
(web-pozivi). Za razliku od obavijesti o reviziji
dostavljenih krajnjim točkama webhooka nakon izvršavanja, ovaj zahtjev jest
izvršavanje — vaš HTTP odgovor rezultat je alata.
{
"type": "telephony.tool",
"data": {
"call_id": 987654321,
"tool_name": "search_appointments",
"arguments": { "date": "2026-04-21" },
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}
web.tool sadrži origin_domain umjesto from_number /
to_number. Odgovorite rezultatom alata kao JSON-om — isti ugovor
odgovora kao za izravne pozive krajnje točke. Zahtjev je potpisan
tajnim ključem webhooka organizacije nad neobrađenim tijelom, kao i svaki drugi webhook.
Provjera potpisa
Izravni pozivi alata potpisuju se na isti način kao webhookovi:
- HMAC-SHA256 nad točnim bajtovima tijela zahtjeva (kanonski JSON — sortirani ključevi, bez dodatnih razmaka)
- Uz ključ koji je tajna webhooka vaše organizacije
- Alati
GET/DELETEpotpisuju prazan niz bajtova
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 });
});
Potpuni primjeri — uključujući slučaj praznog tijela i napomenu o nedostatku tajne — nalaze se u odjeljku Provjera potpisa webhooka.
Primjer: cjeloviti tijek rezervacije
Evo skupa alata za cjelovit sustav rezervacije termina:
{
"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" }
}
}
]
}
Najbolje prakse
Napišite jasne opise
Polje description pomaže AI-ju razumjeti kada upotrijebiti alat. Jasno navedite što alat radi i kada ga je prikladno koristiti.
Elegantno obradite pogreške
Vratite poruke o pogreškama koje AI može razumjeti: {"error": "No slots available for that date"} umjesto generičkih pogrešaka 500.
Neka odgovori budu sažeti
Vratite samo ono što AI treba za nastavak razgovora. Veliki korisni tereti usporavaju vrijeme odgovora.
Promišljeno koristite obavezna polja
Označite polja kao required samo kada je to doista potrebno. AI će od korisnika zatražiti obavezne informacije prije pozivanja alata.
Povezano
Alati kojima upravlja platforma za HubSpot, Salesforce, Slack, Google Calendar, Google Sheets i Cal.com — nije potrebna krajnja točka.
Priložite MCP poslužitelj i omogućite agentu pozivanje njegovih alata.
REST integracije za višekratnu upotrebu koje možete priložiti agentima.
Jedan pomoćnik za provjeru webhookova i poziva alata.