Open in
Créer une intégration d
Permettez à votre agent d
Une intégration d’outil est un point de terminaison HTTP réutilisable qu’un agent peut appeler pendant un appel. Vous fournissez à ThunderPhone une description du schéma JSON de l’outil ainsi qu’une URL de point de terminaison ; l’agent décide quand l’appeler en fonction de la conversation, puis ThunderPhone effectue la requête HTTP sortante depuis ses serveurs et renvoie la réponse à l’agent.
Ce guide explique de bout en bout comment créer un outil de consultation de la météo.
Anatomie d’un outil
Deux éléments :
- Le schéma — une définition de fonction de style OpenAI
(
{type: "function", function: {name, description, parameters}}) qui indique au LLM ce que fait l’outil et quels arguments il accepte. - Le point de terminaison — l’URL appelée par les serveurs de ThunderPhone lorsque le LLM décide d’utiliser l’outil. La requête est un POST JSON dont le corps contient les arguments choisis par le LLM.
1. Choisir un éditeur
Ouvrez Connexions → APIs, créez ou modifiez la connexion API, passez l’éditeur de paramètres en JSON, puis ajoutez-y le format.
Créez la spécification avec POST /v1/integrations, ou mettez-la à jour avec
PATCH /v1/integrations/{id}.
Les deux méthodes créent une intégration enregistrée. Attachez cette intégration à l’agent
après l’avoir enregistrée. L’API Agents ne possède aucun champ tools intégré accessible en écriture.
Ce guide utilise la méthode via l’API d’intégrations.
2. Créez l’intégration
curl -X POST https://api.thunderphone.com/v1/integrations \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"display_name": "Weather API",
"spec": {
"type": "function",
"function": {
"name": "get_weather",
"description": "Return the current weather for a zip code.",
"parameters": {
"type": "object",
"properties": {
"zip": { "type": "string", "description": "5-digit US ZIP code" }
},
"required": ["zip"]
}
}
},
"endpoint_url": "https://api.example.com/weather",
"endpoint_method": "GET",
"headers": [
{ "key": "X-Api-Key", "value": "your-provider-key" }
]
}'Enregistrez l’id renvoyé (un UUID). Les valeurs d’en-tête sont accessibles en écriture uniquement : les réponses répertorient uniquement les noms d’en-tête, et un PATCH ultérieur peut envoyer un en-tête sans value pour conserver la valeur stockée.
Déclarez format: "email" sur les paramètres d’adresse
Un paramètre qui reçoit une adresse e-mail doit l’indiquer dans son schéma :
"email": { "type": "string", "format": "email", "description": "The caller's email address" }format est plus qu’une indication. Pour un schéma d’e-mail résolu, avant
d’appeler votre endpoint, ThunderPhone supprime les espaces en début et fin de valeur,
met le domaine en minuscules, transforme les mots anglais isolés at, dot,
underscore, dash et hyphen en leurs caractères correspondants, et supprime les
espaces directement autour de @, ., _ et -. Ces mots ont le même sens,
que la transcription contienne déjà ou non un @ littéral :
"john dot smith at gmail dot com" devient
john.smith@gmail.com.
Tout autre espace interne est rejeté plutôt que joint silencieusement.
Les mots de séparation prononcés sont pris en charge uniquement en anglais ; les formes
espacées non anglaises ou non reconnues échouent de manière sécurisée. Les domaines
internationalisés valides et les parties locales SMTPUTF8 sont acceptés. Une entrée
Punycode reste en Punycode et une entrée de domaine Unicode reste en Unicode après la
normalisation de l’analyseur : votre API reçoit donc la représentation conventionnelle
fournie par l’appelant. Si la valeur finale est invalide, l’outil n’est pas appelé.
L’agent reçoit invalid_email_argument, qui lui indique
de confirmer l’orthographe avec l’appelant et de renvoyer l’adresse littérale.
Un e-mail facultatif omis n’est pas modifié. null, une chaîne vide ou une
chaîne ne contenant que des espaces ne sont pas non plus modifiés lorsque la propriété est facultative
ou nullable ; ces mêmes valeurs sont rejetées pour un e-mail obligatoire et non nullable.
Les références de schéma locales telles que #/$defs/email et
#/definitions/email, ainsi que anyOf, oneOf et allOf, sont inspectées
avec des limites de cycles et de profondeur. Un $ref non local ou impossible à résoudre
constitue une limite d’application connue et est transmis sans modification, tout comme un appel
dont l’instantané de l’outil ne comporte aucun schéma exploitable. Conservez les schémas d’e-mail
locaux lorsque vous devez appliquer ce contrôle.
Les paramètres sans format d’e-mail appliqué sont transmis exactement tels que le modèle les a produits.
Les formats pris en charge sont date-time, time, date, duration,
email, hostname, ipv4, ipv6 et uuid ; seul email est
normalisé et appliqué aujourd’hui.
3. Testez l’endpoint dans le sandbox
Avant de lier l’intégration à un agent, envoyez une requête signée depuis les serveurs de ThunderPhone pour confirmer la connectivité :
curl -X POST https://api.thunderphone.com/v1/integrations/test-request \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/weather?zip=94110",
"method": "GET",
"headers": { "X-Api-Key": "your-provider-key" }
}'{
"ok": true,
"status": 200,
"elapsed_ms": 187,
"response_headers": { "content-type": "application/json" },
"response_preview": "{\"temperature_f\": 64, ...}"
}Ce test renforce également les protections SSRF de ThunderPhone : les requêtes vers
localhost ou des plages d’IP privées renvoient 400 code=url_not_allowed.
4. Lier l'intégration à un agent
Associez-la via integration_ids lorsque vous créez ou mettez à jour un agent :
curl -X PATCH https://api.thunderphone.com/v1/agents/12 \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"integration_ids": ["f9b5a1a4-..."]
}'Vous pouvez lier plusieurs intégrations à un même agent. Le prompt de l'agent peut
y faire référence par leur nom — « utilisez get_weather lorsque l'appelant demande
des informations sur les conditions météorologiques » — ou les découvrir implicitement à partir des
descriptions du schéma.
5. Implémenter l'endpoint
Lorsque l'agent invoque l'outil, ThunderPhone envoie une requête POST signée vers
votre endpoint_url :
POST /weather HTTP/1.1
Host: api.example.com
X-Api-Key: your-provider-key
X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<HMAC-SHA256 hex>
X-ThunderPhone-Signature: <HMAC-SHA256 hex>
X-ThunderPhone-Call-ID: 987654321
Content-Type: application/json
{"zip": "94110"}
Votre serveur répond avec du JSON qui est renvoyé au LLM :
{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}Le LLM assimile cette réponse et en donne un résumé naturel à l'appelant.
6. Tester la boucle
Lancez une session micro avec l'agent et posez la question que votre outil traite (« Quel temps fait-il à 94110 ? »). La transcription de l'appel affiche l'aller-retour complet :
{
"call_id": 987654321,
"transcripts": [
{ "role": "user",
"content": "What's the weather in 94110?" },
{ "role": "tool_call",
"content": "{\"tool_call\": \"get_weather\", \"arguments\": {\"zip\": \"94110\"}}" },
{ "role": "tool_response",
"content": "{\"tool_name\": \"get_weather\", \"response\": {\"temperature_f\": 64, \"condition\": \"Partly cloudy\"}}" },
{ "role": "agent",
"content": "It's 64 degrees and partly cloudy." }
]
}Vous pouvez récupérer cela avec
GET /v1/calls/{call_id}/transcript ;
le flux d'événements brut (avec le minutage de chaque entrée et les décalages audio) est disponible via
GET /v1/calls/{call_id}/history.
Dans les interfaces de liste d’appels et d’analytique, ThunderPhone distingue désormais les appels de test du trafic réel. Les tests et simulations Browser Talk peuvent réutiliser un vrai numéro de téléphone et sembler entrants, mais ils ne sont pas comptabilisés dans les totaux d’appels en production, les notes ou les métriques de problèmes.
Pièges fréquents
L'agent n'appelle jamais l'outil
Le LLM décide en fonction de la description de l'outil. Si la question de l'appelant
ne correspond pas à la description, le modèle n'invoquera pas
l'outil. Précisez la description (ajoutez des synonymes et
formulations courants) ou mentionnez-le explicitement dans le prompt de l'agent (« Lorsque
l'appelant pose une question sur la météo, utilisez get_weather. »).
L'outil renvoie trop de données
Les réponses de plus de 6 kB sont tronquées dans l'aperçu de la transcription. Renvoyez uniquement les champs dont le LLM a besoin — pas toute votre ligne.
Délais d'expiration
Les endpoints d'outils ont un délai d'expiration par défaut de 10 secondes. Si vous avez besoin de plus de temps,
traitez la requête de manière asynchrone : renvoyez {"status": "pending", "request_id": "..."}
et exposez le résultat via un appel d'outil distinct.
Gestion des versions
Chaque PATCH d'intégration crée une nouvelle révision. Consultez
GET /v1/integrations/{id}/versions
pour voir qui a modifié quoi. Si vous cassez le schéma d'un outil, vous pouvez
revenir en arrière manuellement en appliquant par PATCH un ancien instantané.
Étapes suivantes
CRUD, transfert, historique des versions.
Grammaire complète du schéma JSON et contrat des endpoints signés.
Appliquez le modèle de signature de webhook aux endpoints des outils.
Inspectez l'aller-retour complet d'un appel d'outil.