Envoi d’outils — requêtes sortantes d’appel de fonction
Cette page documente la requête qu’Audact envoie au point de terminaison HTTP propre au tenant lorsque le LLM en cours d’appel invoque un outil personnalisé (appel de fonction) configuré sur un agent.
Authentification — X-Signature
Lorsqu’un secret de signature est configuré pour un outil, chaque envoi sortant porte :
X-Signature: <hex_hmac_sha256_of_raw_request_body>
- Algorithme : HMAC-SHA256 calculé sur les octets exacts du corps JSON brut qui est envoyé.
Contrairement à la signature des webhooks (voir Livraison des webhooks), la signature d’envoi d’outil ne comporte aucun
horodatage — c’est un simple HMAC du corps seul, et
il n’existe aucun en-tête compagnon de type
X-Audact-Timestamp. - Si aucun secret de signature n’est configuré pour l’outil,
X-Signatureest entièrement omis — configurez un secret sur l’outil si vous avez besoin de vérifier l’appelant. - Ne confondez pas avec
X-Audact-Signature(la signature de livraison des webhooks, qui comprend bien un horodatage et prend en charge la rotation à double clé). Ce sont deux mécanismes indépendants pour deux surfaces indépendantes (webhooks et envoi d’outils). - Vérification de votre côté : recalculez
hex(hmac_sha256(secret, raw_body))et comparez-le en temps constant à la valeur de l’en-têteX-Signature.
Structure du corps de la requête
Par défaut (args_only = false) :
json
{
"name": "<tool_name>",
"args": { "...": "LLM-supplied arguments, merged with any const fields" },
"call": {
"tenant_id": "<uuid>",
"call_id": "<uuid>",
"turn": 3,
"jurisdiction": "NL",
"direction": "inbound",
"vars": { "...": "current dynamic-variable snapshot" }
}
}call.call_idest toujours présent dès que le contextecallest disponible — c’est la frontière de sécurité sur laquelle doit s’appuyer un gardecall_id → tenant_idsur votre point de terminaison.call.tenant_idest aussi toujours présent à ses côtés.call.varsest la table courante des variables dynamiques du pipeline (valeurs résolues par la substitution de{{varName}}et variables de réponse d’outil extraites jusqu’ici) — et non un champ nommécall.metadata. Les métadonnées par appel sont une fonctionnalité distincte et seront ajoutées à cet objet dès qu’elles seront disponibles.call.directionvaut"inbound"ou"outbound".call.turnest le numéro du tour de conversation en cours (entier, à partir de 1).
args_only = true : l’enveloppe {name, args, call} est entièrement supprimée et le corps de la requête est
uniquement args — un objet JSON plat, sans enveloppe, sans name, sans call. C’est un booléen délibéré et
explicite, propre à chaque outil (ToolConfig.ArgsOnly, champ JSON args_only), qu’un tenant active lorsque
son point de terminaison attend un corps plat ; ce n’est pas une option cachée du tableau de bord.
Délai d’expiration, nouvelles tentatives et traitement de la réponse
- Délai d’expiration par outil :
ToolConfig.Execution.TimeoutMs; lorsqu’il n’est pas défini (zéro), la valeur par défaut est 120 000 ms (120 s). La plage acceptée lorsqu’il est défini explicitement est[1, 300000]ms (5 minutes au maximum). - Nouvelles tentatives : jusqu’à 3 tentatives au total, avec 500 ms d’attente entre deux tentatives. Une tentative arrivée à expiration n’est jamais rejouée — les nouvelles tentatives ne s’appliquent qu’aux erreurs hors expiration (erreurs réseau, réponses non 2xx). Les nouvelles tentatives s’arrêtent aussi immédiatement si le contexte parent (en cours d’appel) est annulé.
- Plafond du corps de la réponse : 15 000 caractères ; les corps plus longs sont tronqués avant d’être renvoyés au LLM.
- Extraction de variables de réponse : les chemins à points de
ToolConfig.ResponseVarssont extraits de la réponse JSON vers le stock de variables dynamiques du pipeline (feuilles de type chaîne, nombre ou booléen uniquement ; les tableaux et les objets ne sont pas extraits) et deviennent disponibles pour les substitutions{{varName}}suivantes et pour les appels d’outils ultérieurs au sein du même appel. - Le client HTTP des outils est protégé contre le SSRF : les résolutions d’adresses sont validées par rapport aux plages privées, de bouclage et de lien local avant la connexion, à chaque tentative.
Exemple : vérifier et lire une requête d’envoi d’outil (pseudocode)
sig := request.header("X-Signature")
if sig != hex(hmac_sha256(secret, raw_body)):
reject()
body := json.parse(raw_body)
call_id := body.call.call_id # always present
tenant_id := body.call.tenant_id # always present
args := body.args # or the whole body if args_only