Open in
Strumenti di funzione
Fornisci ai tuoi agenti AI strumenti di funzione che chiamano API esterne durante la conversazione — recuperano dati dei clienti, fissano appuntamenti, aggiornano record — con parametri tipizzati.
Gli strumenti funzione consentono ai tuoi agenti AI di invocare API esterne durante le chiamate telefoniche. Usali per cercare dati dei clienti, verificare la disponibilità, prenotare appuntamenti o eseguire qualsiasi azione supportata dal tuo backend.
Come funziona
- Definisci gli strumenti con uno schema (quali argomenti accetta lo strumento)
- Fornisci una configurazione
endpoint(dove ThunderPhone chiama la tua API) oppure omettila per ricevere le chiamate degli strumenti sul webhook della tua organizzazione - Durante una chiamata, l'AI decide quando usare uno strumento in base alla conversazione
- ThunderPhone chiama il tuo endpoint con gli argomenti dello strumento
- La risposta della tua API viene restituita all'AI per continuare la conversazione
| Capacità | Dove viene eseguito | Configurazione |
|---|---|---|
| Strumenti integrati | ThunderPhone | Istruzioni nel prompt; alcuni strumenti richiedono anche un'impostazione dell'agente |
| Connessioni app | ThunderPhone e il provider connesso | Connetti l'account e associa le azioni approvate |
| Connessioni API e strumenti funzione | La tua API HTTP | Definisci l'endpoint e lo schema, oppure ricevi le chiamate funzione tramite webhook |
| Server MCP | Un server MCP remoto | Aggiungi il server, rileva i suoi strumenti e associalo all'agente |
Schema dello strumento
Ogni strumento segue questa struttura:
{
"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
}Configurazione dello strumento
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
timeout | numero | No | Tempo massimo di esecuzione in secondi (predefinito: 20, massimo: 180) |
Definizione della funzione
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
name | stringa | Sì | Identificatore univoco dello strumento |
description | stringa | Sì | Spiega all'AI quando usare questo strumento |
parameters | oggetto | Sì | Schema JSON per gli argomenti dello strumento |
Configurazione dell'endpoint
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
url | stringa | Sì | URL dell'endpoint della tua API |
method | stringa | No | Metodo HTTP (predefinito: POST) |
headers | oggetto | No | Intestazioni personalizzate da includere |
Due percorsi di invocazione
La richiesta ricevuta dal tuo server dipende dal fatto che lo strumento abbia un
endpoint:
Strumento con endpoint | Strumento senza endpoint | |
|---|---|---|
| Destinazione della richiesta | Direttamente a endpoint.url | URL webhook legacy della tua organizzazione |
| Corpo | Formato della richiesta selezionato (argomenti senza wrapper per impostazione predefinita) | Involucro telephony.tool / web.tool |
| Intestazioni | endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature-V2 + X-ThunderPhone-Signature | Content-Type + X-ThunderPhone-Signature-V2 + X-ThunderPhone-Signature |
| Chiave di firma | Segreto webhook dell'organizzazione | Segreto webhook dell'organizzazione |
Entrambi i percorsi sono bloccanti: l'AI attende il
risultato a metà frase. Il timeout predefinito è 20 s; imposta il
timeout di primo livello dello strumento per consentire un'esecuzione più lunga, fino al
massimo della piattaforma di 180 s. Mantieni gli handler rapidi. Puoi combinarli:
in una chiamata la cui organizzazione dispone di un URL webhook, gli strumenti con un endpoint vengono
chiamati direttamente e gli altri usano il webhook.
Chiamate dirette agli endpoint
Quando l'AI richiama uno strumento con un endpoint, ThunderPhone invia
una richiesta al tuo URL:
Intestazioni della richiesta
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-keyLe intestazioni personalizzate di endpoint.headers vengono sempre incluse
alla lettera, insieme a queste intestazioni con namespace ThunderPhone:
X-ThunderPhone-Signature-V2— HMAC-SHA256 con timestamp su metodo, percorso, query e corpo, con chiave nel tuo segreto webhook dell'organizzazione. Verifica questa firma e rifiuta le richieste più vecchie di 5 minuti; consulta Verificare le firme webhookX-ThunderPhone-Signature— HMAC-SHA256 legacy dei byte esatti del corpo della richiesta, stessa chiave, ancora inviata per i verificatori esistentiX-ThunderPhone-Call-ID— L'ID della chiamata corrente
Content-Type: application/json viene impostato a meno che il tuo endpoint.headers
non lo sovrascriva — un Content-Type personalizzato ha la precedenza.
Formato della richiesta
Ogni connessione API ha un'impostazione request_format. Scegli vapi o
retell quando uno strumento importato deve continuare a chiamare un endpoint creato per
quella piattaforma. Le connessioni nuove ed esistenti usano standard per impostazione predefinita.
Per POST / PUT / PATCH, ThunderPhone serializza in modo canonico
l'involucro selezionato (chiavi ordinate, separatori compatti). Entrambe le firme
coprono questi byte esatti.
Standard
standard invia solo gli argomenti dello strumento, senza wrapper. Questo è il comportamento
predefinito e preserva il corpo della richiesta originale di ThunderPhone byte per byte:
{"date":"2025-01-02","service":"consultation"}Vapi
vapi invia il messaggio server tool-calls
di Vapi nella forma documentata da Vapi. Il call.id è l'ID della chiamata ThunderPhone. L'id
della chiamata allo strumento è univoco per l'invocazione e viene riutilizzato per associare il
risultato dell'endpoint. La chiamata appare sia in toolCallList sia in
toolWithToolCallList, con function.arguments come oggetto JSON:
{
"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" }
}
}
}
]
}
}I campi esclusivi di Vapi come assistant, artifact e l'oggetto call completo
non vengono inviati.
Restituisci l'involucro di risposta di Vapi con l'ID della chiamata allo strumento corrispondente:
{
"results": [
{
"toolCallId": "call_00112233445566778899aabbccddeeff",
"result": "{\"available_slots\":[\"9:00 AM\",\"2:00 PM\"]}"
}
]
}ThunderPhone fornisce all'IA la stringa result senza involucro. Accetta anche un
valore JSON per la compatibilità con endpoint che ne restituiscono già uno. Un
error al posto di result viene restituito all'IA come errore dello strumento. Se l'
endpoint restituisce un involucro Vapi non valido o non corrispondente, ThunderPhone registra
un avviso e passa all'analisi standard della risposta invece di interrompere
la chiamata.
Retell
retell invia la richiesta documentata per una funzione personalizzata
Retell:
{
"name": "search_appointments",
"call": { "call_id": "987654321" },
"args": { "date": "2025-01-02", "service": "consultation" }
}L'oggetto call include solo call_id. ThunderPhone non include
campi specifici di Retell che non può fornire correttamente al momento dell'invio, come
agent_id, transcript, transcript_object, metadata o variabili
dinamiche. Retell accetta qualsiasi corpo della risposta; ThunderPhone lo inoltra
utilizzando la gestione standard della risposta.
Per GET / DELETE, gli argomenti vengono inviati come parametri di query
e il corpo è vuoto indipendentemente da request_format. La firma V2
copre la stringa di query così come inviata; la firma legacy viene calcolata sulla
stringa di byte vuota. Consulta
Verifica le firme dei webhook.
Risposta
Restituisci una risposta JSON con il risultato dello strumento:
{
"available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
"timezone": "America/Los_Angeles"
}La risposta viene formattata e fornita all'AI per continuare la
conversazione. Le risposte non JSON vengono racchiuse in {"data": "<text>"};
i timeout e gli errori di connessione vengono segnalati all'AI come errori,
così l'agente può scusarsi e proseguire anziché bloccarsi.
Instradamento in modalità webhook
Gli strumenti senza un endpoint vengono instradati all'URL webhook legacy
della tua organizzazione come richiesta firmata telephony.tool (chiamate
telefoniche) o web.tool (chiamate web). A differenza delle
notifiche di audit recapitate agli endpoint webhook dopo
l'esecuzione, questa richiesta è l'esecuzione — la tua risposta HTTP è il
risultato dello strumento.
{
"type": "telephony.tool",
"data": {
"call_id": 987654321,
"tool_name": "search_appointments",
"arguments": { "date": "2026-04-21" },
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}web.tool include origin_domain invece di from_number /
to_number. Rispondi con il risultato dello strumento in formato JSON — lo stesso contratto di risposta delle chiamate dirette agli endpoint. La richiesta è firmata con il segreto webhook dell'organizzazione, con entrambe le intestazioni della firma, come qualsiasi altro webhook.
Verifica della firma
Le chiamate dirette agli strumenti sono firmate come i webhook, usando il segreto webhook della tua organizzazione:
X-ThunderPhone-Signature-V2firma il timestamp, il metodo, il percorso e la query così come inviati, nonché i byte esatti del corpo. Rifiuta le richieste il cui timestamp differisce di più di 5 minuti dal tuo orologio.X-ThunderPhone-Signature(legacy) firma solo i byte del corpo, la stringa di byte vuota perGET/DELETE. Viene ancora inviata, invariata.
Gli helper dell'SDK verificano l'header V2, inclusa la finestra di 5 minuti:
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 });
});Le procedure complete — la stringa firmata, un esempio pratico, il codice senza
SDK, il caso GET / DELETE e l'avvertenza in assenza di segreto — sono disponibili in Verificare le firme dei webhook.
Esempio: flusso di prenotazione completo
Ecco un insieme di strumenti per un sistema completo di prenotazione appuntamenti:
{
"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" }
}
}
]
}Best practice
Scrivi descrizioni chiare
Il campo description aiuta l'IA a capire quando usare lo strumento. Specifica con precisione cosa fa e quando è appropriato utilizzarlo.
Gestisci gli errori in modo efficace
Restituisci messaggi di errore comprensibili per l'IA: {"error": "No slots available for that date"} anziché errori 500 generici.
Mantieni concise le risposte
Restituisci solo ciò di cui l'IA ha bisogno per continuare la conversazione. Payload di grandi dimensioni rallentano i tempi di risposta.
Usa con criterio i campi obbligatori
Contrassegna i campi come required solo quando è davvero necessario. L'IA chiederà all'utente le informazioni obbligatorie prima di chiamare lo strumento.
Correlati
Attiva azioni di chiamata gestite dalla piattaforma senza definire un endpoint.
Strumenti gestiti dalla piattaforma per HubSpot, Salesforce, Slack, Google Calendar, Google Sheets e Cal.com — nessun endpoint richiesto.
Collega un server MCP e consenti all'agente di chiamare i suoi strumenti.
Integrazioni REST riutilizzabili che puoi collegare agli agenti.
Un unico strumento di verifica per webhook e chiamate degli strumenti.