Aller au contenu
Nos produitsSur-mesureSites & boutiquesRéférencesWe AreBlogNous contacter
Apparence
← Tous les articles
· 6 min de lecture#architecture#réversibilité#cas concret

Rester libre de son opérateur téléphonique : le SIP comme point de découplage

T

Thomas

Développeur Node.js

En bref

Comment éviter d'être prisonnier d'un fournisseur de téléphonie quand on déploie un agent vocal ?

En faisant entrer les appels par un trunk SIP plutôt que par l'API propriétaire de l'opérateur. Le SIP est un standard : changer d'opérateur revient à repointer un trunk, sans toucher au code de l'agent. Le piège se déplace alors ailleurs — vers la gestion des numéros, qui reste propre à chaque opérateur et qui est le vrai endroit où l'on se retrouve attaché.

Sur Discall, la téléphonie est le composant dont nous savions dès le départ qu’il changerait. Pas parce qu’un opérateur serait mauvais, mais parce que le choix ne nous appartient pas toujours : un client a déjà un contrat, un autre veut ses numéros chez un opérateur français pour des raisons de conformité, un troisième compare les tarifs à l’international.

La bonne nouvelle est que le découplage existe déjà, et qu’il ne demande pas d’écrire une couche d’abstraction maison. La moins bonne est qu’il ne protège pas de tout.

Le trunk SIP fait le travail

L’erreur serait de brancher l’agent sur l’API propriétaire de l’opérateur — celle qui pilote l’appel avec ses propres verbes et son propre format d’événements. C’est le chemin le plus rapide en démonstration, et celui qui rend le changement d’opérateur coûteux : la logique de conduite de l’appel se retrouve mélangée au vocabulaire d’un fournisseur.

Nous passons par un trunk SIP. L’opérateur ne fait alors qu’une chose : acheminer l’appel vers notre infrastructure temps réel, en SIP, qui est un standard. Chez nous, l’agent parle à cette infrastructure, jamais à l’opérateur.

La conséquence est que changer d’opérateur consiste à configurer un nouveau trunk et à repointer les numéros. Le code de l’agent — détection de parole, transcription, génération, synthèse — ne sait pas quel opérateur est en face, et n’a aucune raison de le savoir.

C’est ce qui nous permet de faire tourner Twilio et Telnyx en parallèle sur la même plateforme, selon les clients, sans branche conditionnelle dans la logique d’appel.

Ce que le SIP ne découple pas

Voilà le point qu’on découvre à l’usage, et qui compte davantage que le transport.

Un numéro de téléphone n’est pas seulement un identifiant : c’est une ressource achetée chez un opérateur, avec son API d’achat, sa portabilité, ses contraintes réglementaires. Là, aucun standard ne vient à la rescousse. Chaque opérateur a sa console, son API et ses règles.

Nous avons donc deux mondes qui divergent :

  • ce que l’on paie chez les opérateurs — les numéros réellement actifs sur les comptes ;
  • ce que la plateforme sait router — les numéros enregistrés en base et rattachés à un client et à un agent.

Ces deux listes devraient être identiques. Elles ne le sont jamais complètement, et c’est ce qui produit les incidents les plus pénibles à diagnostiquer : un numéro acheté chez un opérateur mais jamais enregistré côté plateforme est invisible dans l’interface. Il sonne dans le vide, il est facturé, et rien ne le signale.

Nous avons fini par écrire un inventaire de rapprochement : un module qui interroge tous les comptes opérateurs, les confronte à la base de routage, et affiche les écarts. Il ne fait aucune écriture — ni chez l’opérateur, ni en base. Importer un numéro reste un geste explicite, parce qu’une synchronisation automatique qui se tromperait couperait des appels en production.

Ce module est arrivé tard. Avec le recul, c’est le genre d’outil qu’il faut prévoir dès qu’on gère des numéros chez plus d’un opérateur — c’est-à-dire dès le deuxième client.

Une nuance sur la dégradation

Un détail de conception, appris de la même façon : quand l’inventaire interroge un opérateur et que celui-ci ne répond pas, il ne faut surtout pas afficher « aucun numéro ».

« Aucun numéro » et « je n’ai pas pu demander » sont deux informations opposées, et les confondre conduit à croire qu’un numéro a disparu du compte. Chaque opérateur est donc rapporté avec son propre état — répondu, ignoré parce que non configuré, ou en erreur — et l’interface distingue les trois.

C’est une règle qui vaut au-delà de la téléphonie : dès qu’un écran agrège plusieurs sources externes, l’absence de donnée et l’échec de la requête doivent se distinguer visuellement. Sinon on prend des décisions sur une panne en croyant lire un état.

Illustration Photo : domaine public (CC0).

Un piège de multi-tenant, dans le même sujet

Un détail qui n’a l’air de rien et qui aurait pu coûter cher.

Les comptes opérateurs sont globaux : une seule clé d’API par opérateur, pour toute la plateforme, quel que soit le nombre de clients hébergés. Le lien entre un numéro et le client auquel il appartient n’existe que dans notre base, pas chez l’opérateur.

Autrement dit, l’inventaire brut renvoyé par un opérateur contient les numéros de tous les clients. Un écran qui l’afficherait à un administrateur de client lui montrerait les numéros des autres — une fuite de données entre clients, sans qu’aucune requête n’ait été mal écrite.

L’endpoint qui expose cet inventaire est donc réservé aux administrateurs de la plateforme, et la raison est écrite à côté du code plutôt que dans une décision orale. C’est une précaution qui paraît excessive tant qu’on n’a pas vu quelqu’un rebrancher un module utile sur un écran client six mois plus tard, en toute bonne foi.

La règle générale que nous en tirons : dès qu’une ressource externe est partagée entre plusieurs clients, la vue par défaut doit être celle de la plateforme, et l’accès client doit être une restriction explicite. L’inverse — partir d’une vue client et espérer que le filtre soit toujours appliqué — finit toujours par laisser passer un cas.

Photo : domaine public (CC0).

L’isolation ne dispense pas de connaître le transport

Dernier point, contre-intuitif : découpler ne veut pas dire ignorer.

L’audio téléphonique n’a rien à voir avec l’audio d’une visioconférence. Il arrive en 8 kHz, avec une bande passante réduite à la voix, et une énergie plus faible. Un réglage de détection de parole calibré sur du WebRTC ne fonctionne pas sur du SIP — nous l’avons découvert avec des appels où l’agent restait littéralement sourd pendant toute la conversation, sans erreur nulle part.

Nous avons donc des réglages distincts selon le transport, appliqués automatiquement. L’agent ne sait pas quel opérateur l’appelle, mais il sait s’il est en SIP ou en WebRTC, et il s’y adapte.

C’est la bonne granularité de découplage : abstraire le fournisseur, pas la physique du canal. Une abstraction qui masquerait aussi la nature du transport nous aurait fait passer des semaines à chercher un bug de modèle là où le problème était un seuil.

La question à poser à un prestataire

Si vous faites construire un agent vocal, deux questions suffisent :

  1. Que faut-il modifier si nous changeons d’opérateur ? Si la réponse est « on repointe le trunk », le découplage existe. Si elle tourne autour de « il faudrait regarder », la logique d’appel est probablement écrite dans le vocabulaire d’un fournisseur.
  2. Comment savez-vous que tous les numéros que nous payons sont bien routés ? C’est la question qui surprend, et c’est celle dont la réponse coûte de l’argent tous les mois quand elle n’existe pas.

À lire aussi

Vous cherchez qui peut construire votre application ?

We IT conçoit, développe et exploite des applications web métier depuis 2022, à Lyon et partout en France. Cadrage, développement, mise en production et RUN.