Outils de fonction
Donnez à vos agents vocaux IA des outils de fonction qui appellent des API externes en pleine conversation — récupérer des données client, prendre des rendez-vous, mettre à jour des dossiers — avec des paramètres typés.
Les outils de fonction permettent à vos agents IA d’appeler des API externes pendant les appels téléphoniques. Utilisez-les pour rechercher des données client, vérifier les disponibilités, réserver des rendez-vous ou effectuer toute action prise en charge par votre backend.
Fonctionnement
- Définissez des outils avec un schéma (les arguments acceptés par l’outil)
- Fournissez une configuration
endpoint(où ThunderPhone appelle votre API) — ou omettez-la pour recevoir les appels d’outils sur le webhook de votre organisation - Pendant un appel, l’IA décide quand utiliser un outil en fonction de la conversation
- ThunderPhone appelle votre endpoint avec les arguments de l’outil
- La réponse de votre API est renvoyée à l’IA pour poursuivre la conversation
Schéma de l’outil
Chaque outil suit cette structure :
{
"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
}Configuration de l’outil
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
timeout | nombre | Non | Temps d’exécution maximal en secondes (par défaut : 20, maximum : 180) |
Définition de fonction
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
name | chaîne | Oui | Identifiant unique de l’outil |
description | chaîne | Oui | Indique à l’IA quand utiliser cet outil |
parameters | objet | Oui | Schéma JSON des arguments de l’outil |
Configuration de l’endpoint
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
url | chaîne | Oui | URL de l’endpoint de votre API |
method | chaîne | Non | Méthode HTTP (par défaut : POST) |
headers | objet | Non | En-têtes personnalisés à inclure |
Deux chemins d’appel
La requête reçue par votre serveur dépend de la présence ou non d’un
endpoint pour l’outil :
Outil avec endpoint | Outil sans endpoint | |
|---|---|---|
| Destination de la requête | Directement vers endpoint.url | URL de webhook héritée de votre organisation |
| Corps | Arguments bruts de l’outil | Enveloppe telephony.tool / web.tool |
| En-têtes | Vos endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature | Content-Type + X-ThunderPhone-Signature |
| Clé de signature | Secret du webhook de l’organisation | Secret du webhook de l’organisation |
Les deux chemins sont bloquants — l’IA attend le résultat en pleine
phrase. Le délai d’expiration par défaut est de 20 s ; définissez le
timeout de premier niveau de l’outil pour autoriser une exécution plus longue,
jusqu’au maximum de la plateforme de 180 s. Gardez les gestionnaires rapides. Un mélange est possible :
lors d’un appel dont l’organisation possède une URL de webhook, les outils avec un endpoint sont
appelés directement et les autres utilisent le webhook.
Appels directs à un endpoint
Lorsque l’IA invoque un outil qui possède un endpoint, ThunderPhone envoie
une requête à votre URL :
En-têtes de requête
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-keyLes en-têtes personnalisés de votre endpoint.headers sont toujours inclus
verbatim, ainsi que deux en-têtes dans l’espace de noms ThunderPhone :
X-ThunderPhone-Signature— HMAC-SHA256 des octets exacts du corps de la requête, avec votre secret de webhook de l’organisation comme cléX-ThunderPhone-Call-ID— L’ID de l’appel en cours
Content-Type: application/json est défini sauf si votre endpoint.headers
le remplace — un Content-Type personnalisé prévaut.
Corps de la requête
Pour POST / PUT / PATCH, le corps contient uniquement les arguments
de l’outil (sans enveloppe), sérialisés de manière canonique (clés triées,
séparateurs compacts) :
{"date":"2025-01-02","service":"consultation"}Pour GET / DELETE, les arguments sont envoyés en tant que paramètres de requête
et le corps est vide — la signature est alors calculée sur la chaîne
d’octets vide. Consultez
Vérifier les signatures de webhook.
Réponse
Renvoyez une réponse JSON contenant le résultat de l’outil :
{
"available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
"timezone": "America/Los_Angeles"
}La réponse est mise en forme et fournie à l’IA pour poursuivre la
conversation. Les réponses non JSON sont encapsulées sous la forme {"data": "<text>"} ;
les délais d’expiration et les échecs de connexion sont signalés à l’IA comme des erreurs afin que
l’agent puisse s’excuser et continuer plutôt que de rester bloqué.
Distribution en mode webhook
Les outils sans endpoint sont distribués à l’URL de webhook historique de votre
organisation sous la forme d’une requête signée telephony.tool (appels téléphoniques) ou web.tool
(appels web). Contrairement aux notifications d’audit
envoyées aux endpoints de webhook après l’exécution, cette requête est
l’exécution — votre réponse HTTP constitue le résultat de l’outil.
{
"type": "telephony.tool",
"data": {
"call_id": 987654321,
"tool_name": "search_appointments",
"arguments": { "date": "2026-04-21" },
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}web.tool contient origin_domain à la place de from_number /
to_number. Répondez avec le résultat de l’outil au format JSON — le même contrat de réponse
que pour les appels directs à un endpoint. La requête est signée avec le secret de webhook de l’organisation
sur le corps brut, comme tout autre webhook.
Vérification de signature
Les appels directs d’outils sont signés de la même manière que les webhooks :
- HMAC-SHA256 sur les octets exacts du corps de la requête (le JSON canonique — clés triées, sans espaces superflus)
- Avec le secret webhook de votre organisation comme clé
- Les outils
GET/DELETEsignent la chaîne d’octets vide
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}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 });
});Les recettes complètes — y compris le cas du corps vide et la réserve concernant l’absence de secret — sont disponibles dans Vérifier les signatures de webhook.
Exemple : flux de réservation complet
Voici un ensemble d’outils pour un système complet de prise de rendez-vous :
{
"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" }
}
}
]
}Bonnes pratiques
Rédiger des descriptions claires
Le champ description aide l’IA à comprendre quand utiliser l’outil. Indiquez précisément ce qu’il fait et dans quels cas il est approprié.
Gérer les erreurs avec élégance
Renvoyez des messages d’erreur que l’IA peut comprendre : {"error": "No slots available for that date"} plutôt que des erreurs 500 génériques.
Garder les réponses concises
Renvoyez uniquement ce dont l’IA a besoin pour poursuivre la conversation. Les charges utiles volumineuses ralentissent les temps de réponse.
Utiliser les champs obligatoires avec discernement
Marquez les champs comme required uniquement lorsque c’est réellement nécessaire. L’IA demandera à l’utilisateur les informations obligatoires avant d’appeler l’outil.
Pages associées
Outils gérés par la plateforme pour HubSpot, Salesforce, Slack, Google Calendar, Google Sheets et Cal.com — aucun point de terminaison requis.
Connectez un serveur MCP et laissez l’agent appeler ses outils.
Intégrations REST réutilisables que vous pouvez associer à des agents.
Un seul outil de vérification pour les webhooks et les appels d’outils.