Travaux sélectionnés

Systèmes en production

Six chantiers issus de ma mission actuelle comme Head of AI chez Crème de la Crème, l'une des plus grandes marketplaces freelance de France. Pour chacun : le problème, l'architecture, le résultat mesuré, et l'arbitrage que j'ai dû rendre.

Les six ont été construits dans la même entreprise : une marketplace où des milliers de freelances rencontrent les entreprises qui les cherchent, et où une équipe Sales doit faire ce rapprochement vite, juste, et sans voir des données qu'elle n'a pas à voir. C'est cette contrainte qui a façonné chacun des systèmes ci-dessous.

Je porte l'architecture et j'écris ces systèmes front et back, en menant le build avec des agents de code et en corrigeant ce qu'ils produisent ; ce qui part en production est relu par l'équipe engineering côté client. Le code appartient au client et les dépôts sont privés : l'architecture et les résultats mesurés se présentent de vive voix plutôt qu'en lien.

En intégration, pilote avant la production
Juil. – août 2026Rôle : Seul architecte et développeur

Ouvrir le back-office d’une entreprise au langage naturel

N’importe qui dans l’entreprise demande une chose en langage courant et elle est faite, sans traverser cinq écrans, et sans jamais voir une ligne à laquelle il n’a pas droit.

49 outils
chacun répondant sous les droits de la personne qui demande, jamais ceux d’un compte de service

Le problème

Tout back-office mature exprime une partie de ses permissions par l’interface : ce qu’on peut faire, c’est en grande partie ce qu’on nous montre. Un serveur MCP n’a pas d’interface, donc pas de bouton à masquer. L’exposer suppose que chaque droit que l’application transmet par ce qu’elle affiche soit réénoncé comme une règle explicite, côté serveur, avant qu’un seul outil ne sorte, et que chacune de ces règles soit vérifiée dans le code plutôt que supposée.

Ce que ça débloque

  • Les Sales, et à terme tout le monde, demandent en une phrase ce qui demandait un parcours de plusieurs écrans, et l’action est exécutée.
  • Des tâches trop petites ou trop fastidieuses pour valoir la peine d’être déléguées peuvent aller à un agent, parce que l’agent hérite des droits de la personne qui demande et non de ceux d’un compte de service.
  • Des briefs personnalisés assemblés depuis les données vivantes, au lieu d’être recopiés à la main avant un rendez-vous client.
  • La même question posée par deux personnes renvoie deux réponses différentes, et aucune des deux n’apprend ce que l’autre peut voir.

Architecture

  • Trois couches d’autorisation, toutes vérifiées côté serveur : qui peut atteindre le serveur, quels outils il peut appeler, quelles lignes il peut voir.
  • Des personas dérivés des rôles existants, chaque périmètre étant calculé à partir des données plutôt que recopié d’une liste tenue à la main.
  • Les outils sensibles s’adossent aux contrôles de permission que l’application évalue déjà côté serveur, plutôt qu’à une liste de rôles recopiée dans le serveur : la règle reste vraie par construction quand le back-office évolue, et un accès nominatif est couvert sans déploiement.
  • Projection du payload champ par champ : aucun objet métier n’est renvoyé brut, donc un champ qui n’avait pas vocation à sortir ne peut pas sortir par accident.
  • Double confirmation sur tout ce qu’un client finira par voir, une garde de confidentialité déterministe tenue hors du chemin d’écriture du modèle, et un audit trail requêtable à conservation bornée.
  • OAuth 2.1 + PKCE sur Streamable HTTP, 49 outils, PostgreSQL.

L'arbitrage

L’essentiel du travail n’était pas l’API. C’était de répondre explicitement aux questions de sécurité que l’interface porte implicitement : comment on donne l’accès, ce qu’un salarié qui part perd et à quel moment, ce qui se passe la première fois qu’on demande à un outil une action irréversible. Quand un accès client OAuth manquant a bloqué la campagne d’intégration, j’ai écrit un script qui passe par la vraie boucle d’autorisation plutôt que d’ajouter un contournement au serveur. Ça a coûté deux jours, et c’est pour ça que le périmètre veut encore dire quelque chose.

Stack

TypeScript / Node
MCP
OAuth 2.1 + PKCE
PostgreSQL
Streamable HTTP
En production, utilisé quotidiennement
Mai – juin 2026Rôle : Lead engineer

Recherche hybride, scoring et jugement LLM borné

Un moteur de matching qui devait battre celui déjà en production, brief par brief, avant d’avoir le droit d’être livré.

1 appel / candidat
un juge borné et parallélisé : le coût et la latence par brief restent plats quand le vivier grandit

Le problème

Un commercial répond à un brief client en trouvant les bons freelances, vite. Une recherche de marketplace qui classe sur le recouvrement de mots-clés rend une liste plate : à peu près la même forme de réponse quel que soit le brief, des profils forts enfouis sous la ligne de flottaison, et la géographie traitée comme un mot-clé de plus. Le mode de défaillance n’est pas le résultat vide, c’est qu’on ne peut plus distinguer un vrai match d’un profil de remplissage.

Ce que ça débloque

  • Un brief qui imposait une recherche manuelle rend maintenant une shortlist qu’un commercial peut défendre devant un client.
  • Le moteur rend ce qui correspond puis s’arrête, au lieu de compléter chaque brief jusqu’au même nombre fixe de profils.
  • Sur le golden dataset, la version livrée ne rate aucun match attendu.
  • Déployé auprès des Sales avant l’ouverture générale.

Architecture

  • Rappel à quatre signaux (BM25, recouvrement de compétences, kNN vectoriel sur embeddings OpenAI stockés dans PostgreSQL/pgvector, et un index d’expériences), fusionnés par Reciprocal Rank Fusion.
  • Scoring déterministe pondéré sur sept dimensions : reproductible, sans modèle dans la boucle.
  • Une couche de LLM-as-a-judge bornée : un appel par candidat, plafonné et parallélisé, pour que le coût et la latence par brief restent plats quelle que soit la taille du vivier.
  • Un harnais d’éval sur un golden dataset de briefs annotés, chacun portant un top 5 attendu et les faux positifs à exclure, exécuté contre la baseline de production avant toute décision de livraison.

L'arbitrage

Le harnais d’éval est venu avant le moteur, et le moteur n’a pas eu le droit de sortir tant qu’il ne battait pas l’existant sur le dataset plutôt que sur une démo. Une version tout-déterministe et une version tout-agentique ont été construites puis écartées : la première ne savait pas lire un brief, la seconde n’était pas reproductible deux fois. Conserver le moteur de recherche en place plutôt que le migrer a été évalué puis tranché avec le CTO.

Stack

TypeScript
API OpenAI Responses + embeddings
PostgreSQL / pgvector
Recherche hybride + RRF
LLM-as-a-judge
Harnais d’éval
En production, utilisé quotidiennement
Déc. 2025Rôle : Construit de bout en bout, puis fiabilisé en prod avec une développeuse

Décision human-in-the-loop sur les candidatures entrantes

Le modèle tranche les cas nets. Un humain garde les cas ambigus, et c’est précisément ce qui rend l’automatisation acceptable.

90–95 %
des candidatures entrantes tranchées sans humain dans la boucle

Le problème

Chaque candidature pour rejoindre la marketplace était relue à la main. Ça coûtait au moins une heure par jour à une Product Manager, et tout le flux d’entrée s’arrêtait dès que cette personne n’était pas disponible.

Ce que ça débloque

  • 90 à 95 % du flux entrant est tranché sans humain. Seuls quelques dossiers par jour remontent à une personne.
  • Environ sept heures par semaine rendues à la Product Manager, et un traitement quasi temps réel au lieu d’un lot quotidien.
  • Avant mise en service, le pipeline a été passé sur un échantillon représentatif de cinquante candidatures déjà tranchées par un humain, sans un seul désaccord.
  • L’entrée sur la plateforme ne dépend plus de la présence d’une seule personne.

Architecture

  • Des verdicts à trois états, scorés sur plusieurs axes indépendants plutôt que rabattus sur un score opaque unique.
  • Des sorties structurées validées par schéma, pour qu’une décision malformée n’atteigne jamais le pipeline.
  • Un pré-filtre d’admissibilité, et un routage par règles de toute anomalie ou tout doute vers un humain, qui peut aussi reclasser un dossier a posteriori.
  • Le schéma est le contrat, pas le modèle. Le pipeline a traversé des générations de modèles sans changer ni le format de décision ni le flux de revue.

L'arbitrage

Trier vaut mieux qu’automatiser à 100 %. Garder un humain sur les cas durs est ce qui rend l’automatisation acceptable sur une décision aussi sensible que l’accès à la plateforme, et c’est ce qui a permis à la chose de sortir tout court.

Stack

TypeScript
Sorties structurées validées par schéma
Modèles frontier
En production, utilisé quotidiennement
Févr. – mars 2026Rôle : Conçu et construit de bout en bout

Accès en langage naturel à une base de production, sous gouvernance

Une équipe non technique qui pose ses questions à la base de production en langage courant, en lecture seule par choix de gouvernance et non par limite technique.

30 min → secondes
par extraction de données, en self-service, sans passer par un ingénieur

Le problème

Chaque extraction de données passait par une seule personne, et prenait de trente minutes à plusieurs heures. Et un schéma de production qui compte bien plus de tables que ce qu’on garde en tête ne se tend pas à un modèle en espérant que ça passe.

Ce que ça débloque

  • Des extractions qui prenaient de trente minutes à plusieurs heures se font en quelques secondes, en self-service.
  • Un commercial a traité une demande de cinq extractions et treize entités en une seule passe.
  • Des règles métier qu’il fallait mémoriser sont désormais appliquées par le template de requête plutôt que par la mémoire de chacun.
  • Le goulot d’étranglement est sorti de la boucle sur les questions de routine, et y reste sur celles qui comptent.

Architecture

  • Un serveur MCP base de données avec découverte de schéma, plus une skill packagée qui porte le contexte métier que le schéma ne porte pas.
  • Un schéma de référence documenté sur les tables qui comptent vraiment, un glossaire métier relié aux bonnes formules, et les pièges de jointure rendus explicites.
  • Des règles métier câblées dans des templates de requête obligatoires plutôt que laissées à la mémoire de chacun : consentement, exclusions, gestion des devises, LIMIT par défaut, secrets jamais exposés.

L'arbitrage

À l’origine, l’agent exécutait et exportait seul. Faute d’un environnement sûr où exécuter, je l’ai restreint à générer du SQL qu’un humain relit et exécute. C’est une décision de gouvernance, pas une limite technique. Elle est documentée, et elle a une porte de sortie nommée : un rôle dédié en lecture seule.

Stack

TypeScript
MCP
PostgreSQL
Skill packagée
En production, utilisé quotidiennement
Févr. – mars 2026Rôle : Conçu et construit de bout en bout

Transformer un outil d’expert en capacité self-service

Acheter l’accès API plutôt que des sièges, et laisser un brief en langage courant écrire la syntaxe que personne n’avait envie d’apprendre.

200+
utilisations le premier mois, par des gens qui n’avaient pas accès à l’outil avant

Le problème

Un produit de recherche de talents de niche était enfermé derrière une poignée de licences payantes et une syntaxe booléenne que peu de gens savaient écrire. Tous les autres faisaient la queue derrière eux.

Ce que ça débloque

  • Un outil que seule une poignée de détenteurs de licence pouvait utiliser est devenu accessible à toute l’équipe commerciale.
  • Plus de 200 utilisations le premier mois.
  • Plus besoin d’apprendre la syntaxe booléenne pour obtenir une recherche correcte.

Architecture

  • Un module de back-office qui compile un brief en langage courant vers la syntaxe booléenne de l’éditeur : une grammaire contrainte plutôt qu’une génération libre, pour que le modèle remplisse les cases d’un template au lieu d’émettre des opérateurs qu’il peut se tromper.
  • Chaque requête générée est montrée au commercial avant exécution, avec les critères interprétés écrits à côté : une mauvaise requête se lit comme un mauvais critère, pas comme une liste de résultats vide sans explication.
  • Facturé à l’usage plutôt qu’au siège, ce qui a rendu l’ouverture à toute l’équipe moins chère que l’ajout de licences.

L'arbitrage

Le geste évident était d’acheter des licences. Choisir l’API voulait dire devenir responsable de la justesse des requêtes plutôt que de louer une interface éditeur qui s’en chargeait déjà, d’où la grammaire contrainte et la relecture humaine sur chaque requête. L’argument coût rendait la décision facile à défendre ; ce qui la rendait juste, c’est qu’une licence débloque une personne de plus et que l’API a débloqué l’équipe.

Stack

TypeScript
Génération contrainte
API de sourcing tierce
En production, plus deux systèmes volontairement arrêtés
2025 – 2026Rôle : Conçu et construit de bout en bout

Packager le savoir-faire pour qu’il cesse de passer par une seule personne

Des composants modulaires et recombinables qui ont sorti des capacités de mes mains, et deux chantiers que j’ai arrêtés quand l’éditeur a rattrapé.

3 jours
de la conception à la livraison, pour le sourcing agentique qui a remplacé un outillage que j’étais seul à savoir manœuvrer

Le problème

Le savoir-faire qui marchait restait chez ceux qui l’avaient : préparation de compte, préparation de rendez-vous, qualification d’appels d’offres, onboarding, support. Pendant ce temps, certains chantiers précoces se faisaient discrètement rattraper par une roadmap éditeur.

Ce que ça débloque

  • Des capacités qui passaient par moi tournent maintenant sans moi, seul test qui compte pour de l’outillage interne.
  • Une nouvelle skill est un fichier dans un dépôt, plus un projet.
  • Deux systèmes précoces arrêtés plutôt que maintenus, une fois que l’éditeur du CRM a sorti une capacité équivalente.

Architecture

  • Un marketplace de skills métier modulaires et recombinables, distribuées à l’équipe Sales et tenues à jour depuis un dépôt plutôt que recopiées de main en main.
  • Du sourcing et de l’enrichissement externes agentiques au-delà de la base interne, conçus et livrés en trois jours, en remplacement d’un outillage que j’étais seul à savoir manœuvrer.
  • Un serveur MCP au-dessus du design system qui a ramené une maquette front alignée à une demi-journée, dans une période sans designer.

L'arbitrage

Construire en interne n’a de sens que si l’éditeur ne comblera pas le manque. J’ai arrêté les deux chantiers les plus anciens quand il l’a comblé. Savoir s’arrêter fait partie du métier, surtout dans une maison dont l’instinct est de construire.

Stack

Skills packagées
MCP
Synchronisation par dépôt
Design system

Conseil, formation et interventions

Au-delà des systèmes ci-dessus : diagnostics, ateliers et programmes de formation menés auprès des équipes de Chanel, Stellantis, Bouygues Telecom, Rakuten, Generali, Institut Pasteur et d'autres.

Systèmes en production | Atomly AI