WinDev 2026 : agents IA CRM
En résumé
- Un agent IA dans un CRM WinDev doit être branché sur des actions métier limitées, pas sur toute l'application.
- L'approche sans champ Chat garde une interface CRM classique : boutons, fiches, workflows et validations utilisateur.
- La journalisation, les droits et la séparation lecture-écriture restent indispensables dès que l'IA agit sur des données client.
Introduction
Dans un CRM, l’IA devient intéressante quand elle évite à l’utilisateur de relire quinze notes commerciales, trois mails copiés-collés et deux comptes rendus de rendez-vous pour savoir quoi faire ensuite.
Pas quand elle ajoute une zone de discussion de plus dans l’écran.
WinDev 2026 met davantage l’IA dans l’environnement et dans les applications. La documentation PC SOFT autour des agents et du compagnon IA montre une direction assez claire : l’IA n’est plus seulement une réponse textuelle, elle peut aider à raisonner sur un contexte et à déclencher des actions encadrées. PC SOFT met aussi en avant l’utilisation de modèles comme Claude, Mistral, GPT, Gemini ou OpenRouter via un compte API. ( pcsoft.fr )
Dans cet article, je prends volontairement un angle précis : un CRM WinDev 2026 avec des agents IA, mais sans exemple basé sur le champ Chat.
L’interface reste celle d’un CRM classique :
- une fiche client,
- un historique,
- des opportunités,
- des relances,
- des boutons d’action,
- des validations utilisateur.
L’agent IA travaille derrière. Il lit un contexte limité, produit une proposition structurée, puis l’application décide ce qui peut être affiché, enregistré ou refusé.
C’est moins spectaculaire qu’une grande fenêtre conversationnelle. Mais sur un outil métier utilisé tous les jours, c’est souvent plus utile.
Pourquoi éviter le réflexe du champ Chat dans un CRM
Le champ Chat IA a sa place. Pour un support interne, une recherche documentaire ou une interface exploratoire, il peut rendre service.
Dans un CRM, je suis plus réservé.
Un commercial ne veut pas forcément “discuter avec le CRM”. Il veut savoir :
- quel client rappeler ce matin,
- pourquoi une opportunité est bloquée,
- quelle relance envoyer,
- quels comptes n’ont pas été vus depuis trop longtemps,
- quels signaux faibles méritent une action.
Le risque du chat dans ce contexte, c’est de créer une interface parallèle. On sort de la fiche client, on reformule ce que l’écran sait déjà, puis on recopie une réponse dans une note. Au bout de quelques jours, l’usage baisse.
Une approche par agent métier est différente. L’utilisateur clique sur Préparer la relance, Analyser le compte, Résumer l’historique, Proposer une prochaine action. L’IA est appelée dans un traitement précis, avec un format attendu.
Le CRM garde la main.
Architecture cible sans champ Chat
Dans une application WinDev existante, je sépare généralement l’intégration IA en quatre couches.
Une couche CRM : fichiers HFSQL, PostgreSQL ou SQL Server, fenêtres, droits utilisateur, règles métier.
Une couche contexte IA : extraction contrôlée des données utiles. Pas toute la base. Pas tout l’historique. Juste le nécessaire.
Une couche agent : prompt système, modèle, outils autorisés, format de sortie.
Une couche validation : affichage de la proposition, contrôle des droits, écriture éventuelle, journalisation.
Le schéma ressemble à ça :
Fenêtre CRM WinDev
|
| bouton "Préparer une relance"
v
Procédure WLangage
|
| construit un contexte limité
v
Service Agent IA
|
| appelle le modèle + outils autorisés
v
Réponse JSON structurée
|
| contrôles métier WinDev
v
Proposition affichée à l'utilisateur
|
| validation humaine
v
Écriture CRM + journal IA
On peut héberger le service agent de plusieurs façons :
- directement dans une collection de procédures WinDev si le besoin reste simple ;
- via un microservice HTTP en Node.js, Python ou .NET ;
- dans un conteneur Docker interne si l’entreprise veut isoler les clés API et la supervision ;
- avec un modèle local si les données CRM ne doivent pas sortir.
Sur un CRM PME, je préfère souvent démarrer avec un petit service HTTP. Il évite de stocker les clés IA dans le poste client. Il permet aussi de tracer les appels et de limiter la consommation.
Exemple métier : préparer une relance client
Prenons une fiche client classique.
On dispose de :
- l’identité du client ;
- les trois dernières interactions ;
- les devis ouverts ;
- les factures échues ;
- la prochaine échéance commerciale ;
- le statut du compte.
L’utilisateur clique sur Préparer une relance.
L’agent ne doit pas envoyer l’email. Il doit proposer :
- un motif de relance ;
- un niveau de priorité ;
- un texte court ;
- une action CRM suggérée ;
- un niveau de confiance.
Le format attendu peut être très strict :
{
"priorite": "haute",
"motif": "Devis ouvert depuis 18 jours avec dernier échange positif",
"action_suggeree": "appel",
"message_propose": "Bonjour, je reviens vers vous concernant le devis...",
"niveau_confiance": 0.82,
"points_a_verifier": [
"Vérifier si le client a déjà reçu la version corrigée du devis",
"Confirmer la disponibilité annoncée en réunion"
]
}
Ce JSON est important. Une réponse libre est pénible à exploiter dans WinDev. Une réponse structurée permet de remplir une fenêtre interne, de colorer la priorité, de forcer une validation et de refuser une sortie incorrecte.
Extraction du contexte côté WinDev
L’erreur classique consiste à envoyer toute la fiche client au modèle.
C’est rarement nécessaire. Et dans un CRM, ça augmente le coût, le bruit et le risque de fuite de données.
Une procédure WLangage peut construire un contexte court :
PROCÉDURE CRMConstruitContexteRelance(nIdClient est un entier) : chaîne
sContexte est une chaîne
SI PAS HLitRecherchePremier(Client, IDClient, nIdClient) ALORS
RENVOYER ""
FIN
sContexte += "Client: " + Client.Nom + RC
sContexte += "Secteur: " + Client.SecteurActivite + RC
sContexte += "Statut: " + Client.StatutCommercial + RC
sContexte += "Commercial: " + Client.CodeCommercial + RC
sContexte += RC + "Dernières interactions:" + RC
POUR TOUT Interaction AVEC IDClient = nIdClient
SI Interaction.DateInteraction >= DateSys() - 180 ALORS
sContexte += DateVersChaîne(Interaction.DateInteraction, "AAAA-MM-JJ")
sContexte += " - " + Interaction.TypeInteraction
sContexte += " - " + Gauche(Interaction.Commentaire, 600) + RC
FIN
FIN
sContexte += RC + "Devis ouverts:" + RC
POUR TOUT Devis AVEC IDClient = nIdClient
SI Devis.Statut = "OUVERT" ALORS
sContexte += Devis.Numero + " - "
sContexte += NumériqueVersChaîne(Devis.MontantHT, "10.2f") + " EUR - "
sContexte += "créé le " + DateVersChaîne(Devis.DateCreation, "AAAA-MM-JJ") + RC
FIN
FIN
RENVOYER sContexte
Je limite volontairement les commentaires à 600 caractères. Dans une vraie application, j’ajoute souvent un nettoyage plus sérieux : suppression des signatures mail, retrait des pièces jointes copiées dans les notes, masquage de certaines données personnelles.
Le modèle n’a pas besoin du numéro de mobile personnel du dirigeant pour proposer une relance.
Appel à un service agent depuis WinDev
Un service HTTP interne peut exposer une route simple :
POST /agents/crm/relance
Depuis WinDev :
PROCÉDURE AgentCRMPrepareRelance(nIdClient est un entier)
sContexte est une chaîne = CRMConstruitContexteRelance(nIdClient)
SI sContexte = "" ALORS
Info("Impossible de construire le contexte client.")
RETOUR
FIN
sJSONRequete est une chaîne = [
{
"id_client": %1,
"objectif": "preparer_relance_commerciale",
"contexte": %2,
"format_reponse": "json"
}
]
sJSONRequete = ChaîneConstruit(sJSONRequete, nIdClient, ChaîneVersJSON(sContexte))
req est un httpRequête
req.URL = "https://ia-interne.exemple.local/agents/crm/relance"
req.Méthode = httpPost
req.ContentType = "application/json"
req.Contenu = sJSONRequete
rep est un httpRéponse = HTTPEnvoie(req)
SI ErreurDétectée ALORS
Erreur("Erreur lors de l'appel au service IA.", ErreurInfo())
RETOUR
FIN
SI rep.CodeEtat <> 200 ALORS
Erreur("Le service IA a retourné une erreur : " + rep.CodeEtat)
RETOUR
FIN
CRMChargePropositionRelance(rep.Contenu)
Le code exact varie selon les conventions du projet. L’idée reste la même : WinDev appelle un service borné, pas directement un modèle depuis dix fenêtres différentes.
C’est plus facile à maintenir. Plus facile à couper aussi, le jour où le fournisseur IA change ses tarifs ou son API.
Le service agent : prompt court, outils limités
Côté service, l’agent ne reçoit pas un accès complet au CRM. Il reçoit un objectif et un contexte déjà préparé.
Exemple de consigne système :
Tu es un assistant CRM pour une équipe commerciale B2B.
Tu aides à préparer une relance client.
Tu ne dois pas inventer de faits absents du contexte.
Tu ne dois pas promettre une remise, un délai ou une condition commerciale.
Tu dois produire uniquement un JSON valide.
Tu dois signaler les informations à vérifier si le contexte est incomplet.
La sortie attendue est validée par schéma :
{
"type": "object",
"required": [
"priorite",
"motif",
"action_suggeree",
"message_propose",
"niveau_confiance",
"points_a_verifier"
],
"properties": {
"priorite": {
"type": "string",
"enum": ["basse", "normale", "haute"]
},
"action_suggeree": {
"type": "string",
"enum": ["appel", "email", "rdv", "ne_pas_relancer"]
},
"niveau_confiance": {
"type": "number",
"minimum": 0,
"maximum": 1
}
}
}
Dans un projet réel, je refuse toute réponse qui ne respecte pas ce format. Pas de correction silencieuse. Pas de “on va essayer de parser quand même”.
Les applications LLM exposent des risques spécifiques comme l’injection de prompt, la fuite d’informations sensibles, la mauvaise gestion des sorties et l’excès d’autonomie accordé au modèle. L’OWASP les documente dans son Top 10 dédié aux applications LLM, avec la prompt injection en risque majeur. ( OWASP )
Validation dans l’écran CRM
La proposition IA ne doit pas s’écrire directement dans l’historique.
Je préfère afficher une fenêtre de validation :
Relance proposée par l'IA
Priorité : Haute
Action : Appel
Motif : Devis ouvert depuis 18 jours, dernier échange positif
Message proposé :
Bonjour M. Durand,
je reviens vers vous concernant le devis DV-2026-0142...
Points à vérifier :
- Le client a-t-il reçu la version corrigée ?
- La disponibilité annoncée est-elle toujours valable ?
[Modifier] [Créer la relance] [Ignorer]
Si l’utilisateur clique sur Créer la relance, l’application écrit une tâche CRM normale :
PROCÉDURE CRMValideRelanceIA(nIdClient est un entier, stRelanceIA est une ST_RelanceIA)
SI PAS UtilisateurPeutCréerRelance(nIdClient) ALORS
Erreur("Vous n'avez pas les droits pour créer une relance sur ce client.")
RETOUR
FIN
Relance.IDClient = nIdClient
Relance.DateCréation = DateSys()
Relance.HeureCréation = HeureSys()
Relance.TypeRelance = stRelanceIA.ActionSuggeree
Relance.Priorité = stRelanceIA.Priorite
Relance.Commentaire = stRelanceIA.MessagePropose
Relance.Source = "IA_VALIDEE"
Relance.IDUtilisateur = gnUtilisateurConnecte
HAjoute(Relance)
JournalIA.IDClient = nIdClient
JournalIA.IDUtilisateur = gnUtilisateurConnecte
JournalIA.Action = "RELANCE_CREEE"
JournalIA.ScoreConfiance = stRelanceIA.NiveauConfiance
JournalIA.DateHeure = DateHeureSys()
JournalIA.RéponseJSON = stRelanceIA.JSONBrut
HAjoute(JournalIA)
Deux champs comptent beaucoup : Source = "IA_VALIDEE" et JournalIA.
Quand un utilisateur demande trois semaines plus tard pourquoi une relance a été créée, il faut pouvoir répondre. “C’est l’IA” n’est pas une réponse acceptable.
Structurer les données de journalisation
Je crée en général un fichier dédié.
JOURNAL_IA
- IDJournalIA
- DateHeure
- IDUtilisateur
- IDClient
- TypeAgent
- Objectif
- FournisseurModele
- Modele
- NbTokensEntree
- NbTokensSortie
- ScoreConfiance
- Statut
- MessageErreur
- ReponseJSON
- HashContexte
Je n’enregistre pas forcément tout le prompt complet. Cela dépend du contexte RGPD, du volume et de la sensibilité des données.
Le HashContexte permet de prouver que le contexte n’a pas été modifié, sans stocker une copie complète de données client dans un journal technique. Pour certains clients, on garde aussi le contexte complet pendant quelques jours seulement, avec purge planifiée.
Sur Ubuntu 24.02, une purge simple peut être lancée par cron si le journal est stocké côté service :
#!/usr/bin/env bash
set -euo pipefail
DB_NAME="crm_ai"
DB_USER="crm_ai"
RETENTION_DAYS=30
psql "postgresql://${DB_USER}@localhost/${DB_NAME}" <<SQL
DELETE FROM journal_ia
WHERE date_heure < NOW() - INTERVAL '${RETENTION_DAYS} days'
AND statut IN ('OK', 'REFUSE');
SQL
Ce n’est pas glorieux. Mais ce genre de tâche évite des journaux IA qui grossissent pendant deux ans sans que personne ne les regarde.
Utiliser des Docker secrets pour la clé API
Si le service agent tourne dans Docker, la clé API ne doit pas être dans le docker-compose.yml.
Exemple avec Docker secrets :
services:
crm-agent:
image: registry.local/crm-agent:1.0.0
container_name: crm-agent
restart: unless-stopped
environment:
AI_PROVIDER: "openai"
AI_MODEL: "gpt-4.1-mini"
AI_API_KEY_FILE: "/run/secrets/ai_api_key"
CRM_AGENT_LOG_LEVEL: "info"
ports:
- "127.0.0.1:8088:8080"
secrets:
- ai_api_key
secrets:
ai_api_key:
file: ./secrets/ai_api_key
Création du secret local :
mkdir -p secrets
printf '%s' 'sk-xxxxxxxxxxxxxxxx' > secrets/ai_api_key
chmod 600 secrets/ai_api_key
Le service lit ensuite le fichier :
import { readFileSync } from "node:fs";
const apiKeyFile = process.env.AI_API_KEY_FILE;
if (!apiKeyFile) {
throw new Error("AI_API_KEY_FILE manquant");
}
const apiKey = readFileSync(apiKeyFile, "utf8").trim();
if (!apiKey) {
throw new Error("Clé API IA vide");
}
Même sur une petite installation, ce détail change beaucoup de choses. La clé ne circule pas dans le code WinDev, ni dans un fichier INI partagé sur un lecteur réseau.
Cas d’usage utiles dans un CRM WinDev
Résumer l’historique client
C’est le cas le plus simple.
L’agent reçoit les interactions des 6 ou 12 derniers mois et produit une synthèse courte :
{
"resume": "Client actif, intéressé par l'offre maintenance, mais attente récurrente sur les délais de livraison.",
"risques": [
"Deux relances sans réponse depuis mars",
"Facture échue mentionnée dans le dernier échange"
],
"prochaine_action": "Appel court avant nouvelle proposition commerciale"
}
L’écran CRM affiche ce résumé en haut de fiche. Il peut être recalculé à la demande ou chaque nuit.
Attention à ne pas remplacer l’historique complet. La synthèse aide à reprendre le fil, elle ne devient pas la vérité officielle.
Qualifier une opportunité commerciale
Une opportunité peut être notée selon des critères internes :
- budget identifié ;
- décideur connu ;
- date cible ;
- concurrence ;
- urgence ;
- dernier contact.
Le modèle propose une qualification, mais le CRM applique les règles.
{
"maturite": "moyenne",
"score": 63,
"justification": "Budget évoqué mais non validé, décideur identifié, échéance encore floue.",
"questions_a_poser": [
"Le budget est-il validé pour ce trimestre ?",
"Qui signe la commande finale ?"
]
}
Je n’utiliserais pas ce score pour rémunérer un commercial ou arbitrer automatiquement un portefeuille. Pour préparer une revue d’opportunités, oui.
Détecter les comptes à risque
L’agent peut analyser des signaux faibles :
- baisse du nombre d’échanges ;
- tickets support plus fréquents ;
- devis non signés ;
- factures en retard ;
- changement d’interlocuteur ;
- commentaire négatif récent.
Là encore, on sépare lecture et décision. L’agent ne classe pas seul un client comme “à risque critique”. Il propose une alerte.
{
"niveau_risque": "modere",
"signaux": [
"Aucun contact commercial depuis 94 jours",
"Deux tickets support ouverts en moins de 30 jours",
"Dernier devis expiré sans retour"
],
"action_recommandee": "Planifier un appel de suivi avec le responsable de compte"
}
Sur un CRM de PME, ce cas parle vite aux équipes. Il fait ressortir des dossiers oubliés, sans imposer une nouvelle méthode commerciale.
Ne pas donner trop d’outils à l’agent
Un agent IA devient dangereux quand on lui donne trop de capacités trop vite.
Dans un CRM, je distingue trois niveaux.
Lecture seule :
- lire synthèse client
- lire opportunités ouvertes
- lire dernières interactions
- lire tickets récents
Préparation :
- proposer une relance
- rédiger un brouillon
- suggérer une qualification
- signaler des points à vérifier
Action contrôlée :
- créer une tâche après validation
- ajouter une note après validation
- préparer un email sans l'envoyer
- modifier un statut uniquement avec confirmation
Je commence presque toujours par lecture seule et préparation. Les actions contrôlées viennent après usage terrain, quand on voit comment les utilisateurs corrigent les propositions.
Il y a souvent des surprises. Des formulations trop longues. Des priorités mal comprises. Des historiques pollués par d’anciens imports. Mieux vaut le découvrir avant de brancher l’agent sur des écritures.
Exemple de table de paramétrage des agents
Plutôt que coder les comportements partout, on peut créer une table de paramétrage.
AGENT_PARAM
- CodeAgent
- Libelle
- Actif
- Modele
- Temperature
- MaxTokens
- RoleSysteme
- FormatSortie
- NiveauActionMax
- JournaliserContexte
Exemple :
CodeAgent: CRM_RELANCE
Libelle: Préparation relance client
Actif: Oui
Modele: gpt-4.1-mini
Temperature: 0.2
MaxTokens: 900
NiveauActionMax: PREPARATION
JournaliserContexte: Non
Dans WinDev, le traitement vérifie si l’agent est actif avant l’appel :
SI PAS HLitRecherchePremier(AgentParam, CodeAgent, "CRM_RELANCE") ALORS
Info("Agent CRM_RELANCE non paramétré.")
RETOUR
FIN
SI AgentParam.Actif = Faux ALORS
Info("Cet assistant IA est désactivé.")
RETOUR
FIN
Ce paramétrage donne un levier simple à l’administrateur. Pas besoin de redéployer l’application pour désactiver un agent qui se comporte mal.
Gestion des erreurs et des réponses faibles
Une intégration IA doit prévoir les réponses inutilisables.
Exemples courants :
- JSON invalide ;
- réponse hors sujet ;
- niveau de confiance trop faible ;
- action suggérée interdite ;
- hallucination sur une donnée absente ;
- délai API trop long ;
- quota fournisseur atteint.
Je préfère afficher un message sobre :
L'assistant n'a pas produit une proposition exploitable.
Aucune donnée CRM n'a été modifiée.
Et côté journal :
Statut: REFUSE
MessageErreur: JSON invalide - propriété priorite absente
Il ne faut pas forcer l’IA à répondre à tout prix. Sur une fiche client pauvre, une absence de proposition est parfois le meilleur résultat.
Séparer les prompts des règles métier
Les règles métier ne doivent pas vivre uniquement dans le prompt.
Mauvais exemple :
Tu ne dois jamais créer de relance pour un client bloqué comptablement.
C’est utile comme consigne, mais insuffisant.
La règle doit aussi exister dans le code WinDev :
SI Client.BloqueCompta = Vrai ALORS
Erreur("Client bloqué comptablement : création de relance commerciale interdite.")
RETOUR
FIN
Le prompt oriente le modèle. Le code protège l’application.
Sur des projets WinDev anciens, cette séparation demande parfois un peu de ménage. Certaines règles sont dans des boutons, d’autres dans des triggers, d’autres dans des procédures copiées. Avant d’ajouter l’IA, je préfère identifier les règles critiques. Sinon l’agent va simplement rendre visible le désordre existant.
Tester l’agent avec des cas CRM réels
Les tests ne doivent pas se limiter à trois clients propres créés pour la démo.
Je prépare plutôt un petit jeu de cas :
- client actif avec devis ouvert
- client sans interaction récente
- client bloqué comptablement
- client avec historique très long
- client avec notes contradictoires
- client VIP
- prospect sans email
- opportunité perdue puis réouverte
Pour chaque cas, on définit le comportement attendu.
Exemple :
Cas : client bloqué comptablement
Attendu :
- ne pas proposer d'envoi commercial
- signaler le blocage
- recommander une vérification interne
On peut automatiser une partie de ces tests avec un script qui appelle le service agent et compare les champs structurés.
#!/usr/bin/env bash
set -euo pipefail
API_URL="http://127.0.0.1:8088/agents/crm/relance"
for file in tests/crm-relance/*.json; do
echo "Test $file"
curl -sS \
-H "Content-Type: application/json" \
-d @"$file" \
"$API_URL" | jq .
done
Ce n’est pas un banc de test parfait. Mais il donne déjà une idée de la stabilité de l’agent après un changement de modèle ou de prompt.
Ce que WinDev doit continuer à faire
L’IA ne remplace pas les fondamentaux d’une application métier.
WinDev doit continuer à gérer :
- les droits utilisateur ;
- les transactions ;
- les contrôles de saisie ;
- les statuts ;
- les validations ;
- les impressions et exports ;
- les règles propres au client ;
- la traçabilité.
L’agent IA vient aider sur les zones floues : synthèse, formulation, qualification, mise en évidence d’un risque.
Il ne doit pas devenir une couche magique posée au-dessus d’un CRM fatigué.
Sur un audit, je regarde d’abord la qualité des données. Si les historiques sont vides, les statuts jamais mis à jour et les commerciaux stockent tout dans des commentaires libres, l’IA produira surtout des phrases plausibles. Pas forcément utiles.
Déploiement progressif dans une PME
Je commencerais par un seul agent.
Par exemple : Préparer une relance client.
Périmètre initial :
- lecture des 180 derniers jours d'historique
- devis ouverts uniquement
- aucune écriture automatique
- validation utilisateur obligatoire
- journalisation systématique
- activation par profil utilisateur
Après deux ou trois semaines d’usage, on regarde :
- combien de propositions sont acceptées ;
- combien sont modifiées ;
- combien sont ignorées ;
- quels champs manquent dans le contexte ;
- quels clients posent problème ;
- quels utilisateurs n’en veulent pas.
Ces retours valent mieux qu’un long cadrage théorique.
Ensuite seulement, on ajoute un deuxième agent : synthèse de compte, détection de risque, qualification d’opportunité. Pas les trois en même temps.
Conclusion
WinDev 2026 ouvre une porte intéressante pour intégrer des agents IA dans les outils métier. Dans un CRM, le bon angle n’est pas forcément de mettre un champ Chat au milieu de la fiche client.
Une intégration plus sobre fonctionne souvent mieux : un bouton métier, un contexte limité, un agent spécialisé, une réponse JSON, une validation humaine, une trace.
Pour une entreprise comme EloNeva, l’intérêt est là : moderniser une application WinDev sans casser les habitudes utilisateur, ajouter de l’aide là où les équipes perdent du temps, et garder une architecture compréhensible. L’IA doit s’insérer dans le CRM. Pas l’inverse.