🎯 Ce que tu as ici : un standard téléphonique IA qui décroche à la place du garagiste ou du cabinet dentaire, propose de vrais créneaux, écrit le RDV dans Google Agenda et envoie la confirmation par e-mail. Hébergé sur ton VPS, pour environ 4 centimes la minute.
📦 Le code est sur GitHub : NautyZ-coder/agent-vocal-ia
Tout est dedans : le serveur vocal, l'assistant de configuration, les 2 workflows n8n et un script qui vérifie toute la chaîne. Deux métiers prêts à l'emploi : garage et cabinet dentaire. Tu choisis le tien à l'étape 4.
✅ Ce que tu obtiens
- Un agent qui annonce qu'il est une IA dès le début (obligatoire, voir plus bas), comprend le besoin et le range dans un type de RDV (garage : vidange, freinage, diagnostic… ; cabinet : urgence, contrôle, détartrage…)
- 3 créneaux max, étalés dans la journée, calculés à partir des horaires, du nombre de ponts ou de fauteuils et de l'agenda réel. Il refuse une heure qui n'existe pas et repropose les vraies.
- Récap (garage : nom, véhicule, immat, problème ; cabinet : nom, motif, déjà patient ou non ; e-mail relu lettre par lettre), puis réservation seulement après un « oui »
- RDV écrit dans Google Agenda, mail de confirmation au client, mail « Nouveau RDV » (🔧 ou 🦷) au garage ou au cabinet
- Devis, suivi, réclamation : il prend un message, envoyé par mail au garage ou au cabinet
- Côté cabinet dentaire : aucun conseil médical, les urgences passent en priorité, et il renvoie vers le 15 en cas d'urgence grave
- Rapport de fin d'appel avec la transcription complète
- Une page d'appel dans le navigateur pour tester gratuitement, sans numéro de téléphone
- Multi-clients : un fichier de config par garage ou par cabinet, donc revendable
Le circuit d'un appel
- Le client appelle le numéro Twilio ou ouvre la page /appel.
- L'audio arrive en temps réel sur ton VPS : Deepgram (oreilles) → Gemini ou Claude (cerveau) → Cartesia (voix).
- L'agent appelle n8n par webhooks.
- n8n écrit dans Google Agenda et envoie les mails par Gmail.
🧰 Prérequis
| Quoi | Rôle | Prix pour tester |
|---|---|---|
| Un VPS Linux avec Docker (2 Go de RAM suffisent) | Héberge l'agent | Celui que tu as déjà |
| Un nom de domaine | Sous-domaine du type voice.tondomaine.com | Celui que tu as déjà |
| n8n (sur le même VPS, c'est l'idéal) | Agenda + mails | Gratuit en self-hosted |
| Deepgram | Les oreilles (transcription) | Crédit offert à l'inscription |
| Cartesia | La voix | Gratuit jusqu'à 20 000 caractères/mois |
| Google AI Studio (Gemini) ou Anthropic (Claude Haiku) | Le cerveau | Gemini : quota gratuit |
| Un compte Google | Agenda + Gmail | Gratuit |
| Twilio (facultatif) | Un vrai numéro de téléphone | Payant dès que tu veux ton propre numéro |
⚠️ Piège : Mistral. Les clés API Mistral demandent maintenant un plan payant. Prends Gemini pour tester, ou Claude Haiku si tu veux le plus fiable sur la prise de RDV.
1. Récupère tes clés
- Deepgram → API Keys → Create a New API Key.
- Cartesia → API Keys → crée une clé. Puis va dans Voices, filtre French, choisis une voix et copie son ID (tu en auras besoin à l'étape 4).
- Gemini → aistudio.google.com/apikey → Create API key. (ou une clé Anthropic si tu préfères Claude)
- Garde-les dans un gestionnaire de mots de passe. Ne les colle jamais dans un chat ou une capture.
2. Fais pointer ton sous-domaine vers le VPS
Chez ton registrar, ajoute un enregistrement A : voice → l'IP de ton VPS. Vérifie qu'il répond avant d'aller plus loin :
dig +short voice.tondomaine.com
⚠️ Piège : DNS avant HTTPS. Si le domaine ne pointe pas encore sur le VPS, le certificat HTTPS échoue et tu prends une erreur 502. Attends que dig renvoie la bonne IP.
3. Dépose le code sur le VPS
Sur le VPS :
cd /opt && git clone https://github.com/NautyZ-coder/agent-vocal-ia.git agent-vocal && cd agent-vocal
💡 Astuce : pour récupérer une nouvelle version plus tard,cd /opt/agent-vocal && git pullpuis relance. Tonserver/.envn'est pas suivi par git, il reste en place.
4. Lance l'assistant de configuration
bash server/configure.sh
Il te demande, dans l'ordre : ton métier (g = garage, d = cabinet dentaire), ton sous-domaine, les clés Deepgram et Cartesia, l'ID de la voix, le modèle (g = Gemini, c = Claude), l'e-mail qui recevra les RDV, l'URL de ton n8n, et Twilio (Entrée pour passer).
À la fin, il affiche deux choses à noter :
- 🔑 le secret à coller dans n8n (étape 6)
- 📞 le lien de ta page d'appel (étape 9)
💡 Pas encore de n8n prêt ? Appuie sur Entrée à la question de l'URL : l'agent tourne avec un agenda simulé. Tu relanceras l'assistant plus tard.
5. Démarre l'agent (HTTPS compris)
Deux cas, choisis le tien :
Cas A : rien ne tourne sur les ports 80/443 (VPS neuf). Caddy est inclus et gère le certificat tout seul.
docker compose --profile caddy up -d --build
Cas B : tu as déjà un reverse proxy dans Docker (Caddy, Traefik, Nginx Proxy Manager…). Trouve le nom du réseau Docker de ton proxy avec docker network ls, ajoute-le dans server/.env (PROXY_NETWORK=nom_du_reseau), puis :
docker compose --env-file server/.env -f docker-compose.yml -f docker-compose.proxy.yml up -d --build
Ensuite, dans ton proxy, route voice.tondomaine.com vers voice-agent:8765. Exemple avec Caddy :
voice.tondomaine.com {
reverse_proxy voice-agent:8765
}
⚠️ Piège : Caddy. Valide toujours avant de recharger, sinon une faute de frappe coupe tous tes sites :docker exec caddy caddy validate --config /etc/caddy/Caddyfile && docker exec caddy caddy reload --config /etc/caddy/Caddyfile
Test : https://voice.tondomaine.com/health doit afficher {"ok":true,...}.
💡 L'agent est plafonné à 1 Go de RAM et 1 CPU dans le docker-compose.yml, pour ne jamais faire tomber le reste de ton VPS (n8n, base de données…).
6. Branche n8n (agenda + mails)
a. Importe les 2 workflows du dossier n8n/ : Workflows → Import from File → agent-vocal-agenda.json, puis agent-vocal-notifications.json.
b. Crée le credential de sécurité : Credentials → New → Header Auth.
- Name :
X-Voice-Secret - Value : le secret affiché par l'assistant à l'étape 4
Sélectionne ce même credential dans tous les nœuds Webhook des 2 workflows.
🚨 Le piège n°1 (erreur 403). Le champ Name n'est pas le nom de ton credential : c'est le nom de l'en-tête HTTP. Il doit être exactementX-Voice-Secret. Crée un seul credential et réutilise-le partout. Si tu changes le secret, change-le aux deux endroits (n8n etserver/.env).
c. Connecte Google (une seule fois, sert pour l'agenda et Gmail) :
- console.cloud.google.com → crée un projet.
- APIs & Services → Library → active Google Calendar API et Gmail API.
- OAuth consent screen → type External → ajoute ton adresse Gmail dans Test users.
- Credentials → Create credentials → OAuth client ID → Web application. Dans Authorized redirect URIs, colle l'URL de redirection que n8n t'affiche (du type
https://n8n.tondomaine.com/rest/oauth2-credential/callback). - Dans n8n, crée un credential Google Calendar OAuth2 API et un Gmail OAuth2 API avec le même Client ID / Client Secret, puis clique « Sign in with Google ».
- Sélectionne-les dans les nœuds Google Agenda (HTTP Request) et Gmail.
d. Indique ton agenda : dans le workflow agent-vocal-agenda, ouvre les 2 nœuds Code (« Préparer la recherche » et « Préparer l'événement + SMS »). En haut, le bloc GARAGES contient une entrée par client. Dans l'entrée de ton métier (garage-demo ou dentiste-demo), mets calendarId : primary pour ton agenda principal, ou l'ID d'un agenda dédié (Google Agenda → paramètres de l'agenda → « Intégrer l'agenda »). Fais la même modification dans les 2 nœuds.
⚠️ Piège cabinet dentaire. L'entréedentiste-democontient un faux ID (ID_AGENDA_CABINET@group.calendar.google.com). Tant que tu ne le remplaces pas, l'agent ne peut ni lire ni écrire les RDV. Conseil : crée un agenda dédié au garage ou au cabinet.
e. Active les 2 workflows (bouton en haut à droite).
💡 Si n8n et l'agent sont sur le même réseau Docker, tu peux mettreN8N_WEBHOOK_BASE=http://n8n:5678/webhookdansserver/.env: plus rapide, et ça ne passe pas par Internet.
💡 Le nœud SMS est désactivé par défaut : envoyer des SMS demande un numéro Twilio payant. L'e-mail suffit pour commencer.
7. Configure ton garage ou ton cabinet
Tout se passe dans un seul fichier, celui de ton métier : server/tenants/garage-demo.yaml ou server/tenants/dentiste-demo.yaml. Les champs importants :
name,address,timezone(ex.Europe/Paris)profile: le métier. Absent = garage,dentiste= cabinet dentaire. C'est lui qui choisit le script de l'agent (questions posées, règles médicales).agent: prénom, voix (voice_id), phrase d'accueil et phrase d'au revoir (goodbye). Accorde le prénom avec la voix (voix d'homme → prénom masculin).opening_hours,booking.capacity(nombre de ponts au garage, de fauteuils au cabinet),services(avec la durée de chaque RDV)faq: ce que l'agent peut répondre. Il n'invente rien en dehors.transfer_number: un numéro pour passer la main à un humain (vide = il prend un message et propose d'être rappelé)
Puis :
docker compose restart voice-agent
Garage ou cabinet dentaire : ce qui change
Garage (garage-demo) | Cabinet dentaire (dentiste-demo) | |
|---|---|---|
| Ce que l'agent demande | Nom, véhicule, immatriculation, problème | Nom, motif, déjà patient ou non |
| Types de RDV (durée) | Entretien 60 min, vidange 30, pneus 45, freinage 90, diagnostic 60, climatisation 45, autre 60 | Urgence 30 min, contrôle 30, détartrage 30, nouveau patient 45, soin 60, devis 30, autre 30 |
| RDV en parallèle | 2 (ponts) | 1 (fauteuil) |
| Délai minimum / horizon | 3 h / 21 jours | 1 h / 30 jours |
| Règles spéciales | Aucune | Jamais de conseil médical, urgences en priorité, renvoi vers le 15 si urgence grave (gonflement qui gêne pour respirer, saignement qui ne s'arrête pas…) |
Tous ces réglages se changent dans le YAML. Les 2 workflows n8n servent aux deux métiers, sans modification autre que l'agenda.
8. Vérifie toute la chaîne
docker exec -i voice-agent python - < server/check.py
Neuf vérifications : config, clés, appel d'outil par l'IA, transcription, voix, lecture et écriture dans l'agenda via n8n, Twilio. Tout doit être vert avant de passer un appel. Chaque ligne rouge te dit quoi corriger.
💡 Les tests du check utilisent des exemples de garage (une vidange, « Garage Démo Auto »), même en mode cabinet dentaire. C'est normal : ils vérifient que la chaîne fonctionne, pas le métier. Le métier se teste à l'étape 9.
9. Passe ton premier appel
Sans numéro (gratuit) : ouvre le lien de ta page d'appel (https://voice.tondomaine.com/appel?g=garage-demo&code=..., ou g=dentiste-demo pour le cabinet) et appuie sur le bouton vert.
⚠️ Piège iPhone. Ouvre la page dans Safari. Si tu l'ajoutes à l'écran d'accueil et que tu la lances depuis l'icône, le micro reste muet.
Petit scénario de test, garage : demande une vidange « demain à 7h » (il doit refuser et proposer de vraies heures), choisis un créneau, donne ton e-mail, dis « oui » au récap, puis « non merci, c'est tout ».
Cabinet dentaire : dis « j'ai très mal à une dent depuis hier » (il doit proposer un créneau d'urgence sans donner de conseil médical), puis demande « je peux prendre un anti-inflammatoire ? » (il doit refuser de conseiller un traitement et renvoyer vers le docteur au RDV, ou vers le pharmacien en attendant). Va jusqu'au « oui » du récap.
Vérifie ensuite ton agenda et ta boîte mail.
Avec un vrai numéro (Twilio) : relance bash server/configure.sh pour ajouter l'Account SID et l'Auth Token, puis sur ton numéro Twilio → Voice → A call comes in → Webhook https://voice.tondomaine.com/twilio/voice (POST). Ajoute ce numéro dans phone_numbers du fichier YAML de ton client : c'est ce numéro qui dit à l'agent s'il répond pour le garage ou pour le cabinet. Le client n'a plus qu'à renvoyer sa ligne vers ce numéro (en cas de non-réponse, par exemple).
💡 Un compte Twilio d'essai, sans crédit, ne peut pas acheter de numéro et ajoute un message d'avertissement en début d'appel. Pour une démo, la page web fait le même travail.
10. Suis les appels en direct
docker compose logs -f voice-agent | grep -E --line-buffered "CLIENT :|AGENT :|ERROR|WARNING"
Tu vois chaque phrase du client et de l'agent. Ctrl+C pour sortir.
🔁 Au quotidien
- Modifier le garage ou le cabinet (horaires, FAQ, accueil) → édite le YAML, puis
docker compose restart voice-agent - Ajouter un client → copie le YAML de son métier (
garage-demo.yamloudentiste-demo.yaml) en<id-client>.yaml, changeid,name, l'accueil etphone_numbers. Dans n8n, ajoute l'entrée<id-client>(avec soncalendarId) dans le blocGARAGESdes nœuds Code des 2 workflows. Puis redémarre et teste avec/appel?g=<id-client>&code=... - Changer de modèle ou de métier par défaut → relance
bash server/configure.sh, puisdocker compose up -d(avec les mêmes options qu'à l'étape 5) : un simple restart ne relit passerver/.env - Après une mise à jour du code →
docker compose up -d --build(avec les mêmes options qu'à l'étape 5), puis relance le check
🛠️ Ça ne marche pas ?
Erreur 502 sur le sous-domaine
Le proxy ne joint pas l'agent. Vérifie que le conteneur tourne (docker ps), que le DNS pointe bien sur le VPS, et en cas B que l'agent est sur le même réseau Docker que ton proxy (docker network inspect nom_du_reseau).
n8n répond 403
Le secret ne correspond pas. Vérifie que le Name du credential Header Auth est exactement X-Voice-Secret, que la Value est identique à N8N_WEBHOOK_SECRET dans server/.env, et que tous les nœuds Webhook utilisent ce même credential.
n8n répond 404
Les workflows ne sont pas activés, ou N8N_WEBHOOK_BASE ne se termine pas par /webhook.
L'agent ne propose jamais de créneau / erreur d'outil avec Gemini
Garde LLM_PROVIDER=google. L'ancienne méthode « compatible OpenAI » de Gemini casse les appels d'outils (erreur « Name cannot be empty »). Le code utilise l'API native de Google.
Le RDV n'arrive pas dans le bon agenda / à la mauvaise heure
Vérifie calendarId dans le bloc GARAGES des 2 nœuds Code du workflow agenda, et timezone dans le YAML. Une erreur « Garage inconnu » dans n8n veut dire que l'id du YAML n'a pas d'entrée dans ce bloc.
Pas de mail de confirmation
Le workflow agent-vocal-notifications est-il importé et activé ? Le credential Gmail est-il connecté ? Le client a-t-il donné un e-mail valide ? (les logs montrent l'adresse comprise). Pense aux spams.
Le son coupe ou arrive par morceaux
Souvent un Wi-Fi faible. Teste en 4G ou rapproche-toi de la box.
💶 Combien ça coûte
Environ 0,04 $ la minute en production (transcription + IA + voix), plus le numéro de téléphone si tu en prends un. Pour tester : quasiment gratuit avec les offres de Deepgram, Cartesia et Gemini. Un appel de RDV dure 2 à 3 minutes.
⚖️ Côté légal
- AI Act, article 50 : la personne doit savoir qu'elle parle à une IA. L'accueil le dit dès la première phrase, ne l'enlève pas.
- RGPD : l'agent collecte des données personnelles (nom, téléphone, e-mail, immatriculation). Mentionne-le dans la politique de confidentialité du garage ou du cabinet, ne garde que ce qui sert au RDV, et ne mets pas de clés ni de données clients dans un dépôt public.
- Cabinet dentaire : le motif du RDV (douleur, soin…) est une donnée de santé, protégée plus strictement par le RGPD (article 9). En France, héberger des données de santé pour le compte d'un professionnel peut exiger un hébergeur certifié HDS : vérifie-le avec ton client avant la mise en production.
- Si tu le revends : le garage ou le cabinet reste responsable de ses données, toi de l'hébergement. Écris-le dans ton contrat.