Funkční nástroje
Poskytněte svým AI agentům funkční nástroje, které během hovoru volají externí API — načítají data zákazníků, rezervují schůzky, aktualizují záznamy — s typovanými parametry.
Funkční nástroje umožňují vašim AI agentům během telefonních hovorů volat externí API. Použijte je k vyhledávání údajů o zákaznících, kontrole dostupnosti, rezervaci schůzek nebo provedení jakékoli akce, kterou váš backend podporuje.
Jak to funguje
- Definujete nástroje pomocí schématu (jaké argumenty nástroj přijímá)
- Poskytnete konfiguraci
endpoint(kam ThunderPhone volá vaše API) — nebo ji vynecháte, abyste přijímali volání nástrojů na webhooku své organizace - Během hovoru AI podle konverzace rozhodne, kdy nástroj použít
- ThunderPhone zavolá váš endpoint s argumenty nástroje
- Odpověď vašeho API se předá zpět AI, aby mohla pokračovat v konverzaci
Schéma nástroje
Každý nástroj má tuto 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"
}
},
"timeout": 120
}Konfigurace nástroje
| Pole | Typ | Povinné | Popis |
|---|---|---|---|
timeout | číslo | Ne | Maximální doba provádění v sekundách (výchozí: 20, maximum: 180) |
Definice funkce
| Pole | Typ | Povinné | Popis |
|---|---|---|---|
name | řetězec | Ano | Jedinečný identifikátor nástroje |
description | řetězec | Ano | Vysvětluje AI, kdy má tento nástroj použít |
parameters | objekt | Ano | Schéma JSON pro argumenty nástroje |
Konfigurace endpointu
| Pole | Typ | Povinné | Popis |
|---|---|---|---|
url | řetězec | Ano | URL vašeho endpointu API |
method | řetězec | Ne | Metoda HTTP (výchozí: POST) |
headers | objekt | Ne | Vlastní hlavičky, které se mají zahrnout |
Dvě cesty vyvolání
To, jaký požadavek váš server obdrží, závisí na tom, zda nástroj obsahuje
endpoint:
Nástroj s endpoint | Nástroj bez endpoint | |
|---|---|---|
| Kam požadavek směřuje | Přímo na endpoint.url | Na starší URL webhooku vaší organizace |
| Tělo | Pouhé argumenty nástroje | Obálka telephony.tool / web.tool |
| Hlavičky | Vaše endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature | Content-Type + X-ThunderPhone-Signature |
| Podpisový klíč | Tajný klíč webhooku organizace | Tajný klíč webhooku organizace |
Obě cesty jsou blokující — AI uprostřed věty čeká na
výsledek. Výchozí časový limit je 20 s; nastavte timeout
na nejvyšší úrovni nástroje, pokud chcete povolit delší provádění, až do maxima platformy
180 s. Udržujte obslužné funkce rychlé. Kombinace je možná:
při hovoru, jehož organizace má URL webhooku, jsou nástroje s endpoint
volány přímo a ostatní se vrátí k webhooku.
Přímá volání endpointů
Když AI vyvolá nástroj, který má endpoint, ThunderPhone odešle
požadavek na vaši adresu URL:
Hlavičky požadavku
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-keyVlastní hlavičky z vašeho endpoint.headers jsou vždy zahrnuty
doslovně spolu se dvěma hlavičkami ve jmenném prostoru ThunderPhone:
X-ThunderPhone-Signature— HMAC-SHA256 přes přesné bajty těla požadavku, s klíčem ve vašem tajemství webhooku organizaceX-ThunderPhone-Call-ID— ID aktuálního hovoru
Content-Type: application/json je nastaveno, pokud je nepřepíšou vaše
endpoint.headers — vlastní Content-Type má přednost.
Tělo požadavku
Pro POST / PUT / PATCH tělo obsahuje pouze argumenty nástroje
(bez obálky), serializované kanonicky (seřazené klíče, kompaktní
oddělovače):
{"date":"2025-01-02","service":"consultation"}Pro GET / DELETE jsou argumenty odesílány jako parametry dotazu
a tělo je prázdné — podpis se pak vypočítá přes prázdný bajtový
řetězec. Viz
Ověření podpisů webhooků.
Odpověď
Vraťte odpověď JSON s výsledkem nástroje:
{
"available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
"timezone": "America/Los_Angeles"
}Odpověď je naformátována a poskytnuta AI, aby mohla pokračovat
v konverzaci. Odpovědi jiné než JSON jsou zabaleny jako {"data": "<text>"};
časové limity a selhání připojení jsou AI hlášeny jako chyby, takže se
agent může omluvit a pokračovat, místo aby se zasekl.
Odesílání v režimu webhooku
Nástroje bez endpoint jsou odesílány na starší adresu URL webhooku
vaší organizace jako podepsaný požadavek telephony.tool (telefonní hovory)
nebo web.tool (webové hovory). Na rozdíl od oznámení auditu,
která jsou doručena na endpointy webhooků po provedení, tento požadavek je
provedením — vaše odpověď HTTP je výsledkem nástroje.
{
"type": "telephony.tool",
"data": {
"call_id": 987654321,
"tool_name": "search_appointments",
"arguments": { "date": "2026-04-21" },
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}web.tool obsahuje origin_domain namísto from_number /
to_number. Odpovězte výsledkem nástroje jako JSON — platí stejný
kontrakt odpovědi jako pro přímá volání endpointů. Požadavek je podepsán
tajemstvím webhooku organizace přes nezpracované tělo, stejně jako každý
jiný webhook.
Ověření podpisu
Přímá volání nástrojů jsou podepisována stejným způsobem jako webhooky:
- HMAC-SHA256 přes přesné bajty těla požadavku (kanonický JSON — seřazené klíče, bez nadbytečných mezer)
- S použitím vašeho tajného klíče webhooku organizace
- Nástroje
GET/DELETEpodepisují prázdný bajtový řetězec
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 });
});Úplné postupy — včetně případu s prázdným tělem a upozornění pro případ bez tajného klíče — najdete v části Ověření podpisů webhooků.
Příklad: Kompletní tok rezervace
Zde je sada nástrojů pro kompletní systém rezervace schůzek:
{
"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" }
}
}
]
}Osvědčené postupy
Pište jasné popisy
Pole description pomáhá AI pochopit, kdy má nástroj použít. Jasně uveďte, co nástroj dělá a kdy je vhodné ho použít.
Chyby zpracovávejte vhodně
Vracíme chybové zprávy, kterým AI rozumí: {"error": "No slots available for that date"} namísto obecných chyb 500.
Odpovědi udržujte stručné
Vracejte pouze informace, které AI potřebuje k pokračování v konverzaci. Velké datové odpovědi zpomalují dobu odezvy.
Povinná pole používejte uvážlivě
Pole označujte jako required pouze tehdy, když je to skutečně nutné. AI si před voláním nástroje vyžádá od uživatele povinné informace.
Související
Nástroje spravované platformou pro HubSpot, Salesforce, Slack, Google Calendar, Google Sheets a Cal.com — není vyžadován žádný endpoint.
Připojte server MCP a nechte agenta volat jeho nástroje.
Opakovaně použitelné integrace REST, které můžete připojit k agentům.
Jeden pomocný nástroj pro ověřování webhooků a volání nástrojů.