Appels
Chaque interaction vocale sur Manivox.ai est un appel. Les appels sont soit entrants (un appelant compose votre numéro) soit sortants (la plateforme compose un contact). Chaque appel génère un enregistrement riche, transcription, variables collectées, événements de transition de nœuds, métriques de latence, et un enregistrement audio optionnel.
Types d'appels
| Type | Déclencheur | Cas d'usage typiques |
|---|---|---|
| Entrant | Un tiers externe appelle un numéro assigné à un agent | Support client, prise de rendez-vous, remplacement SVI, couverture après les heures d'ouverture |
| Sortant, campagne | Le composeur de campagne parcourt automatiquement une liste de contacts, à une cadence contrôlée et dans les plages horaires d'appel | Prospection commerciale, sondages de satisfaction, rappels de rendez-vous, confirmations de livraison à grande échelle |
| Sortant, appel unitaire | Déclenché depuis votre propre backend avec POST /v1/calls (clé API avec la permission calls:write) ou l'endpoint de session POST /api/calls |
Suivis ponctuels, rappels de paiement, notifications déclenchées par votre propre backend |
La mise en place, l'exécution et la lecture d'une campagne sont décrites sur la page Campagnes ; ce à quoi ressemble un appel sortant de l'intérieur (statuts, résultats, numéro présenté, rappels) est décrit sur Appels sortants.
Cycle de vie d'un appel
Chaque appel passe par une séquence de statuts. Les appels sortants démarrent à QUEUED ; les appels entrants entrent à RINGING.
Les appels sortants démarrent à QUEUED ; les appels entrants entrent à RINGING. Depuis là, les appels passent à IN_PROGRESS lorsqu'ils sont décroché, et se terminent à COMPLETED ou dans l'un des statuts terminaux listés dans le tableau ci-dessous.
| Statut | Description | Terminal ? |
|---|---|---|
QUEUED | Enregistrement d'appel créé, SIP INVITE en cours d'envoi vers l'opérateur (sortant uniquement) | Non |
RINGING | L'opérateur fait sonner la destination | Non |
IN_PROGRESS | Appel décroché, session de l'agent active et traitement de la parole en cours | Non |
COMPLETED | Appel terminé normalement, nœud Hangup exécuté ou l'une des parties a raccroché proprement | Oui |
FAILED | Erreur SIP, problème réseau, plantage de l'agent ou exception non gérée | Oui |
NO_ANSWER | L'appel sortant n'a pas été décroché dans le délai imparti | Oui |
BUSY | La ligne de destination était occupée (SIP 486) | Oui |
CANCELED | L'appel a été annulé avant d'être décroché (SIP 487) | Oui |
L'enregistrement d'appel
Chaque appel génère un enregistrement persistant, une ligne dans la table calls plus des tables enfants dédiées aux tours de transcription et aux événements de flux. L'enregistrement est peuplé progressivement, les entrées de transcription sont écrites pendant l'appel, duration et le statut final sont définis à la fin.
| Champ | Type | Description |
|---|---|---|
id | string | Identifiant unique de l'appel (CUID2) |
direction | enum | INBOUND ou OUTBOUND |
status | enum | Statut actuel, voir le cycle de vie ci-dessus |
from_number | string | Numéro E.164 de l'appelant (ex. +33612345678) |
to_number | string | Numéro E.164 appelé (votre numéro pour les entrants, la destination pour les sortants) |
caller_id | string | null | Identifiant d'appelant utilisé pour les appels sortants (le numéro affiché à la partie appelée) |
duration | integer | null | Durée totale de l'appel en secondes (définie à la fin de l'appel) |
queued_at | datetime | Horodatage de création de l'enregistrement d'appel |
ringing_at | datetime | null | Quand l'opérateur a commencé à faire sonner la destination |
answered_at | datetime | null | Quand l'appel a été décroché et la session de l'agent démarrée |
ended_at | datetime | null | Quand l'appel s'est déconnecté |
transcript | array | Tours de conversation ordonnés, chacun avec role, content, horodatage et métriques de latence (voir ci-dessous). Stocké dans la table enfant call_transcript_entries. |
call_variables | object | Toutes les variables collectées et résolues pendant l'appel |
tool_calls | array | Appels d'API externes et MCP effectués pendant l'appel, avec paramètres, réponse et horodatage |
call_events | array | Événements de transition de nœuds, chemin emprunté dans le graphe conversationnel. Stocké dans la table enfant call_event_entries. |
call_summary | object | null | Résumé de l'appel généré par LLM (quand l'évaluation est configurée) |
call_objectives | array | null | Objectifs d'évaluation et leurs résultats (quand l'évaluation est configurée) |
call_quality_score | integer | null | Score de qualité calculé par l'évaluation (0–100) |
sip_headers | object | null | En-têtes SIP reçus sur les appels entrants (métadonnées x-mai-* transportées dans l'INVITE) |
recording_url | string | null | Chemin côté serveur vers l'enregistrement WAV (si recording_enabled est vrai sur l'agent) |
agent_id | string | L'agent qui a géré cet appel |
agent_version_id | string | La version exacte de l'agent (snapshot) qui s'est exécutée, épinglée au démarrage de l'appel, immuable |
experiment_id | string | null | Le test A/B qui a routé cet appel, lorsqu'un test était en cours |
experiment_arm | string | null | Le bras (A ou B) auquel cet appel a été assigné ; conservé même si le bras est ensuite repointé vers une version fixe, afin que agent_version_id reste la vérité concrète de ce qui s'est exécuté |
campaign_id | string | null | La campagne qui a passé cet appel, ou à laquelle un rappel a été associé. null sur les appels entrants ordinaires et sur la répétition Call me first d'une campagne (qui enregistre sa campagne dans metadata à la place, afin de ne jamais fausser les chiffres de la campagne) |
campaign_contact_id | string | null | Le contact de campagne auquel cet appel appartient, sur les tentatives de campagne et sur les rappels reconnus |
attempt_number | integer | null | Le numéro de la tentative sur ce contact que représente cet appel (1 pour la première). Absent sur un rappel : un rappel n'est pas l'une de nos tentatives |
disposition | string | null | Le verdict de l'opérateur sur un appel sortant : ANSWERED, BUSY, NO_ANSWER, UNREACHABLE, VOICEMAIL, INVALID, REJECTED, CONGESTION, CARRIER_CAPPED, CALLED_BACK ou FAILED. Voir Campagnes → résultats |
queued_at | datetime | null | Quand la plateforme a passé un appel sortant. C'est cet instant, et non le premier événement de l'agent, qui marque le début de l'appel sur sa chronologie |
Transcription et métriques de latence
Chaque entrée de transcription capture non seulement ce qui a été dit, mais aussi à quelle vitesse. Les tours de l'agent incluent la décomposition complète de la latence pour le tour : STT → premier token LLM → premier octet audio TTS.
// Tour utilisateur
{ "role": "user", "content": "Je voudrais connaître mon solde.", "ts": 0.8 }
// Tour agent avec décomposition complète de la latence
{
"role": "agent",
"content": "Bien sûr. Votre solde est de 142,50 €.",
"ts": 3.2,
"stt_latency_ms": 210,
"llm_latency_ms": 185,
"tts_latency_ms": 92,
"total_latency_ms": 487
}
Un total_latency_ms régulièrement supérieur à 800 ms indique un problème de fournisseur ou de réseau qui mérite investigation. Vérifiez les champs llm_latency_ms et tts_latency_ms pour identifier le goulot d'étranglement.
Tours interrompus (barge-in)
Quand l'appelant coupe la parole à l'agent en plein milieu d'une phrase, la transcription affiche exactement ce que l'appelant a réellement entendu en texte normal, avec le reste coupé ajouté en orange, de sorte que ce que vous lisez correspond à l'enregistrement plutôt qu'à la phrase complète que l'agent avait générée. Sur la rare paire adjacente où la ligne agent interrompue s'afficherait autrement sous la coupure de l'appelant (la ligne agent n'est finalisée qu'au moment où le barge-in la coupe), la vue de détail d'appel réordonne la paire pour que la ligne agent apparaisse toujours au-dessus de l'interruption qui l'a coupée.
Détail par tour : RAG, outils & cache
Activez Show metrics sur la page de détail d'appel pour révéler des informations supplémentaires attachées à chaque tour :
- Extraits RAG récupérés : un tour ayant lancé une recherche dans une base de connaissances affiche un badge
RAG, dépliez-le pour voir chaque extrait récupéré avec son score de pertinence, triés du plus élevé au plus faible. - Détail des appels outils / API : un tour ayant invoqué une action Web Service ou Composio affiche un compteur d'appels d'outils, dépliez-le pour voir la méthode, le statut, la durée et les corps de requête et de réponse de chaque appel (rédigés côté serveur, la même rédaction que celle appliquée par l'API).
- Appels d'outils supprimés : si le modèle a demandé un outil sur un tour dont la course de routage a été remportée par une exit route avant que l'outil n'ait pu s'exécuter, une note ambrée, « An action was not run », le signale et explique que l'action a été sautée car l'appel était déjà passé à l'étape suivante ; utilisez une exit route basée sur une règle sur cette étape si vous avez besoin que l'action s'exécute systématiquement.
- Compteurs de tokens en cache : pour les tours utilisant un fournisseur LLM compatible avec la mise en cache des prompts, un pourcentage de cache-hit s'affiche à côté des compteurs de tokens, avec les nombres exacts de tokens en cache / total disponibles dans le panneau de détail LLM déplié du tour.
Séparateurs de transition de nœud
Lorsque vous ouvrez le détail d'un appel, la transcription est affichée sous forme de conversation. Chaque fois que le flux passe d'un nœud au suivant, une pastille de séparation est insérée entre les tours, une pastille indigo ornée d'une flèche, libellée Acheminé vers {nom du nœud}. Elle marque l'instant précis de la conversation où l'agent a changé de nœud de flux, ce qui permet de voir d'un coup d'œil quelle partie de la conversation chaque nœud a traitée.
Trois autres types de séparateurs vous indiquent comment l'appel s'est terminé et pourquoi :
- Fin d'appel : {nom du nœud} : le nœud Hangup qui a clos l'appel, dessiné au-dessus de son message d'au revoir. Quand le flux a atteint ce nœud par une route de sortie, le séparateur ajoute via « {libellé de la route} », en reprenant le libellé de la route tel que configuré dans la version qui s'est exécutée, et précise si la route a été décidée immédiatement, après la réponse, ou par une règle.
- Transféré vers {cible} : le nœud Transfer qui a remis l'appel à un humain ; c'est le dernier séparateur, puisque le transfert est la dernière étape.
- Échec du transfert vers {cible} : la cible n'a pas répondu, était occupée ou injoignable, le flux a donc continué sur la branche d'échec du transfert.
Un séparateur rouge, Une action d'enregistrement n'a pas été exécutée, apparaît quand l'appel est passé à l'étape suivante avant qu'une action d'écriture (réservation, ticket, mise à jour CRM) ait pu s'exécuter : tout ce que l'agent a dit sur le fait que c'était enregistré n'est adossé à aucune donnée sauvegardée. Liez l'action à une route de sortie basée sur une règle à cette étape pour garantir qu'elle s'exécute d'abord.
Enregistrement audio
Un enregistrement n'existe que si l'agent avait l'enregistrement activé (recording_enabled). Le cas échéant, l'audio de l'appel est capturé et sauvegardé sous forme de fichier WAV sur le serveur. La plupart des utilisateurs l'écoutent directement depuis le tableau de bord.
Les enregistrements sont conservés 7 jours. Le fichier audio est supprimé automatiquement 7 jours après l'appel ; la transcription et tous les autres détails de l'appel restent disponibles. Si vous devez conserver un enregistrement, téléchargez-le pendant cette fenêtre via le bouton Télécharger du lecteur ou l'endpoint API ci-dessous.
Écouter depuis le tableau de bord
Sur la page de détail d'un appel, l'enregistrement est présenté sous forme d'un lecteur audio à forme d'onde interactif. L'audio est tracé en une forme d'onde intégrée avec une règle de temps en dessous, et chaque tour de parole est mis en évidence sous forme de région colorée sur la frise (bleu pour l'appelant, vert pour l'agent), ce qui permet de voir d'un coup d'œil qui a parlé et quand. Le lecteur propose lecture/pause, retour et avance rapides, et un affichage du temps courant. Cliquer sur un tour de la transcription positionne la lecture à cet instant, et la position du curseur met en surbrillance le tour correspondant dans la transcription au fil de la lecture.
Un bouton Télécharger dans le lecteur enregistre l'enregistrement sous forme de fichier .wav sur votre ordinateur.
Dans la liste des appels, toute ligne dont l'appel possède un enregistrement affiche un petit bouton de lecture/arrêt intégré, ce qui permet d'écouter un appel sans l'ouvrir.
Accès programmatique (API)
Vous pouvez aussi récupérer l'enregistrement directement via l'API (authentification requise) :
# Diffusion en ligne dans le navigateur (Content-Disposition: inline)
GET /api/calls/{call_id}/recording
# Téléchargement en tant que fichier (Content-Disposition: attachment)
GET /api/calls/{call_id}/recording?download
Les deux réponses retournent Content-Type: audio/wav avec le support Accept-Ranges: bytes. Un 404 est retourné si l'enregistrement n'existe pas ou a déjà été supprimé (les enregistrements sont retirés automatiquement au bout de 7 jours).
Liste des appels (tableau de bord)
La page Tableau de bord → Voir les appels affiche tous les appels de votre organisation, avec une colonne Compte à côté de l'agent pour voir en un coup d'œil à quel client final chaque appel appartient, et une durée affichée dans un format lisible (ex. 1m 31s plutôt qu'un nombre de secondes brut). Depuis la liste, vous pouvez :
- Filtrer par plage de dates, agent, statut, direction (Inbound / Outbound), campagne (le sélecteur de campagne n'apparaît qu'une fois que votre organisation a des campagnes), compte, qui a raccroché (appelant ou agent), sentiment, bras A/B, ou durée. Le sélecteur A/B arm (All A/B arms / Arm A / Arm B) sélectionne les appels routés par un test A/B et cadre la bande de KPI ainsi que l'export CSV en même temps que la liste ; il est partageable dans l'URL sous la forme
?arm=B. Le filtre de durée prend un nombre de secondes et une comparaison au choix (≥, par défaut, ou ≤) ; en secondes parce que c'est ce que stocke la colonne Durée triable : un 60 saisi ici et un 60 dans cette colonne sont le même nombre. Les appels jamais connectés (sans durée) ne correspondent à aucune des deux comparaisons. Une recherche libre par numéro ou agent complète la barre. - Repérer les appels de campagne : les lignes sortantes sont teintées en bleu, les lignes entrantes en violet. Sur la page d'un appel, une puce à côté du badge de direction nomme la campagne qui l'a composé et renvoie vers son rapport ; une répétition Call me first affiche Test call for [campaign] à la place
- Repérer les appels A/B d'un coup d'œil : un appel routé par un test A/B porte un badge bleu A ou violet B à côté du nom de l'agent, au-dessus de la ligne de version
v{N} - Ouvrir le détail d'un appel en cliquant sur une ligne, affiche la transcription complète, les variables collectées, les événements de flux et les métriques de latence
- Lire l'enregistrement directement dans le navigateur (si l'enregistrement était activé)
- Exporter les données d'appels du filtre actuel en CSV