Funksjonsverktøy
Gi AI-agentene dine funksjonsverktøy som kaller eksterne API-er midt i samtalen — henter kundedata, bestiller avtaler, oppdaterer poster — med typede parametere.
Funksjonsverktøy lar AI-stemmeagentene dine kalle eksterne API-er under telefonsamtaler. Bruk dem til å slå opp kundedata, sjekke tilgjengelighet, bestille avtaler eller utføre handlinger som backend-systemet ditt støtter.
Slik fungerer det
- Du definerer verktøy med et skjema (hvilke argumenter verktøyet godtar)
- Du oppgir en
endpoint-konfigurasjon (der ThunderPhone kaller API-et ditt) — eller lar den stå tom for å motta verktøykall på organisasjonens webhook - Under en samtale avgjør AI-en når den skal bruke et verktøy basert på samtalen
- ThunderPhone kaller endepunktet ditt med verktøyargumentene
- API-svaret ditt sendes tilbake til AI-en for å fortsette samtalen
Verktøyskjema
Hvert verktøy følger denne strukturen:
{
"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
}Verktøykonfigurasjon
| Felt | Type | Påkrevd | Beskrivelse |
|---|---|---|---|
timeout | tall | Nei | Maksimal kjøretid i sekunder (standard: 20, maksimum: 180) |
Funksjonsdefinisjon
| Felt | Type | Påkrevd | Beskrivelse |
|---|---|---|---|
name | streng | Ja | Unik identifikator for verktøyet |
description | streng | Ja | Forklarer AI-en når dette verktøyet skal brukes |
parameters | objekt | Ja | JSON-skjema for verktøyargumenter |
Endepunktkonfigurasjon
| Felt | Type | Påkrevd | Beskrivelse |
|---|---|---|---|
url | streng | Ja | URL-en til API-endepunktet ditt |
method | streng | Nei | HTTP-metode (standard: POST) |
headers | objekt | Nei | Egendefinerte headere som skal inkluderes |
To kallingsveier
Hvilken forespørsel serveren din mottar, avhenger av om verktøyet har et
endpoint:
Verktøy med endpoint | Verktøy uten endpoint | |
|---|---|---|
| Hvor forespørselen sendes | Direkte til endpoint.url | Organisasjonens eldre webhook-URL |
| Brødtekst | Kun verktøyargumenter | telephony.tool / web.tool-innpakning |
| Headere | Dine endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature | Content-Type + X-ThunderPhone-Signature |
| Signeringsnøkkel | Organisasjonens webhook-hemmelighet | Organisasjonens webhook-hemmelighet |
Begge veiene er blokkerende — AI-en venter midt i en setning på
resultatet. Standard tidsavbrudd er 20 s; angi verktøyets øverste
timeout for å tillate lengre kjøretid, opptil plattformens maksimum på
180 s. Hold handlere raske. En kombinasjon fungerer fint:
I en samtale der organisasjonen har en webhook-URL, blir verktøy med et
endpoint kalt direkte, mens resten faller tilbake til webhooken.
Direkte endepunktkall
Når KI-en påkaller et verktøy som har et endpoint, sender ThunderPhone
en forespørsel til URL-en din:
Forespørselsoverskrifter
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-keyEgendefinerte overskrifter fra endpoint.headers inkluderes alltid
ordrett, i tillegg til to ThunderPhone-navngitte overskrifter:
X-ThunderPhone-Signature— HMAC-SHA256 av de nøyaktige byteverdiene i forespørselsbrødteksten, med organisasjonens webhook-hemmelighet som nøkkelX-ThunderPhone-Call-ID— ID-en til den gjeldende samtalen
Content-Type: application/json angis med mindre endpoint.headers
overstyrer den — en egendefinert Content-Type har forrang.
Forespørselsbrødtekst
For POST / PUT / PATCH inneholder brødteksten bare verktøyets
argumenter (uten innpakning), serialisert kanonisk (sorterte nøkler,
kompakte skilletegn):
{"date":"2025-01-02","service":"consultation"}For GET / DELETE sendes argumentene som spørringsparametere,
og brødteksten er tom — signaturen beregnes da over den tomme
bytestrengen. Se
Verifiser webhook-signaturer.
Svar
Returner et JSON-svar med verktøyresultatet:
{
"available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
"timezone": "America/Los_Angeles"
}Svaret formateres og gis til KI-en slik at samtalen kan fortsette.
Ikke-JSON-svar pakkes inn som {"data": "<text>"}; tidsavbrudd og
tilkoblingsfeil rapporteres til KI-en som feil, slik at stemmeagenten
kan beklage og gå videre i stedet for å stoppe opp.
Utsending i webhook-modus
Verktøy uten et endpoint sendes til organisasjonens eldre
webhook-URL som en signert telephony.tool-forespørsel (telefonsamtaler)
eller web.tool-forespørsel (websamtaler). I motsetning til
revisjonsvarsler som leveres til webhook-endepunkter
etter utførelse, er denne forespørselen selve utførelsen — HTTP-svaret
ditt er verktøyresultatet.
{
"type": "telephony.tool",
"data": {
"call_id": 987654321,
"tool_name": "search_appointments",
"arguments": { "date": "2026-04-21" },
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}web.tool inneholder origin_domain i stedet for from_number /
to_number. Svar med verktøyresultatet som JSON — samme svaravtale
som for direkte endepunktkall. Forespørselen signeres med organisasjonens
webhook-hemmelighet over råbrødteksten, som alle andre webhooks.
Signaturverifisering
Direkte verktøykall signeres på samme måte som webhooks:
- HMAC-SHA256 over de nøyaktige byteverdiene i forespørselsbrødteksten (den kanoniske JSON-en — sorterte nøkler, uten ekstra mellomrom)
- Med organisasjonens webhook-hemmelighet som nøkkel
GET- ogDELETE-verktøy signerer den tomme bytestrengen
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 });
});Fullstendige oppskrifter — inkludert tilfellet med tom brødtekst og forbeholdet om manglende hemmelighet — finner du i Verifiser webhook-signaturer.
Eksempel: Komplett bestillingsflyt
Her er et sett med verktøy for et komplett system for timebestilling:
{
"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" }
}
}
]
}Beste praksis
Skriv tydelige beskrivelser
Feltet description hjelper AI-en med å forstå når verktøyet skal brukes. Vær spesifikk om hva det gjør, og når det er passende å bruke det.
Håndter feil på en god måte
Returner feilmeldinger AI-en kan forstå: {"error": "No slots available for that date"} i stedet for generiske 500-feil.
Hold svarene konsise
Returner bare det AI-en trenger for å fortsette samtalen. Store nyttelaster forsinker responstiden.
Bruk obligatoriske felt med omhu
Merk felt som required bare når det er helt nødvendig. AI-en vil be brukeren om obligatorisk informasjon før den kaller verktøyet.
Relatert
Plattformadministrerte verktøy for HubSpot, Salesforce, Slack, Google Kalender, Google Regneark og Cal.com — ingen endepunkt kreves.
Koble til en MCP-server og la agenten kalle verktøyene dens.
Gjenbrukbare REST-integrasjoner du kan koble til agenter.
Én verifiseringshjelper for webhooks og verktøykall.