Blog · Agentique
Un agent d'exploitation
l'organisation, n8n, et le portage en Rust
Un agent utile n'est pas un prompt : c'est une organisation. Voici la nôtre, la frontière avec n8n, et le chantier de portage du socle en Rust.
L'organisation, en couches
Un agent qui travaille sur une vraie infrastructure ne tient pas dans un prompt. Le nôtre est organisé en cinq couches, chacune avec un rôle séparé :
| Couche | Rôle |
|---|---|
| Outils | Terminal, navigateur, lecture et écriture de fichiers, appels HTTP, les mains |
| Mémoire | Faits durables sur l'infrastructure et les préférences, réinjectés à chaque session |
| Compétences | Procédures écrites (une par tâche récurrente), chargées à la demande, la mémoire du geste |
| Sous-agents | Tâches isolées exécutées en parallèle, qui ne rendent qu'un résultat |
| Planification | Exécutions différées : relevés, rapports, contrôles quotidiens |
Cette séparation est ce qui rend l'ensemble utilisable : un agent sans mémoire repose les mêmes questions tous les matins, et un agent sans compétences réinvente la même procédure chaque fois, souvent différemment.
n8n : la plomberie déterministe
Tout n'a pas vocation à être « intelligent ». Les appels d'API, les relances, les conversions de format, les accusés de réception : c'est du code, et cela doit se comporter comme du code. n8n tient ce rôle chez nous.
Un workflow n8n, c'est une suite de nœuds : un déclencheur (webhook, planification, événement), des appels HTTP vers les API des services que nous utilisons, des transformations, puis des actions, envoyer un message, créer une facture, alimenter un outil métier, alerter. Chaque étape laisse une trace, chaque erreur peut être réessayée, et relancer un workflow ne casse rien si l'appel est idempotent.
- Ce que n8n fait mieux qu'un agent un enchaînement d'appels prévisible, à heure fixe, avec reprise sur erreur et journal d'exécution. Un agent qui doit « décider » d'envoyer une facture chaque mois est un agent qui se trompera un jour.
- Ce que l'agent fait mieux que n8n lire trois sources contradictoires, comprendre qu'un incident réseau explique cinq alertes, et rédiger le compte rendu.
- Le point de jonction un webhook : l'agent déclenche un workflow quand il faut agir, et un workflow notifie l'agent quand quelque chose est arrivé. Chacun reste dans son métier.
C'est cette frontière, plus que le modèle choisi, qui fait la fiabilité d'un système d'automatisation : la partie prévisible reste prévisible.
Deux tests récents : Callbell et Zenith
Rien ne remplace l'essai réel. Deux API ont servi de banc d'essai ces dernières semaines, et elles ne se comportent pas du tout de la même façon.
Callbell messagerie d'entreprise, WhatsApp et canaux associés. Ce que le workflow
doit gérer : l'envoi depuis un déclencheur métier, l'accusé de réception, et surtout les
webhooks de statut un message n'est pas « envoyé » quand l'appel HTTP répond 200, il
l'est quand le statut revient. Trois enseignements : les limites de débit se traitent avec une
file d'attente et une temporisation exponentielle, pas avec un sleep ; un envoi
doit être idempotent, sinon une relance produit deux messages au client ; et le
consentement du destinataire est une donnée à stocker, pas une case à cocher ailleurs.
Zenith (CitizenPlane, API de vente aérienne), un tout autre métier : recherche de vols, tarifs, disponibilité, réservation. Ici le piège n'est pas le débit, c'est le temps de réponse et la forme des données : certaines réponses arrivent après plusieurs secondes, et une recherche laissée sans délai bloque le workflow entier. Ce qu'on a retenu : délais explicites côté client, mise en cache des résultats de recherche qui ne changent pas d'une minute à l'autre, et une normalisation stricte des réponses avant de les confier à l'étape suivante, sinon chaque appelant réinvente son propre format.
Dans les deux cas, la même architecture : n8n orchestre, l'agent n'intervient pas. Le workflow appelle l'API, journalise, réessaie ; l'agent ne sert qu'à analyser les échecs répétés et à proposer une correction.
Les garde-fous
- Lecture avant écriture l'agent constate, mesure et rapporte. Toute action qui modifie un système passe par une décision humaine explicite.
- Vérification après coup le compte rendu d'une action n'est pas la preuve de son effet : on relit l'état réel.
- Aucun secret dans le contexte les identifiants restent dans des fichiers protégés, jamais dans la conversation.
- Un humain signe nous ne modifions jamais le code produit par un agent sans l'avoir relu. L'agent propose, l'humain décide.
Le portage en Rust : le chantier en cours
Le socle actuel fonctionne, mais il traîne un interpréteur, des dépendances et une empreinte mémoire qui n'ont pas de sens sur une petite machine toujours allumée. Le projet est d'écrire en Rust le cœur du système : la boucle d'outils, le magasin de sessions, le planificateur et le client HTTP.
Ce qu'on y gagne : un binaire unique, un démarrage en quelques millisecondes, une mémoire maîtrisée et un ordonnancement prévisible. Ce qu'on y perd : la souplesse d'écrire un outil en dix lignes de Python, et c'est un vrai coût, pas un détail.
Le projet n'est pas une annonce : c'est un chantier, mené par étapes, avec la même exigence que pour un service client, un banc de test, des mesures avant/après, et aucune bascule tant que le nouveau socle ne fait pas au moins aussi bien.
Nous ne partons pas d'une intuition : le même raisonnement a déjà été écrit, chiffré et validé sur notre API de paiement, dont le document technique dit ceci.
« Un portage en Rust apporterait des bénéfices significatifs : performance native, sécurité mémoire (pas de GC), déploiement en binaire unique, et typage fort. »
Extrait du document technique du projet MONETIK, section « Portage en Rust, architecture proposée ».
Et le même document chiffre l'écart, sur la même charge :
| Critère | Python (FastAPI/uvicorn) | Rust (binaire natif) |
|---|---|---|
| Latence par requête | ~5 à 15 ms | ~0,5 à 2 ms |
| Mémoire résidente | ~50 à 100 Mo | ~10 à 20 Mo |
| Sécurité mémoire | Bonne (ramasse-miettes) | Maximale (borrow checker) |
| Déploiement | Interpréteur + venv + dépendances | Un fichier |
Chiffres issus du document technique MONETIK et du rapport de
déploiement (Rust 1.98.1, NGINX 1.28.3, API monetik-api en service systemd,
écoute sur 127.0.0.1:8443 uniquement).
Un détail de conception vaut d'être repris tel quel dans le socle de l'agent : dans ce projet, l'adaptateur bancaire est défini comme un trait Rust deux implémentations possibles, interchangeables sans toucher au moteur de règles. C'est exactement ce qu'on veut faire des outils de l'agent : chaque capacité (terminal, fichier, navigateur, appel d'API) devient un trait, avec une implémentation réelle et une implémentation de test. On peut alors remplacer un fournisseur, ou simuler un incident, sans réécrire la boucle.
Ce que le même document permet de mesurer, c'est aussi l'ordre de grandeur de l'effort : la phase de portage complète, cœur, API et interface d'administration, y est estimée à cinq à huit jours. C'est peu pour un service, et c'est beaucoup pour un socle qui doit rester en vie dix ans : c'est précisément la raison pour laquelle on y va par étapes.
Un modèle de langage local qui remplacerait celui du service, ou un agent qui s'administrerait tout seul. On déplace le socle d'exécution, pas la responsabilité.
Un projet comparable ? Nous répondons aux questions techniques en rendez-vous, avec les mêmes chiffres que dans ces articles.
The matching service: l'IA vocale et l'automatisation de tâches.