ThunderPhone 2.0 on nyt julkaistu.Ota käyttöön itse – alkaen 2¢/min.Lue lisää julkistuksesta

Function Tools

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

  1. Määrität työkalut skeemalla (mitä argumentteja työkalu hyväksyy)
  2. Määrität endpoint-kokoonpanon (mihin ThunderPhone kutsuu API-rajapintaasi) — tai jätät sen pois vastaanottaaksesi työkalukutsut organisaatiosi webhookissa
  3. Puhelun aikana AI päättää keskustelun perusteella, milloin työkalua käytetään
  4. ThunderPhone kutsuu päätepistettäsi työkalun argumenteilla
  5. 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äTyyppiPakollinenKuvaus
timeoutnumberEiEnimmäissuoritusaika sekunteina (oletus: 20, enimmäisarvo: 180)

Funktion määritys

KenttäTyyppiPakollinenKuvaus
namestringKylläTyökalun yksilöllinen tunniste
descriptionstringKylläSelittää AI:lle, milloin tätä työkalua käytetään
parametersobjectKylläTyökalun argumenttien JSON-skeema

Päätepisteen kokoonpano

KenttäTyyppiPakollinenKuvaus
urlstringKylläAPI-rajapintasi päätepisteen URL-osoite
methodstringEiHTTP-metodi (oletus: POST)
headersobjectEiMukautetut sisällytettävät otsakkeet

Kaksi kutsupolkua

Se, minkä pyynnön palvelimesi vastaanottaa, riippuu siitä, onko työkalulla endpoint:

Työkalu, jossa on endpointTyökalu, jossa ei ole endpoint
Mihin pyyntö lähetetäänSuoraan osoitteeseen endpoint.urlOrganisaatiosi vanhaan webhook-URL-osoitteeseen
RunkoPelkät työkalun argumentittelephony.tool / web.tool -kirjekuori
OtsakkeetOma endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature
AllekirjoitusavainOrganisaation webhook-salaisuusOrganisaation 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-key

Mukautetut 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-salaisuudella
  • X-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- ja DELETE-työkalut allekirjoittavat tyhjän tavumerkkijonon
Python
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}
Node.js
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ää