ThunderPhone 2.0 este acum disponibil.Îl configurați singur, de la 2 ¢/min.Citiți anunțul

Function Tools

Instrumente de funcții

Oferiți agenților dumneavoastră AI instrumente de funcții care apelează API-uri externe în timpul conversației — preiau datele clienților, programează întâlniri, actualizează înregistrări — cu parametri tipizați.

Instrumentele de funcție le permit agenților dvs. AI să invoce API-uri externe în timpul apelurilor telefonice. Folosiți-le pentru a căuta date despre clienți, a verifica disponibilitatea, a programa întâlniri sau a efectua orice acțiune acceptată de backend-ul dvs.

Cum funcționează

  1. Definiți instrumente cu o schemă (ce argumente acceptă instrumentul)
  2. Furnizați o configurație endpoint (unde ThunderPhone apelează API-ul dvs.) — sau omiteți-o pentru a primi apelurile instrumentelor în webhook-ul organizației dvs.
  3. În timpul unui apel, AI-ul decide când să folosească un instrument pe baza conversației
  4. ThunderPhone apelează endpoint-ul dvs. cu argumentele instrumentului
  5. Răspunsul API-ului dvs. este transmis înapoi AI-ului pentru a continua conversația

Schema instrumentului

Fiecare instrument urmează această structură:

{
  "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
}

Configurarea instrumentului

CâmpTipObligatoriuDescriere
timeoutnumărNuTimpul maxim de execuție în secunde (implicit: 20, maxim: 180)

Definiția funcției

CâmpTipObligatoriuDescriere
nameșirDaIdentificator unic pentru instrument
descriptionșirDaExplică AI-ului când să utilizeze acest instrument
parametersobiectDaSchemă JSON pentru argumentele instrumentului

Configurarea endpoint-ului

CâmpTipObligatoriuDescriere
urlșirDaURL-ul endpoint-ului API-ului dvs.
methodșirNuMetoda HTTP (implicit: POST)
headersobiectNuAntete personalizate de inclus

Două căi de invocare

Solicitarea pe care o primește serverul dvs. depinde de existența unui endpoint pentru instrument:

Instrument cu endpointInstrument fără endpoint
Unde ajunge solicitareaDirect la endpoint.urlURL-ul webhook moștenit al organizației dvs.
CorpArgumente simple ale instrumentuluiPlic telephony.tool / web.tool
Anteteendpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature
Cheie de semnareSecretul webhook al organizațieiSecretul webhook al organizației

Ambele căi sunt blocante — AI-ul așteaptă rezultatul în mijlocul propoziției. Timpul de expirare implicit este de 20 s; setați timeout la nivelul superior al instrumentului pentru a permite o execuție mai lungă, până la maximul platformei de 180 s. Păstrați handler-ele rapide. Puteți utiliza o combinație: într-un apel al cărui organizație are un URL webhook, instrumentele cu un endpoint sunt apelate direct, iar restul revin la webhook.

Apeluri directe către endpoint

Când AI-ul invocă un instrument care are un endpoint, ThunderPhone trimite o solicitare către URL-ul dumneavoastră:

Antete de solicitare

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

Antetele personalizate din endpoint.headers sunt întotdeauna incluse literal, împreună cu două antete din spațiul de nume ThunderPhone:

  • X-ThunderPhone-Signature — HMAC-SHA256 al octeților exacți ai corpului solicitării, utilizând ca cheie secretul webhook al organizației
  • X-ThunderPhone-Call-ID — ID-ul apelului curent

Content-Type: application/json este setat dacă endpoint.headers nu îl suprascrie — un Content-Type personalizat are prioritate.

Corpul solicitării

Pentru POST / PUT / PATCH, corpul conține doar argumentele instrumentului (fără înveliș), serializate canonic (chei sortate, separatori compacți):

{"date":"2025-01-02","service":"consultation"}

Pentru GET / DELETE, argumentele sunt trimise ca parametri de interogare iar corpul este gol — semnătura este calculată apoi peste șirul gol de octeți. Consultați Verificarea semnăturilor webhook.

Răspuns

Returnați un răspuns JSON cu rezultatul instrumentului:

{
  "available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
  "timezone": "America/Los_Angeles"
}

Răspunsul este formatat și furnizat AI-ului pentru a continua conversația. Răspunsurile care nu sunt JSON sunt împachetate ca {"data": "<text>"}; expirările și eșecurile de conexiune sunt raportate AI-ului ca erori, astfel încât agentul să își poată cere scuze și să continue, în loc să se blocheze.

Distribuire în modul webhook

Instrumentele fără un endpoint sunt distribuite către URL-ul webhook vechi al organizației dumneavoastră ca solicitare semnată telephony.tool (apeluri telefonice) sau web.tool (apeluri web). Spre deosebire de notificările de audit livrate către endpointurile webhook după execuție, această solicitare este execuția — răspunsul dumneavoastră HTTP reprezintă rezultatul instrumentului.

{
  "type": "telephony.tool",
  "data": {
    "call_id": 987654321,
    "tool_name": "search_appointments",
    "arguments": { "date": "2026-04-21" },
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  }
}

web.tool conține origin_domain în loc de from_number / to_number. Răspundeți cu rezultatul instrumentului ca JSON — același contract de răspuns ca pentru apelurile directe către endpoint. Solicitarea este semnată cu secretul webhook al organizației peste corpul brut, la fel ca orice alt webhook.


Verificarea semnăturii

Apelurile directe ale instrumentelor sunt semnate la fel ca webhookurile:

  • HMAC-SHA256 peste octeții exacți ai corpului cererii (JSON-ul canonic — chei sortate, fără spații suplimentare)
  • Cu cheia secretului webhook al organizației dumneavoastră
  • Instrumentele GET / DELETE semnează șirul de octeți gol
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 });
});

Rețetele complete — inclusiv cazul cu corp gol și precizarea privind absența unui secret — sunt disponibile în Verificați semnăturile webhookurilor.


Exemplu: flux complet de programare

Iată un set de instrumente pentru un sistem complet de programare a întâlnirilor:

{
  "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" }
      }
    }
  ]
}

Practici recomandate

Scrieți descrieri clare

Câmpul description ajută IA să înțeleagă când să utilizeze instrumentul. Specificați clar ce face și când este potrivit să fie utilizat.

Gestionați erorile corect

Returnați mesaje de eroare pe care IA le poate înțelege: {"error": "No slots available for that date"} în locul unor erori 500 generice.

Păstrați răspunsurile concise

Returnați doar informațiile de care IA are nevoie pentru a continua conversația. Încărcăturile mari încetinesc timpii de răspuns.

Utilizați câmpurile obligatorii cu discernământ

Marcați câmpurile ca required doar atunci când este cu adevărat necesar. IA va cere utilizatorului informațiile obligatorii înainte de a apela instrumentul.


Asociate