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 — 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

  1. Määrität työkalut skeemalla (mitkä argumentit työkalu hyväksyy)
  2. Määrität endpoint-asetuksen (mihin ThunderPhone kutsuu API-rajapintaasi) — tai jätät sen pois, jolloin saat työkalukutsut organisaatiosi webhookiin
  3. Puhelun aikana tekoäly päättää keskustelun perusteella, milloin työkalua käytetään
  4. ThunderPhone kutsuu päätepistettäsi työkalun argumenteilla
  5. API-vastauksesi välitetään takaisin tekoälylle keskustelun jatkamiseksi
OminaisuusMissä se suoritetaanMääritys
Sisäänrakennetut työkalutThunderPhoneKehoteohjeet; jotkin työkalut tarvitsevat myös agenttiasetuksen
SovellusyhteydetThunderPhone ja yhdistetty palveluntarjoajaYhdistä tili ja liitä hyväksytyt toiminnot
API-yhteydet ja funktiotyökalutHTTP API-rajapintasiMääritä päätepiste ja skeema tai vastaanota funktiokutsut webhookin kautta
MCP-palvelimetEtäinen MCP-palvelinLisää 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äTyyppiPakollinenKuvaus
timeoutnumeroEiEnimmäissuoritusaika sekunteina (oletus: 20, enintään: 180)

Funktiomääritelmä

KenttäTyyppiPakollinenKuvaus
namemerkkijonoKylläTyökalun yksilöllinen tunniste
descriptionmerkkijonoKylläKertoo tekoälylle, milloin tätä työkalua käytetään
parametersobjektiKylläJSON-skeema työkalun argumenteille

Päätepisteen määritys

KenttäTyyppiPakollinenKuvaus
urlmerkkijonoKylläAPI-rajapintasi päätepisteen URL-osoite
methodmerkkijonoEiHTTP-metodi (oletus: POST)
headersobjektiEiMukaan sisällytettävät mukautetut otsakkeet

Kaksi kutsutapaa

Palvelimesi vastaanottama pyyntö 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
RunkoValittu pyyntömuoto (oletuksena pelkät argumentit)telephony.tool / web.tool -kirjekuori
OtsakkeetSinun endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature-V2 + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature-V2 + X-ThunderPhone-Signature
AllekirjoitusavainOrganisaation webhook-salaisuusOrganisaation 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-key

Omat 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-allekirjoitukset
  • X-ThunderPhone-Signature — vanha HMAC-SHA256 pyynnön rungon tarkoista tavuista samalla avaimella; lähetetään edelleen olemassa olevia vahvistajia varten
  • X-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-V2 allekirjoittaa 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öille GET / DELETE. Se lähetetään edelleen muuttumattomana.

SDK-aputoiminnot tarkistavat V2-otsakkeen, mukaan lukien 5 minuutin aikarajan:

Python
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}
Node.js
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ää