Des rapports automatisés
Gabarit figé, chiffres produits par du code, commentaire généré : la structure qui rend une série de rapports comparable.
Le rapport mensuel est un bon candidat à l'automatisation : même périmètre, même public, même questions, douze fois par an. Et pourtant la première tentative échoue presque toujours de la même façon.
On demande « fais-moi le rapport de mars à partir de ces données », on obtient un document correct, et le mois suivant on obtient un document correct qui n'a plus la même structure. Les sections ont changé de nom, un indicateur a disparu, un autre est apparu. Deux rapports non comparables ne forment pas une série, et une série est tout l'intérêt d'un rapport récurrent.
La correction est simple : le gabarit ne se régénère pas. Il est écrit une fois, il est figé, et le modèle ne fait que remplir les trous. Trois pièces séparées : un gabarit, des chiffres produits par du code, un texte qui commente les chiffres.
Ce qui appartient à chaque pièce
| Pièce | Produit par | Change quand |
|---|---|---|
| Le gabarit | Un humain, une fois | On décide de changer le rapport |
| Les chiffres | Un script, à chaque exécution | Les données changent |
| Le commentaire | Le modèle, à chaque exécution | Les chiffres changent |
| Les décisions | Un humain, toujours | Jamais automatisées |
Un chiffre dans un rapport ne sort jamais d'un modèle
Les totaux, moyennes et variations sont calculés par le script, avant l'appel au modèle, et injectés tels quels. Le modèle reçoit des nombres déjà écrits ; son travail est de les expliquer, pas de les obtenir.
Avant de commencer
- Deux ou trois exemplaires du rapport, faits à la main
- Une source de données interrogeable par script
- Un endroit où le rapport sera lu, décidé à l'avance
1Figer le gabarit
Prends les rapports existants et extrais la structure commune. Les sections, dans l'ordre, avec pour chacune : ce qu'elle contient, sa longueur maximale, et les indicateurs qu'elle affiche.
# Rapport [MOIS] [ANNEE]
## En un coup d'oeil
{{SYNTHESE}} <- 3 puces maximum, 15 mots chacune
## Chiffres cles
| Indicateur | Ce mois | Mois precedent | Variation |
| --- | --- | --- | --- |
{{TABLEAU_KPI}} <- genere par le script, jamais par le modele
## Ce qui a change
{{ANALYSE}} <- 200 mots maximum, factuel
## Points d'attention
{{ALERTES}} <- uniquement les seuils depasses, sinon "Aucun"
## Decisions a prendre
{{A_REMPLIR_PAR_UN_HUMAIN}}
Cette dernière section est volontairement vide. Elle rappelle à chaque lecture que le rapport constate, et que quelqu'un doit décider.
2Produire les chiffres par du code
Le script fait trois choses : interroger la source, calculer, et écrire un fichier de données. Il ne rédige rien.
{
"periode": "2026-07",
"kpi": [
{"nom": "Commandes", "valeur": 1284, "precedent": 1190, "variation_pct": 7.9},
{"nom": "Panier moyen", "valeur": 47.2, "precedent": 51.0, "variation_pct": -7.5},
{"nom": "Taux de retour", "valeur": 4.1, "precedent": 3.9, "variation_pct": 5.1}
],
"seuils_depasses": [
{"nom": "Panier moyen", "seuil": "-5 %", "constate": "-7,5 %"}
],
"lignes_exclues": 12,
"motif_exclusion": "commandes de test"
}
Deux champs méritent d'exister systématiquement : le nombre de lignes exclues et le motif. Ils rendent le rapport auditable, et évitent la question « pourquoi ce chiffre n'est pas le même que dans l'outil ».
Les seuils, eux, sont définis dans le script, pas laissés au jugement du modèle. Un seuil est une décision de gestion, elle doit être écrite quelque part.
3Le prompt de rédaction
Un seul appel, avec le gabarit et les données. La consigne interdit tout ce que le modèle a naturellement envie de faire.
Voici un gabarit de rapport et les donnees du mois, au format JSON.
Remplis uniquement les emplacements {{SYNTHESE}}, {{ANALYSE}} et
{{ALERTES}}. Ne touche a aucune autre partie du gabarit, ne renomme
aucune section, n'en ajoute ni n'en supprime.
Regles :
1. N'ecris aucun nombre qui ne figure pas dans le JSON. Reprends-les
tels quels, sans arrondir.
2. Ne cherche pas de cause a une variation. Decris ce qui a change. Si
une explication est evidente d'apres les donnees fournies, formule-la
comme une hypothese a verifier.
3. {{ALERTES}} ne contient que les seuils depasses listes dans le JSON.
Si la liste est vide, ecris "Aucun".
4. Pas de superlatif, pas de "excellente performance", pas de
"en forte hausse". Les chiffres parlent.
5. Respecte les longueurs indiquees en commentaire dans le gabarit.
6. Mentionne les lignes exclues et leur motif dans {{ANALYSE}}.
GABARIT :
[GABARIT]
DONNEES :
[JSON]
La règle 2 est celle qui évite le pire travers de ces rapports : une causalité inventée qui devient la version officielle parce qu'elle était écrite.
4Le faire tourner
En mode non interactif, on injecte les données par l'entrée standard :
python collecte.py > donnees.json
cat donnees.json | claude -p "$(cat prompt-rapport.txt)" > rapport-2026-07.md
Pour un enchaînement scripté, --bare réduit le temps de démarrage et ignore
les hooks, plugins, serveurs MCP et fichiers CLAUDE.md de la machine, ce qui
donne le même résultat partout. Il faut alors fournir ANTHROPIC_API_KEY, car
ce mode ne lit pas les identifiants de session.
Côté planification, GitHub Actions accepte un cron, en gardant en tête que les horaires sont en UTC et que les exécutions peuvent être retardées en période de charge :
on:
schedule:
- cron: "0 6 1 * *"
Versionner les rapports
Écris chaque rapport dans un fichier daté, dans un dépôt. La série devient consultable, les écarts se voient, et une régression du gabarit se repère au diff.
5Ce qui doit rester humain
Trois choses ne s'automatisent pas, et vouloir les automatiser est le meilleur moyen de rendre le rapport inutile.
- La décision. Un rapport qui dit ce qu'il faut faire enlève à son lecteur le travail pour lequel il est payé. La section « Décisions » reste vide jusqu'à ce qu'un humain l'écrive.
- L'explication d'un écart inhabituel. Le script voit une baisse de 7,5 % ; seul quelqu'un qui était là sait qu'un gros client a décalé sa commande.
- La révision du gabarit. Une fois par an, en regardant les douze rapports : quelles sections personne n'a jamais lues, quel indicateur manque.
Le test du mois vide
Fais tourner la chaîne sur un mois où rien ne s'est passé. Si le rapport produit trois pages d'analyse, tes consignes ne sont pas assez strictes. Un mois sans rien doit produire un rapport court.
Quelques prompts pour aller plus loin
| Objectif | Prompt à adapter |
|---|---|
| Extraire le gabarit | Voici 3 rapports faits a la main. Deduis-en un gabarit commun : sections, ordre, longueurs, indicateurs. Signale ce qui varie d'un rapport a l'autre. |
| Choisir les indicateurs | Voici les 20 indicateurs disponibles et les 3 decisions que ce rapport doit eclairer. Garde les 6 indicateurs qui servent reellement et justifie chaque suppression. |
| Écrire le script | Ecris un script qui interroge [SOURCE] et produit ce JSON, avec les valeurs du mois, celles du mois precedent, la variation, et le nombre de lignes exclues. |
| Tester la stabilité | Voici le meme gabarit rempli sur 3 mois. Signale toute derive : section renommee, indicateur disparu, ton different, longueur qui gonfle. |
| Contrôler la sortie | Relis ce rapport genere et le JSON source. Signale chaque nombre qui n'apparait pas dans le JSON, et chaque phrase qui affirme une cause. |
Tu as d’autres ressources comme ça ?
Ce que tu viens de lire est entièrement gratuit. Une nouvelle ressource part chaque semaine dans la newsletter : guides, modèles à copier et liens triés, sans compte à créer.
Me contacter
Une question, un projet, une envie de collaborer ? Écris-moi.
Cette page est en accès libre, n’hésite pas à la partager.