Ce guide couvre le déploiement complet d'un agent IA vocal de réception d'appel pour une entreprise du secteur bâtiment. Il est valable pour le tier Cloud/VPS standard.
Stack technique : - Téléphonie : Twilio (numéro dédié + webhooks) - Transcription voix → texte (STT) : Deepgram (temps réel, français) - Intelligence / réponse (LLM) : OpenAI GPT-4o-mini (rapide, économique) - Synthèse texte → voix (TTS) : ElevenLabs ou Twilio TTS natif - Orchestration : serveur Node.js/Python sur VPS (ex: OVH VPS Starter 3,99€/mo) - Calendrier : Google Calendar API (prise de RDV en temps réel) - Notifications : Twilio SMS + SendGrid email
https://[votre-vps]/incoming-call# Connexion SSH
ssh ubuntu@[IP_VPS]
# Mise à jour système
sudo apt update && sudo apt upgrade -y
# Installation Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# Installation PM2 (gestionnaire de processus)
sudo npm install -g pm2
# Installation Nginx (reverse proxy)
sudo apt install -y nginx certbot python3-certbot-nginx
# Création du dossier projet
mkdir -p /var/www/agent-ia
cd /var/www/agent-ia
npm init -y
npm install express twilio openai @deepgram/sdk dotenv axios
Créer le fichier /var/www/agent-ia/.env :
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_PHONE_NUMBER=+33XXXXXXXXX
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
DEEPGRAM_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ELEVENLABS_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
GOOGLE_CALENDAR_ID=xxxxxxxx@group.calendar.google.com
GOOGLE_SERVICE_ACCOUNT_JSON=/var/www/agent-ia/credentials.json
CLIENT_COMPANY_NAME=ITM Agency
CLIENT_AGENT_NAME=Alex
CLIENT_AGENT_VOICE_ID=xxxxxxxx # ID voix ElevenLabs
server.jsconst express = require('express');
const twilio = require('twilio');
const { OpenAI } = require('openai');
require('dotenv').config();
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const VoiceResponse = twilio.twiml.VoiceResponse;
// Prompt système de l'agent
const SYSTEM_PROMPT = `Tu es Alex, l'assistant vocal de ${process.env.CLIENT_COMPANY_NAME}, une entreprise du secteur bâtiment.
Tu réponds uniquement en français, de manière professionnelle et chaleureuse.
Tes missions :
1. Accueillir l'appelant chaleureusement
2. Identifier l'objet de l'appel (devis, urgence, information, RDV)
3. Si RDV : proposer un créneau disponible via le calendrier
4. Si urgence : noter les coordonnées et transmettre immédiatement
5. Si devis : collecter les informations (type de travaux, adresse, surface)
6. ClĂ´turer poliment et confirmer les actions prises
Tu ne dois JAMAIS inventer d'informations sur les prix ou délais. Si tu ne sais pas, tu promets un rappel.`;
// Réception d'un appel entrant
app.post('/incoming-call', (req, res) => {
const twiml = new VoiceResponse();
// Message d'accueil initial
const gather = twiml.gather({
input: 'speech',
language: 'fr-FR',
speechTimeout: 'auto',
action: '/process-speech',
method: 'POST'
});
gather.say({
voice: 'Polly.Lea', // Voix française AWS Polly via Twilio
language: 'fr-FR'
}, `Bonjour, vous ĂŞtes bien chez ${process.env.CLIENT_COMPANY_NAME}. Je suis ${process.env.CLIENT_AGENT_NAME}, votre assistant. Comment puis-je vous aider aujourd'hui ?`);
res.type('text/xml');
res.send(twiml.toString());
});
// Traitement de la parole
app.post('/process-speech', async (req, res) => {
const userSpeech = req.body.SpeechResult;
const callSid = req.body.CallSid;
const twiml = new VoiceResponse();
if (!userSpeech) {
twiml.say({ voice: 'Polly.Lea', language: 'fr-FR' },
"Je n'ai pas entendu votre réponse. Pouvez-vous répéter ?");
res.type('text/xml');
return res.send(twiml.toString());
}
try {
// Appel GPT-4o-mini
const completion = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [
{ role: 'system', content: SYSTEM_PROMPT },
{ role: 'user', content: userSpeech }
],
max_tokens: 150,
temperature: 0.7
});
const agentResponse = completion.choices[0].message.content;
// Réponse vocale + écoute suivante
const gather = twiml.gather({
input: 'speech',
language: 'fr-FR',
speechTimeout: 'auto',
action: '/process-speech',
method: 'POST'
});
gather.say({ voice: 'Polly.Lea', language: 'fr-FR' }, agentResponse);
} catch (error) {
console.error('Erreur LLM:', error);
twiml.say({ voice: 'Polly.Lea', language: 'fr-FR' },
"Je rencontre une difficulté technique. Veuillez rappeler dans quelques instants.");
}
res.type('text/xml');
res.send(twiml.toString());
});
app.listen(3000, () => console.log('Agent IA démarré sur le port 3000'));
cd /var/www/agent-ia
pm2 start server.js --name "agent-ia"
pm2 save
pm2 startup # Pour redémarrage auto
server {
server_name agent.[domaine-client].fr;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
sudo certbot --nginx -d agent.[domaine-client].fr
Retourner dans la console Twilio et mettre Ă jour le webhook :
https://agent.[domaine-client].fr/incoming-call
credentials.json dans /var/www/agent-ia/nom@projet.iam.gserviceaccount.com)calendar.jsconst { google } = require('googleapis');
const credentials = require('./credentials.json');
const auth = new google.auth.GoogleAuth({
credentials,
scopes: ['https://www.googleapis.com/auth/calendar']
});
async function getAvailableSlots(date) {
const calendar = google.calendar({ version: 'v3', auth });
const startOfDay = new Date(date);
startOfDay.setHours(8, 0, 0);
const endOfDay = new Date(date);
endOfDay.setHours(18, 0, 0);
const events = await calendar.events.list({
calendarId: process.env.GOOGLE_CALENDAR_ID,
timeMin: startOfDay.toISOString(),
timeMax: endOfDay.toISOString(),
singleEvents: true,
orderBy: 'startTime'
});
return events.data.items;
}
async function createAppointment(summary, start, end, attendeeEmail) {
const calendar = google.calendar({ version: 'v3', auth });
await calendar.events.insert({
calendarId: process.env.GOOGLE_CALENDAR_ID,
resource: {
summary,
start: { dateTime: start, timeZone: 'Europe/Paris' },
end: { dateTime: end, timeZone: 'Europe/Paris' },
attendees: [{ email: attendeeEmail }]
}
});
}
module.exports = { getAvailableSlots, createAppointment };
notify.jsconst twilio = require('twilio');
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);
async function sendCallSummary(toNumber, callerNumber, summary) {
await client.messages.create({
body: `📞 Appel reçu de ${callerNumber}\n\nRésumé : ${summary}\n\n— Agent IA ITM Agency`,
from: process.env.TWILIO_PHONE_NUMBER,
to: toNumber // Numéro du gérant de l'entreprise cliente
});
}
module.exports = { sendCallSummary };
À chaque appel terminé, l'agent envoie les données vers l'API ITM Agency pour loguer dans la base AppelLog :
async function logCall(data) {
await axios.post('https://api.base44.app/apps/[APP_ID]/entities/AppelLog', {
client_id: data.clientId,
client_nom: data.clientNom,
date_appel: new Date().toISOString(),
duree_secondes: data.duree,
numero_appelant: data.callerNumber,
type_demande: data.typedemande, // devis / urgence / rdv / info
statut_appel: 'traité',
rdv_pris: data.rdvPris,
transcription_resume: data.resume,
sentiment: data.sentiment // positif / neutre / négatif
}, {
headers: { 'Authorization': 'Bearer [API_KEY]' }
});
}
□ Compte Twilio créé et vérifié
□ Numéro français acheté
□ VPS commandé et accessible en SSH
□ Node.js + PM2 + Nginx installés
□ Variables d'environnement configurées (.env)
□ server.js déployé et démarré (pm2 start)
â–ˇ Certificat SSL actif (HTTPS)
□ Webhook Twilio pointé vers le VPS
□ Google Calendar connecté (compte de service)
□ Test appel entrant validé
□ SMS de notification post-appel reçu
â–ˇ Log appel visible dans le dashboard ITM
□ Script d'accueil personnalisé pour le client
□ Voix de l'agent sélectionnée et testée
| Poste | Coût estimé |
|---|---|
| Numéro Twilio | ~1€/mois |
| Appels Twilio (0,013$/min) | ~5-15€ selon volume |
| VPS OVH Starter | 3,99€/mois |
| OpenAI GPT-4o-mini | ~2-8€ selon volume |
| Deepgram STT | ~1-5€ selon volume |
| ElevenLabs TTS | ~2-5€ selon volume |
| Total estimé | ~15-37€/mois |
| Abonnement client | 149-249€/mois |
| Marge brute | >75% âś… |
Seuls ces éléments changent d'un client à l'autre :
- CLIENT_COMPANY_NAME → nom de l'entreprise
- CLIENT_AGENT_NAME → prénom de l'agent IA
- CLIENT_AGENT_VOICE_ID → voix choisie
- SYSTEM_PROMPT → script d'accueil + services spécifiques
- GOOGLE_CALENDAR_ID → calendrier du client
- TWILIO_PHONE_NUMBER → numéro dédié du client
Temps de déploiement estimé pour un nouveau client : 45 minutes
ITM Agency — Guide Technique v1.0 — Mai 2026 Document interne — Non destiné à la diffusion client