Démo
Générer une liste de leads de démonstration d'environ 10 contacts enrichis avec des exemples de messages personnalisés, déclenchée par une invite webhook.
Lisez ~/.claude/skills/gtm-pipeline/_shared/conventions.md avant d'exécuter.
Quand l'utiliser
- Déclencheur webhook : l'utilisateur soumet un formulaire de démo gratuit décrivant son audience cible
- Objectif : prouver que l'agent IA rédige une prospection authentique et non générique en utilisant de vrais leads
- Périmètre : ~10 contacts, enrichis avec LinkedIn + email, 2 à 4 exemples de messages
Restrictions de la démo
- Pas d'enrichissement téléphonique — email uniquement
- ~10 contacts (demander 10-15, s'attendre à une baisse d'enrichissement)
- La génération de messages est facultative mais recommandée
- La recherche de signaux est facultative — désactivée par défaut. Activez-la avec le flag
--with-signalsou sur demande explicite de l'utilisateur. Voir l'Étape 5.5. - Seuil de coût : avant le premier appel à un fournisseur payant, indiquez la dépense prévue (les recherches de finder par Cadence Source-Personnes sont généralement gratuites ; ~10-15 crédits d'enrichissement d'email ; signaux <0,50 $ si activés). Interactif : confirmer d'abord avec l'utilisateur. Headless : enregistrer l'estimation dans
run_log.mdet continuer, ne jamais bloquer.
Étape 1 — Analyser l'invite et établir le PIC
L'invite webhook décrit l'audience cible de l'utilisateur. Extrayez :
Éléments obligatoires :
- Que vendez-vous / proposez-vous ?
- Qui est votre client idéal ? (secteur, poste, taille d'entreprise, localisation)
- Quelle est votre proposition de valeur ?
- Quel ton ? (formel vs décontracté, exemples si possible)
- Est-ce pour recruter OU vendre à des clients ?
Si l'invite ne les contient pas, déduisez (ne bloquez pas) :
- Titres de poste cibles, localisation, taille/type d'entreprise
Résolvez automatiquement le demandeur avant d'interpréter l'audience (corrige le problème récurrent « que vendent-ils / pourquoi veulent-ils cette audience ») :
- Résolvez le domaine du demandeur à partir de son email (ex.
[email protected]→acme.de), scrapez/enrichissez-le, et établissez ce qu'ils vendent. Entreprises multi-offres : confirmez quelle ligne de produits la démo concerne — le produit indiqué dans l'invite peut ne pas correspondre au vrai. - Déterminez la relation avec l'audience cible — un terme cible (ex. « centres d'appels ») est généralement un segment auquel ils vendent, pas ce qu'ils sont. Classez : vend-à / achète-de / acquiert / partenaire / recrute. Les mots-clés de persona en découlent, pas d'une supposition.
Interactif vs déployé (headless) :
- Interactif : si un élément obligatoire est réellement ambigu après auto-résolution, posez une question concise de clarification. Sinon, continuez.
- Déployé / headless (invoqué via
claude -pdepuis le webhook — voir Déploiement) : ne jamais bloquer sur des questions. Déduisez chaque champ à partir de l'invite + recherche sur le domaine du demandeur, enregistrez les hypothèses danscontext/icp.mdsous une rubrique « Hypothèses », et allez jusqu'au bout.
Ne PAS procéder à la recherche tant que le PIC n'est pas assez clair pour construire un filtre pertinent.
Enregistrez le PIC dans : {slug-client}-gtm/context/icp.md (incluez l'offre, la classification
de la relation, et toute hypothèse headless).
Étape 2 — Créer le répertoire de travail
Créez la structure de répertoires {slug-client}-gtm/ comme défini dans conventions.md. Écrivez la définition du PIC dans context/icp.md.
Étape 3 — Recherche de personnes (10 contacts)
Utilisez la compétence people-search pour trouver environ 10 à 15 contacts.
Sélection du fournisseur pour la démo : suivez la cadence du finder dans conventions.md → Cadence
Source-Personnes — FullEnrich Finder → BetterContact → Pipe0 → Amplemarket/Crustdata (en dernier recours),
max 2 tentatives/source, FE en premier pour les segments PME/dirigeant/non-anglophones. FE et BC renvoient
directement les URL LinkedIn (nécessaires pour l'enrichissement d'email). S'il n'y a pas de liste d'entreprises
(invite basée sur un persona), utilisez Parallel FindAll ou BC Search. Pour les listes d'entreprises
provenant de répertoires/scraping, recherchez par nom d'entreprise + localisation, jamais par domaine exact
(conventions #11).
Champs clés à collecter :
nom_complet, prénom, nom_de_famille,
intitulé_poste, nom_entreprise, domaine_entreprise,
url_profil_linkedin, localisation
Suivez le protocole d'exécution de people-search : bac à sable → test → révision → exécution.
Étape 4 — Filtrage des contacts (Classement PIC)
Exécutez contact-filter sur les 10 à 15 contacts trouvés. Même les petits lots bénéficient d'un classement PIC — il garantit que l'étape d'enrichissement se concentre sur les contacts les plus pertinents.
- Applique le niveau de poste, le niveau de secteur, le niveau de localisation et la classification de taille d'entreprise
- Rejette les contacts clairement hors PIC
- Classe les contacts retenus par priorité
- Sortie :
csv/intermediate/contacts_filtered.csv
Pour les démos : utilisez un seuil de rejet strict assoupli (autorisez les niveaux 1 à 5), privilégiez le classement au filtrage.
Étape 5 — Enrichissement des personnes (Email uniquement)
Exécutez people-enrichment sur les contacts filtrés. Mode démo : email uniquement, pas de téléphone.
Flux recommandé :
- FullEnrich v2 (email) — tous les contacts
- Cascade Pipe0 — pour les échecs FE uniquement
Enrichissement supplémentaire pour la personnalisation des messages (si disponible) :
- Titre et résumé LinkedIn (via le scraping LinkedIn avec PhantomBuster)
- Publications LinkedIn récentes (2 à 3 par contact) — améliore considérablement la qualité du message
Champs minimum viables pour la génération de messages :
nom, intitulé_poste, nom_entreprise, url_profil_linkedin,
titre (facultatif), résumé (facultatif), publications_récentes (facultatif)
Faible rendement : si moins d'environ 8 contacts survivent au filtrage + enrichissement, effectuez un passage supplémentaire du finder (source suivante dans la Cadence Source-Personnes) avant de passer aux messages.
Étape 5.5 — Recherche de signaux (Facultative)
Par défaut : DÉSACTIVÉE. Activez-la quand :
- L'utilisateur demande explicitement des messages ancrés sur des signaux
- L'invite webhook mentionne des déclencheurs d'achat (financement, embauche, transformation, actualités récentes)
- L'offre du client dépend de signaux temporels pour avoir du sens (ex. « nous aidons les entreprises post-Série A à faire évoluer leurs opérations »)
- Un flag
--with-signalsest passé à l'invocation de la démo
Note de coût : ajoute ~0,01 à 0,05 $ par entreprise unique (recherche web + notation). Sur une démo de 10 contacts, cela représente généralement 5 à 10 entreprises uniques, donc <0,50 $.
Entrées requises pour signal-search
Signal-search a besoin de trois fichiers de contexte :
context/icp.md— déjà collecté à l'Étape 1context/offering.md— le bloc de proposition de valeur de l'Étape 1 (écrivez-le maintenant s'il n'est pas déjà enregistré)context/signal_criteria.md— liste à puces des types de signaux pertinents pour l'offre
Si signal_criteria.md n'existe pas, demandez à l'utilisateur : « Que pourrait faire une entreprise en ce moment
qui suggère qu'elle a besoin de ce que vous proposez ? » — capturez 5 à 10 puces et enregistrez.
Exécution
# Construire la liste d'entreprises à partir des entreprises uniques dans les contacts enrichis
python3 -c "
import csv, sys
vus = set()
with open('csv/output/contacts_enriched.csv') as f, open('csv/input/companies_raw.csv', 'w', newline='') as out:
reader = csv.DictReader(f)
writer = csv.DictWriter(out, fieldnames=['company_name', 'company_domain', 'company_website'])
writer.writeheader()
for row in reader:
c = row.get('company_name') or row.get('company') or ''
if c and c not in vus:
vus.add(c)
writer.writerow({
'company_name': c,
'company_domain': row.get('company_domain') or '',
'company_website': row.get('company_website') or row.get('website') or '',
})
"
# Exécuter signal-search sur les entreprises uniques
source \"$HOME/.claude/skills/gtm-pipeline/_shared/resolve_env.sh\" && \
export $(grep -E '^(PARALLEL_API_KEY|OPENROUTER_API_KEY|FIRECRAWL_API_KEY|GEMINI_API_KEY)=' \"$GTM_ENV_PATH\" | xargs) && \
python3 ~/.claude/skills/gtm-signal-search/signal_search.py \
--client-dir {slug-client}-gtm
La ligne source resolve_env.sh garantit que $GTM_ENV_PATH est défini même dans un shell frais
(voir signal-search SKILL.md / conventions). Pour la démo, laissez Firecrawl et l'enrichissement
Parallel DÉSACTIVÉS — la recherche web + la notation suffisent pour une liste de leads d'environ 10 contacts.
Activez Firecrawl uniquement si le contenu sur site (carrières, blog) est la principale source de signaux ;
si cette machine n'a Firecrawl que via MCP (pas de FIRECRAWL_API_KEY), utilisez la route
--firecrawl-pages-dir documentée dans la compétence signal-search.
Fusionner les signaux dans les contacts
import csv, json
signaux = {}
with open('csv/intermediate/signals.csv') as f:
for row in csv.DictReader(f):
signaux[row['company_name']] = {
'overall_score': row.get('overallScore', ''),
'scored_signals': row.get('scoredSignals', ''),
'overall_summary': row.get('overallSummary', ''),
}
lignes_sortie = []
with open('csv/output/contacts_enriched.csv') as f:
for row in csv.DictReader(f):
s = signaux.get(row.get('company_name') or row.get('company') or '', {})
row['company_overall_score'] = s.get('overall_score', '')
row['company_scored_signals'] = s.get('scored_signals', '')
row['company_overall_summary'] = s.get('overall_summary', '')
lignes_sortie.append(row)
with open('csv/output/contacts_enriched.csv', 'w', newline='') as f:
w = csv.DictWriter(f, fieldnames=list(lignes_sortie[0].keys()))
w.writeheader()
w.writerows(lignes_sortie)
L'étape de génération de messages à l'Étape 6 aura alors company_overall_summary et
company_scored_signals par contact — utilisez le signal le mieux noté comme accroche du message.
Étape 6 — Générer des exemples de messages
Générez 2 à 4 messages échantillons avant de vous engager sur le lot complet.
Structure du message
Chaque message doit suivre : Accroche → Pont → Offre → CTA
| Partie | Objectif | Longueur |
|---|---|---|
| Accroche | Faire référence à quelque chose de spécifique à cette personne (publication, évolution de carrière, signal d'entreprise) | 1 phrase |
| Pont | Relier sa situation à votre offre | 1 phrase |
| Offre | Ce que vous fournissez, clairement énoncé | 1 phrase |
| CTA | Demande douce — pas « planifions un appel » | 1 phrase |
Total : 320–450 caractères. Pas de ligne vide après la salutation. Paragraphes séparés par un saut de ligne simple.
Règles de qualité
Éléments obligatoires :
- Accroche spécifique (référence à une publication OU insight de carrière OU signal d'achat noté — pas générique)
- Proposition de valeur claire
- Ton naturel et conversationnel
- CTA doux
À éviter absolument :
- Répéter des informations de profil qu'ils connaissent déjà (« Vous travaillez comme X chez Y »)
- Observations génériques (« parcours impressionnant », « j'ai remarqué que vous êtes dans [secteur] »)
- Jargon d'entreprise ou mots à la mode
- CTA insistants (« Planifions un appel cette semaine »)
Si l'Étape 5.5 a été exécutée : pour chaque contact, privilégiez le signal le mieux noté de
company_scored_signals comme accroche plutôt que des références génériques à des posts LinkedIn.
Un signal avec un score >= 70 ancré dans une actualité récente réelle est l'accroche la plus forte
que la démo puisse produire.
Processus de génération
- Rédiger une invite système spécifique au client (enregistrer dans
prompts/message_prompt.md) - Générer 2 à 4 échantillons — inclure des contacts avec et sans posts LinkedIn
- Réviser selon la liste de contrôle qualité ci-dessus
- En cas de problèmes, affiner l'invite système et regénérer
- Ne générer en lot qu'une fois la qualité approuvée
Modèle d'invite système (sections clés)
- Contexte client : ce qu'ils vendent, qui ils ciblent, leur proposition de valeur, ton
- Règles interdites : pas de répétition du profil, pas de flatterie générique
- Structure du message : accroche → pont → offre → CTA
- Exemples d'accroches : avec posts / sans posts
- Limite de caractères : 320–450
Étape 7 — Nettoyer et produire la sortie
Étape 7a — Nettoyage (obligatoire, déterministe, sans LLM). csv/intermediate/ conserve tous les champs.
Avant de construire quoi que ce soit destiné aux leads, exécutez le nettoyeur partagé pour éviter le
nettoyage manuel récurrent (étiquettes de fournisseurs, colonnes vides, mauvais emails, signaux obsolètes) qui se produit