Funktiotyökalut
Anna AI-agenteillesi funktiotyökaluja, jotka kutsuvat ulkoisia API-rajapintoja kesken keskustelun — hakevat asiakastietoja, varaavat tapaamisia ja päivittävät tietueita — tyypitetyillä parametreilla.
Toimintotyökalujen avulla AI-agenttisi voivat kutsua ulkoisia API-rajapintoja puheluiden aikana. Käytä niitä asiakastietojen hakemiseen, saatavuuden tarkistamiseen, ajanvarausten tekemiseen tai minkä tahansa taustajärjestelmäsi tukeman toiminnon suorittamiseen.
Miten se toimii
- Määrität työkalut skeemalla (mitä argumentteja työkalu hyväksyy)
- Määrität
endpoint-kokoonpanon (mihin ThunderPhone kutsuu API-rajapintaasi) — tai jätät sen pois vastaanottaaksesi työkalukutsut organisaatiosi webhookissa - Puhelun aikana AI päättää keskustelun perusteella, milloin työkalua käytetään
- ThunderPhone kutsuu päätepistettäsi työkalun argumenteilla
- API-vastauksesi syötetään takaisin AI:lle keskustelun jatkamiseksi
Työkalun skeema
Jokainen työkalu noudattaa tätä rakennetta:
{
"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
}Työkalun kokoonpano
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
timeout | number | Ei | Enimmäissuoritusaika sekunteina (oletus: 20, enimmäisarvo: 180) |
Funktion määritys
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
name | string | Kyllä | Työkalun yksilöllinen tunniste |
description | string | Kyllä | Selittää AI:lle, milloin tätä työkalua käytetään |
parameters | object | Kyllä | Työkalun argumenttien JSON-skeema |
Päätepisteen kokoonpano
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
url | string | Kyllä | API-rajapintasi päätepisteen URL-osoite |
method | string | Ei | HTTP-metodi (oletus: POST) |
headers | object | Ei | Mukautetut sisällytettävät otsakkeet |
Kaksi kutsupolkua
Se, minkä pyynnön palvelimesi vastaanottaa, riippuu siitä, onko työkalulla
endpoint:
Työkalu, jossa on endpoint | Työkalu, jossa ei ole endpoint | |
|---|---|---|
| Mihin pyyntö lähetetään | Suoraan osoitteeseen endpoint.url | Organisaatiosi vanhaan webhook-URL-osoitteeseen |
| Runko | Pelkät työkalun argumentit | telephony.tool / web.tool -kirjekuori |
| Otsakkeet | Oma endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature | Content-Type + X-ThunderPhone-Signature |
| Allekirjoitusavain | Organisaation webhook-salaisuus | Organisaation webhook-salaisuus |
Molemmat polut ovat estävät — AI odottaa tulosta kesken
lauseen. Oletusaikakatkaisu on 20 s; määritä työkalun ylätason
timeout, jos haluat sallia pidemmän suorituksen, enintään alustan
180 s enimmäisaikaan asti. Pidä käsittelijät nopeina. Yhdistelmä toimii hyvin:
puhelussa, jonka organisaatiolla on webhook-URL, työkaluja, joilla on endpoint, kutsutaan
suoraan ja muut palaavat webhookiin.
Suorat endpoint-kutsut
Kun AI kutsuu työkalua, jolla on endpoint, ThunderPhone lähettää
pyynnön URL-osoitteeseesi:
Pyyntöotsakkeet
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-keyMukautetut otsakkeet kohteesta endpoint.headers sisällytetään aina
sellaisenaan sekä kaksi ThunderPhone-nimiavaruuteen kuuluvaa otsaketta:
X-ThunderPhone-Signature— pyynnön rungon tarkkojen tavujen HMAC-SHA256, joka on avattu organisaatiosi webhook-salaisuudellaX-ThunderPhone-Call-ID— nykyisen puhelun tunnus
Content-Type: application/json asetetaan, ellei endpoint.headers
korvaa sitä — mukautettu Content-Type on ensisijainen.
Pyynnön runko
POST- / PUT- / PATCH-pyynnöissä runko sisältää vain työkalun
argumentit (ei käärettä), kanonisesti sarjoitettuna (avaimet lajiteltuina,
tiiviit erotinmerkit):
{"date":"2025-01-02","service":"consultation"}GET- / DELETE-pyynnöissä argumentit lähetetään kyselyparametreina
ja runko on tyhjä — allekirjoitus lasketaan tällöin tyhjästä
tavujonosta. Katso
Webhook-allekirjoitusten vahvistaminen.
Vastaus
Palauta JSON-vastaus, joka sisältää työkalun tuloksen:
{
"available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
"timezone": "America/Los_Angeles"
}Vastaus muotoillaan ja annetaan AI:lle keskustelun jatkamista varten.
Muut kuin JSON-vastaukset kääritään muotoon {"data": "<text>"};
aikakatkaisuista ja yhteysvirheistä ilmoitetaan AI:lle virheinä, jotta
agentti voi pahoitella ja jatkaa sen sijaan, että keskustelu pysähtyisi.
Webhook-tilan välitys
Työkalut, joilla ei ole endpoint-määritystä, välitetään organisaatiosi
vanhaan webhook-URL-osoitteeseen allekirjoitettuna telephony.tool-
(puhelut) tai web.tool-pyyntönä (verkkopuhelut). Toisin kuin
auditointi-ilmoitukset, jotka toimitetaan webhook-endpointeihin
suorituksen jälkeen, tämä pyyntö on suoritus — HTTP-vastauksesi on
työkalun tulos.
{
"type": "telephony.tool",
"data": {
"call_id": 987654321,
"tool_name": "search_appointments",
"arguments": { "date": "2026-04-21" },
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}web.tool sisältää origin_domain-kentän from_number- /
to_number-kenttien sijaan. Vastaa työkalun tuloksella JSON-muodossa —
sama vastaussopimus kuin suorissa endpoint-kutsuissa. Pyyntö allekirjoitetaan
organisaation webhook-salaisuudella raakaa runkoa käyttäen, kuten kaikki
muutkin webhookit.
Allekirjoituksen vahvistaminen
Suorat työkalukutsut allekirjoitetaan samalla tavalla kuin webhookit:
- HMAC-SHA256 tarkkojen pyynnön rungon tavujen yli (kanoninen JSON — lajitellut avaimet, ei ylimääräisiä välilyöntejä)
- Käyttää organisaatiosi webhook-salaisuutta avaimena
GET- jaDELETE-työkalut allekirjoittavat tyhjän tavumerkkijonon
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 });
});Täydelliset ohjeet — mukaan lukien tyhjän rungon tapaus ja huomio salaisuuden puuttumisesta — ovat kohdassa Webhook-allekirjoitusten vahvistaminen.
Esimerkki: täydellinen ajanvarauskulku
Tässä on työkalujoukko täydellistä ajanvarausjärjestelmää varten:
{
"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" }
}
}
]
}Parhaat käytännöt
Kirjoita selkeät kuvaukset
description-kenttä auttaa tekoälyä ymmärtämään, milloin työkalua käytetään. Kerro tarkasti, mitä se tekee ja milloin sen käyttö on sopivaa.
Käsittele virheet hallitusti
Palauta virheilmoituksia, jotka tekoäly ymmärtää: {"error": "No slots available for that date"} yleisten 500-virheiden sijaan.
Pidä vastaukset tiiviinä
Palauta vain se, mitä tekoäly tarvitsee keskustelun jatkamiseksi. Suuret vastaukset hidastavat vasteaikoja.
Käytä pakollisia kenttiä harkiten
Merkitse kentät required-tilaan vain, kun se on todella tarpeen. Tekoäly pyytää käyttäjältä pakolliset tiedot ennen työkalun kutsumista.
Aiheeseen liittyvää
Alustan hallinnoimat työkalut HubSpotille, Salesforcelle, Slackille, Google Calendarille, Google Sheetsille ja Cal.comille — päätepistettä ei tarvita.
Liitä MCP-palvelin ja anna agentin kutsua sen työkaluja.
Uudelleenkäytettävät REST-integraatiot, jotka voit liittää agentteihin.
Yksi vahvistusapuri webhookeille ja työkalukutsuille.