Open in
Funktiotyökalut
Anna AI-agenteillesi funktiotyökaluja, jotka kutsuvat ulkoisia API-rajapintoja kesken keskustelun — hakevat asiakastietoja, varaavat tapaamisia ja päivittävät tietueita — tyyppimääritetyillä parametreilla.
Funktiotyökalujen avulla AI-agenttisi voivat kutsua ulkoisia API-rajapintoja puheluiden aikana. Käytä niitä asiakastietojen hakemiseen, saatavuuden tarkistamiseen, tapaamisten varaamiseen tai mihin tahansa toimintoon, jota taustajärjestelmäsi tukee.
Näin se toimii
- Määrität työkalut skeemalla (mitkä argumentit työkalu hyväksyy)
- Määrität
endpoint-asetuksen (mihin ThunderPhone kutsuu API-rajapintaasi) — tai jätät sen pois, jolloin saat työkalukutsut organisaatiosi webhookiin - Puhelun aikana tekoäly päättää keskustelun perusteella, milloin työkalua käytetään
- ThunderPhone kutsuu päätepistettäsi työkalun argumenteilla
- API-vastauksesi välitetään takaisin tekoälylle keskustelun jatkamiseksi
| Ominaisuus | Missä se suoritetaan | Määritys |
|---|---|---|
| Sisäänrakennetut työkalut | ThunderPhone | Kehoteohjeet; jotkin työkalut tarvitsevat myös agenttiasetuksen |
| Sovellusyhteydet | ThunderPhone ja yhdistetty palveluntarjoaja | Yhdistä tili ja liitä hyväksytyt toiminnot |
| API-yhteydet ja funktiotyökalut | HTTP API-rajapintasi | Määritä päätepiste ja skeema tai vastaanota funktiokutsut webhookin kautta |
| MCP-palvelimet | Etäinen MCP-palvelin | Lisää palvelin, hae sen työkalut ja liitä se agenttiin |
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 määritys
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
timeout | numero | Ei | Enimmäissuoritusaika sekunteina (oletus: 20, enintään: 180) |
Funktiomääritelmä
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
name | merkkijono | Kyllä | Työkalun yksilöllinen tunniste |
description | merkkijono | Kyllä | Kertoo tekoälylle, milloin tätä työkalua käytetään |
parameters | objekti | Kyllä | JSON-skeema työkalun argumenteille |
Päätepisteen määritys
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
url | merkkijono | Kyllä | API-rajapintasi päätepisteen URL-osoite |
method | merkkijono | Ei | HTTP-metodi (oletus: POST) |
headers | objekti | Ei | Mukaan sisällytettävät mukautetut otsakkeet |
Kaksi kutsutapaa
Palvelimesi vastaanottama pyyntö 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 | Valittu pyyntömuoto (oletuksena pelkät argumentit) | telephony.tool / web.tool -kirjekuori |
| Otsakkeet | Sinun endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature-V2 + X-ThunderPhone-Signature | Content-Type + X-ThunderPhone-Signature-V2 + X-ThunderPhone-Signature |
| Allekirjoitusavain | Organisaation webhook-salaisuus | Organisaation webhook-salaisuus |
Molemmat tavat ovat synkronisia — tekoäly odottaa tulosta kesken
lauseen. Oletusaikakatkaisu on 20 s; määritä työkalun ylimmän tason
timeout, jos tarvitset pidemmän suoritusajan, enintään alustan 180 s
-rajaan asti. Pidä käsittelijät nopeina. Voit käyttää molempia:
puhelussa, jonka organisaatiolla on webhook-URL-osoite, työkalut, joilla on endpoint,
kutsutaan suoraan ja muut käyttävät webhookia.
Suorat päätepistekutsut
Kun tekoäly kutsuu työkalua, jolla on endpoint, ThunderPhone lähettää
pyynnön URL-osoitteeseesi:
Pyynnön otsakkeet
POST /appointments/search HTTP/1.1
Host: api.example.com
Content-Type: application/json
X-ThunderPhone-Signature-V2: t=1767225600,v1=5f2c...
X-ThunderPhone-Signature: abc123...
X-ThunderPhone-Call-ID: 987654321
X-Api-Key: your-api-keyOmat endpoint.headers-otsakkeesi sisällytetään aina sellaisinaan
sekä seuraavat ThunderPhone-nimiavaruuden otsakkeet:
X-ThunderPhone-Signature-V2— aikaleimattu HMAC-SHA256 metodista, polusta, kyselystä ja rungosta, avaimena organisaatiosi webhook-salaisuus. Vahvista tämä ja hylkää yli 5 minuuttia vanhat pyynnöt; katso Vahvista webhook-allekirjoituksetX-ThunderPhone-Signature— vanha HMAC-SHA256 pyynnön rungon tarkoista tavuista samalla avaimella; lähetetään edelleen olemassa olevia vahvistajia vartenX-ThunderPhone-Call-ID— Nykyisen puhelun tunniste
Content-Type: application/json asetetaan, ellei endpoint.headers
ohita sitä — mukautettu Content-Type on ensisijainen.
Pyyntömuoto
Jokaisella API-yhteydellä on request_format-asetus. Valitse vapi tai
retell, kun tuodun työkalun tulee edelleen kutsua kyseiselle alustalle
rakennettua päätepistettä. Uusien ja olemassa olevien yhteyksien oletusarvo on standard.
Kohteille POST / PUT / PATCH ThunderPhone sarjallistaa valitun
verhon kanonisesti (avaimet lajiteltuina, tiiviit erottimet). Molemmat allekirjoitukset
kattavat nämä täsmälliset tavut.
Standard
standard lähettää vain työkalun argumentit ilman käärettä. Tämä on
oletusasetus, ja se säilyttää ThunderPhonen alkuperäisen pyynnön rungon tavusta tavuun:
{"date":"2025-01-02","service":"consultation"}Vapi
vapi lähettää Vapin palvelinviestin tool-calls
Vapin dokumentoimassa muodossa. call.id on ThunderPhone-puhelun tunniste. Työkalukutsun
id on yksilöllinen kutsulle, ja sitä käytetään uudelleen päätepisteen tuloksen
yhdistämiseen. Puhelu näkyy sekä kohteessa toolCallList että
toolWithToolCallList, ja function.arguments on JSON-objekti:
{
"message": {
"type": "tool-calls",
"timestamp": 1725000000123,
"call": { "id": "987654321" },
"toolCallList": [
{
"id": "call_00112233445566778899aabbccddeeff",
"type": "function",
"function": {
"name": "search_appointments",
"arguments": { "date": "2025-01-02", "service": "consultation" }
}
}
],
"toolWithToolCallList": [
{
"type": "function",
"function": { "name": "search_appointments" },
"toolCall": {
"id": "call_00112233445566778899aabbccddeeff",
"type": "function",
"function": {
"name": "search_appointments",
"arguments": { "date": "2025-01-02", "service": "consultation" }
}
}
}
]
}
}Vapi-kohtaisia kenttiä, kuten assistant, artifact ja koko call-objektia,
ei lähetetä.
Palauta Vapin vastausverho vastaavalla työkalukutsun tunnisteella:
{
"results": [
{
"toolCallId": "call_00112233445566778899aabbccddeeff",
"result": "{\"available_slots\":[\"9:00 AM\",\"2:00 PM\"]}"
}
]
}ThunderPhone antaa tekoälylle käärimättömän result-merkkijonon. Se hyväksyy myös
JSON-arvon yhteensopivuuden vuoksi sellaisten päätepisteiden kanssa, jotka jo palauttavat
sellaisen. error-kenttä result-kentän tilalla palautetaan tekoälylle työkalun virheenä.
Jos päätepiste palauttaa virheellisen muotoisen tai täsmäämättömän Vapi-verhon, ThunderPhone kirjaa
varoituksen ja palaa vakiovastauksen jäsennykseen puhelun epäonnistamisen sijaan.
Retell
retell lähettää Retell-mukautetulle
funktiolle dokumentoidun pyynnön:
{
"name": "search_appointments",
"call": { "call_id": "987654321" },
"args": { "date": "2025-01-02", "service": "consultation" }
}call-objekti sisältää vain kentän call_id. ThunderPhone ei sisällytä
Retell-kohtaisia kenttiä, joita se ei voi rehellisesti toimittaa lähetysvaiheessa, kuten
agent_id, transcript, transcript_object, metadata tai dynaamisia
muuttujia. Retell hyväksyy minkä tahansa vastausrungon; ThunderPhone välittää sen
vakiovastauskäsittelyllä.
Kohteille GET / DELETE argumentit lähetetään kyselyparametreina,
ja runko on tyhjä request_format-asetuksesta riippumatta. V2-allekirjoitus
kattaa lähetetyn kyselymerkkijonon; vanha allekirjoitus lasketaan
tyhjästä tavumerkkijonosta. Katso
Webhook-allekirjoitusten vahvistaminen.
Vastaus
Palauta työkalun tulos JSON-vastauksena:
{
"available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
"timezone": "America/Los_Angeles"
}Vastaus muotoillaan ja toimitetaan tekoälylle keskustelun jatkamiseksi.
Muut kuin JSON-vastaukset kääritään muotoon {"data": "<text>"};
aikakatkaisuista ja yhteysvirheistä ilmoitetaan tekoälylle virheinä,
jotta agentti voi pyytää anteeksi ja jatkaa sen sijaan, että se jäisi
odottamaan.
Välitys webhook-tilassa
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
audit-ilmoitukset, jotka toimitetaan webhook-päätepisteisiin
suorituksen jälkeen, tämä pyyntö on itse 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 päätepistekutsuissa. Pyyntö on allekirjoitettu organisaation
webhook-salaisuudella ja sisältää molemmat allekirjoitusotsakkeet, kuten kaikki muutkin webhookit.
Allekirjoituksen vahvistus
Suorat työkalukutsut allekirjoitetaan samalla tavalla kuin webhookit käyttäen organisaatiosi webhook-salaisuutta:
X-ThunderPhone-Signature-V2allekirjoittaa aikaleiman, metodin, polun ja kyselyparametrit lähetetyssä muodossa sekä tarkat pyynnön rungon tavut. Hylkää pyynnöt, joiden aikaleima poikkeaa kellostasi yli 5 minuuttia.X-ThunderPhone-Signature(vanha versio) allekirjoittaa vain pyynnön rungon tavut tai tyhjän tavujonon pyynnöilleGET/DELETE. Se lähetetään edelleen muuttumattomana.
SDK-aputoiminnot tarkistavat V2-otsakkeen, mukaan lukien 5 minuutin aikarajan:
import json
from fastapi import FastAPI, HTTPException, Request
from thunderphone import verify_signature
app = FastAPI()
@app.post("/appointments/search")
async def search_appointments(request: Request):
body = await request.body()
query = request.scope.get("query_string", b"").decode("latin-1")
path = request.url.path + (f"?{query}" if query else "")
if not verify_signature(
request.headers.get("X-ThunderPhone-Signature-V2"),
secret=WEBHOOK_SECRET,
method=request.method,
path=path,
body=body,
):
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}import express from "express";
import { verifySignature } from "@thunderphone/sdk";
app.post('/appointments/search', express.raw({type: 'application/json'}), (req, res) => {
const ok = verifySignature({
header: req.header('X-ThunderPhone-Signature-V2'),
secret: WEBHOOK_SECRET,
method: req.method,
path: req.originalUrl,
body: req.body,
});
if (!ok) 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 — allekirjoitettava merkkijono, käytännön esimerkki, koodi ilman
SDK:ta, GET / DELETE -tapaus ja huomautus tilanteesta, jossa salaista avainta ei ole — ovat kohdassa Webhook-allekirjoitusten vahvistaminen.
Esimerkki: täydellinen varausprosessi
Tässä on työkalut täydelliseen ajanvarausjärjestelmään:
{
"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
Kenttä description auttaa tekoälyä ymmärtämään, milloin työkalua käytetään. Kerro tarkasti, mitä se tekee ja milloin sen käyttö on tarkoituksenmukaista.
Käsittele virheet hallitusti
Palauta virheilmoituksia, jotka tekoäly ymmärtää: {"error": "No slots available for that date"} yleisten 500-virheiden sijaan.
Pidä vastaukset ytimekkäinä
Palauta vain se, mitä tekoäly tarvitsee keskustelun jatkamiseksi. Suuret hyötykuormat hidastavat vastausaikoja.
Käytä pakollisia kenttiä harkiten
Merkitse kentät required-kentiksi vain, kun se on todella tarpeen. Tekoäly pyytää käyttäjältä pakolliset tiedot ennen työkalun kutsumista.
Aiheeseen liittyvää
Käynnistä alustan hallinnoimia puhelutoimintoja määrittämättä päätepistettä.
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 varmennusapuri webhookeille ja työkalukutsuille.