4 min

2

Automatiser une variable grammaticale avec une IA dans n8n

Une variable de personnalisation restait vide dans nos campagnes Lemlist. J’ai construit un petit sous-workflow n8n qui demande à un LLM la bonne préposition devant un nom d’entreprise. Simple en apparence, mais le correctif a dérapé deux fois.

Le problème

Certains emails contiennent des phrases comme :

« Comment sécurisez-vous les communications {{companyDu}} ? »

{{companyDu}} contient la préposition et le nom : « de la MACIF », « d’Allianz France », « de CNP Assurances ». Jusque-là, cette variable était calculée à la main à chaque import de leads. Une fois la création et l’enrichissement des leads automatisés, plus personne ne la remplissait, et les nouveaux leads arrivaient avec ce champ vide.

Le déclic

C’est un aperçu de campagne qui affichait littéralement {{companyDu}} dans le sujet d’un email de test qui a révélé le problème.

Ne pas se fier à un seul exemple

Ma première version s’appuyait sur trois leads déjà remplis à la main. Erreur de méthode : j’ai ensuite audité les 32 campagnes via l’API, en cherchant tous les motifs {{company...}}. Il y avait en fait deux variables :

Variable Exemple de phrase Rendu attendu
{{companyDu}} « les communications {{companyDu}} » « les communications de la MACIF »
{{companyAu}} « voir si ça s’applique {{companyAu}} » « voir si ça s’applique à la MACIF »

companyDu apparaît dans 13 campagnes, companyAu dans 3, toujours avec companyDu. Ce ne sont pas des champs personnalisés déclarés côté Lemlist, mais des variables de lead posées au cas par cas : seule la lecture des séquences pouvait les révéler.

Pourquoi un LLM plutôt qu’une règle

Une règle sur la voyelle initiale ne suffit pas. Le genre des sigles vient de l’usage : on dit « la MACIF » mais « le CIC ». Une regex ne le devine pas, un LLM généraliste le sait pour la quasi-totalité des organismes ciblés (mutuelles, banques, assurances, collectivités).

J’utilise un modèle léger via OpenRouter, avec une sortie structurée forcée ({companyDu, companyAu}). Si companyName est vide, le sous-workflow saute l’appel au LLM.

Ce qui a cassé

Un prompt mal cadré. Mon premier prompt parlait de produire le nom « après la préposition de ». Or le template n’a aucune préposition écrite en dur : le modèle risquait de renvoyer « la MACIF » seul, et la phrase devenait « les communications la MACIF ». Je l’ai réécrit en citant le vrai texte :

Dans nos templates, AUCUNE préposition n'est écrite en dur avant la
variable : "les communications {{companyDu}}". TU dois produire la
préposition ET le nom ensemble.

La leçon

Pour remplir une variable de template, citer la phrase réelle qui l’entoure, jamais la paraphraser.

Un correctif qui ne s’appliquait pas. Les tests sont passés au vert, j’ai annoncé « c’est corrigé ». Réponse : « Je vois pas de changement. » Le nœud affichait toujours l’ancien prompt.

Un chemin JSON relatif au mauvais objet

L’outil d’édition n8n prend un chemin JSON relatif à parameters. J’avais écrit /parameters/options/systemMessage au lieu de /options/systemMessage. Résultat : une nouvelle clé parameters imbriquée dans les paramètres existants, que n8n ignore silencieusement.

{
  "parameters": {
    "options": { "systemMessage": "ANCIEN TEXTE" },
    "parameters": {
      "options": { "systemMessage": "NOUVEAU TEXTE" }
    }
  }
}

Aucune erreur, « succès » à chaque appel. Trois mises à jour, dont l’ajout de companyAu, n’ont jamais pris effet. Le même piège est décrit dans l’enrichissement Apollo/Lemlist.

Correction : remplacer l’objet de paramètres complet, puis relire l’état réel du workflow (brouillon et version publiée), ce qui a révélé la clé dupliquée.

Brancher le correctif

Dans n8n, un nœud « Exécuter un sous-workflow » remplace toutes les données de l’item. Je l’appelle donc en parallèle de la chaîne principale, puis je fusionne les deux branches par position avant de créer le lead.

Le nœud Lemlist natif de création n’accepte aucune variable personnalisée. companyDu/companyAu sont posées ensuite par un PATCH /api/leads/{id}/variables, sur une branche latérale : s’il échoue, la confirmation au commercial n’est pas bloquée.

Pour tester, l’outil ne renvoyait que le statut d’exécution, pas la sortie du modèle. La sortie structurée sert de filet (un format invalide fait échouer l’exécution). Les tests (MACIF, Allianz France, CNP Assurances, CIC) sont passés, et le cas « nom vide » s’exécute en ~10 ms : le LLM est bien sauté.

À retenir

Le workflow qui met à jour les contacts existants reste désactivé en attendant une validation en écriture réelle. Si une campagne introduit une nouvelle construction grammaticale, elle ira dans ce même sous-workflow. Et depuis, après chaque modification de nœud n8n, je relis l’état réel : un « succès » dit ce que l’outil a tenté d’écrire, pas ce qui sera lu à l’exécution.

À lire aussi

3Générer des posts LinkedIn avec l’IA pour des commerciaux multi-secteurs34Les règles que mon agent IA a apprises en se trompant1:1Rappel quotidien des tâches Lemlist en 1:1 Teams avec n8n