Funkcijska orodja
Funkcijska orodja vašim glasovnim agentom omogočajo klicanje zunanjih API-jev med telefonskimi klici. Z njimi lahko poiščete podatke o strankah, preverite razpoložljivost, rezervirate termine ali izvedete katero koli dejanje, ki ga podpira vaša zaledna infrastruktura.
Kako deluje
- Orodja določite s shemo (katere argumente orodje sprejema)
- Zagotovite konfiguracijo
endpoint(kam ThunderPhone kliče vaš API) — ali jo izpustite, da klice orodij prejemate na spletni kljuki svoje organizacije - Med klicem se UI na podlagi pogovora odloči, kdaj uporabiti orodje
- ThunderPhone pokliče vaš končni naslov z argumenti orodja
- Odgovor vašega API-ja se posreduje nazaj UI za nadaljevanje pogovora
Shema orodja
Vsako orodje sledi tej strukturi:
{
"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 | Obvezno | Opis |
|---|---|---|---|
name | niz | Da | Enolični identifikator orodja |
description | niz | Da | UI pojasni, kdaj naj uporabi to orodje |
parameters | objekt | Da | Shema JSON za argumente orodja |
Konfiguracija končnega naslova
| Polje | Vrsta | Obvezno | Opis |
|---|---|---|---|
url | niz | Da | URL končnega naslova vašega API-ja |
method | niz | Ne | Metoda HTTP (privzeto: POST) |
headers | objekt | Ne | Glave po meri, ki jih želite vključiti |
Dve poti klicanja
Zahteva, ki jo prejme vaš strežnik, je odvisna od tega, ali ima orodje
endpoint:
Orodje z endpoint | Orodje brez endpoint | |
|---|---|---|
| Kam gre zahteva | Neposredno na endpoint.url | Podedovani URL spletne kljuke vaše organizacije |
| Telo | Samo argumenti orodja | Ovojnica telephony.tool / web.tool |
| Glave | Vaše endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature | Content-Type + X-ThunderPhone-Signature |
| Ključ za podpisovanje | Skrivnost spletne kljuke organizacije | Skrivnost spletne kljuke organizacije |
Obe poti sta blokirni — UI sredi stavka čaka na
rezultat — s časovno omejitvijo 20 s. Obdelovalnike ohranite hitre. Kombinacija je možna:
pri klicu, katerega organizacija ima URL spletne kljuke, se orodja z endpoint
pokličejo neposredno, preostala pa se vrnejo na spletno kljuko.
Neposredni klici končne točke
Ko AI prikliče orodje, ki ima endpoint, ThunderPhone pošlje
zahtevek na vaš URL:
Glave zahtevka
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
Glave po meri iz vašega endpoint.headers so vedno vključene
dobesedno, skupaj z dvema glavama v imenskem prostoru ThunderPhone:
X-ThunderPhone-Signature— HMAC-SHA256 natančnih bajtov telesa zahtevka, s ključem vaše skrivnosti webhooka organizacijeX-ThunderPhone-Call-ID— ID trenutnega klica
Content-Type: application/json je nastavljen, razen če ga vaš endpoint.headers
preglasi — Content-Type po meri ima prednost.
Telo zahtevka
Za POST / PUT / PATCH telo vsebuje samo argumente orodja
(brez ovoja), kanonično serializirane (urejeni ključi, strnjena
ločila):
{"date":"2025-01-02","service":"consultation"}
Za GET / DELETE so argumenti poslani kot parametri poizvedbe,
telo pa je prazno — podpis se nato izračuna nad praznim bajtnim
nizom. Glejte
Preverjanje podpisov webhookov.
Odgovor
Vrnite odgovor JSON z rezultatom orodja:
{
"available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
"timezone": "America/Los_Angeles"
}
Odgovor je oblikovan in posredovan AI-ju za nadaljevanje
pogovora. Odgovori, ki niso JSON, so oviti kot {"data": "<text>"};
časovne prekoračitve in napake povezave so AI-ju sporočene kot napake,
zato se lahko agent opraviči in nadaljuje, namesto da bi obstal.
Usmerjanje v načinu webhook
Orodja brez endpoint so poslana na podedovani URL webhooka vaše
organizacije kot podpisan zahtevek telephony.tool (telefonski klici) ali web.tool
(spletni klici). Za razliko od obvestil za revizijo,
dostavljenih na končne točke webhookov po izvedbi, je ta zahtevek sam
izvedba — vaš odgovor HTTP je rezultat orodja.
{
"type": "telephony.tool",
"data": {
"call_id": 987654321,
"tool_name": "search_appointments",
"arguments": { "date": "2026-04-21" },
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}
web.tool vsebuje origin_domain namesto from_number /
to_number. Odgovorite z rezultatom orodja kot JSON — ista pogodba
odgovora kot pri neposrednih klicih končne točke. Zahtevek je podpisan
s skrivnostjo webhooka organizacije nad neobdelanim telesom, kot vsak
drug webhook.
Preverjanje podpisa
Neposredni klici orodij so podpisani enako kot spletni kavlji:
- HMAC-SHA256 nad natančnimi bajti telesa zahteve (kanonični JSON — razvrščeni ključi, brez dodatnih presledkov)
- S ključem, ki je skrivnost spletnega kavlja vaše organizacije
- Orodja
GET/DELETEpodpišejo prazen bajtni niz
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 });
});
Celotni recepti — vključno s primerom praznega telesa in opozorilom glede manjkajoče skrivnosti — so v razdelku Preverjanje podpisov spletnih kavljev.
Primer: celoten potek rezervacije
Tukaj je nabor orodij za celovit sistem rezervacije terminov:
{
"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" }
}
}
]
}
Najboljše prakse
Napišite jasne opise
Polje description pomaga UI razumeti, kdaj naj uporabi orodje. Natančno opišite, kaj orodje počne in kdaj ga je primerno uporabiti.
Ustrezno obravnavajte napake
Vrnite sporočila o napakah, ki jih UI razume: {"error": "No slots available for that date"} namesto splošnih napak 500.
Odgovori naj bodo jedrnati
Vrnite le tisto, kar UI potrebuje za nadaljevanje pogovora. Veliki koristni tovori upočasnijo odzivni čas.
Polja, ki so obvezna, uporabljajte premišljeno
Polja označite kot required le, kadar je to res potrebno. UI bo uporabnika pred klicem orodja vprašal za zahtevane informacije.
Povezano
Orodja, ki jih upravlja platforma, za HubSpot, Salesforce, Slack, Google Calendar, Google Sheets in Cal.com — končna točka ni potrebna.
Priključite strežnik MCP in agentu omogočite klic njegovih orodij.
Večkrat uporabne integracije REST, ki jih lahko priključite agentom.
En pomočnik za preverjanje webhookov in klicev orodij.