Agentique · Comptabilité

Un agent sur l'API Pennylane
préparer sans envoyer seul

Un agent lit la comptabilité, prépare les récapitulatifs et les brouillons de devis, et s'arrête devant tout ce qui engage la société. Les pièges d'API qui ont changé notre code.

Lire avant d'écrire

La première version de notre agent Pennylane ne crée rien. Elle lit : chiffre d'affaires hors taxes, TVA et TTC sur une période, principaux clients, devis en cours, factures non réglées avec leur retard en jours. C'est déjà l'essentiel d'un lundi matin, et c'est le seul périmètre où une erreur de l'agent ne coûte rien à personne.

Le principe qui a guidé le reste tient en une phrase : l'agent prépare, l'humain valide. La commande affiche ce qu'elle va faire avant de le faire, et rien ne part vers un client sans une relecture. Un agent qui écrit tout seul dans une comptabilité n'est pas une avancée, c'est un incident en attente.

Les briques, et pourquoi elles sont séparées

Le montage n'a rien d'exotique. Il assemble quatre ou cinq outils qui existaient déjà, chacun avec une seule responsabilité. C'est ce qui permet de savoir où regarder quand une réponse est fausse.

BriqueSon rôleCe que ça évite
CLI maisonParle à l'API, gère les pages, formate les montantsNeuf scripts jetables qui divergent
AgentEnchaîne les commandes, résume, alerte, rédige un brouillonLa synthèse recopiée à la main
Fichiers de règlesFormats de sortie, seuils, vocabulaire, modèlesUn savoir qui vit dans une tête
Messagerie interneLivraison du récap du matin, alertes d'impayésLe tableau de bord jamais ouvert
Client mailEnvoi du devis avec une phrase d'introductionLe texte imposé par un modèle d'e-mail

Le CLI est écrit en Python standard, sans dépendance : il peut tourner sur un serveur sans paquets, et il n'y a pas de couche d'abstraction entre l'API et la sortie. C'est volontairement peu élégant, volontairement lisible.

Trois pièges d'API qui changent le code

  • La pagination se fait par curseur. La réponse contient items, has_more et next_cursor. Un limit seul tronque le récapitulatif sans erreur : on croit avoir tout lu, on a lu la première page.
  • Les montants arrivent en texte. Les champs de prix sont des chaînes : sans conversion explicite, la somme de deux montants donne une concaténation. Nos totaux passent par une conversion unique, au même endroit.
  • Un impayé est une définition, pas un champ. Ce n'est ni un statut ni un drapeau fourni par l'API, mais une combinaison : facture non réglée, restant dû supérieur à zéro, et brouillon exclu. En retard seulement si l'échéance est passée. Une seule de ces conditions relâchée et la relance part sur une facture déjà payée.

Un jeton, une société, des droits variables

Les jetons de l'API sont liés à une société, et leurs droits ne sont pas tous les mêmes : un jeton de cabinet ne se substitue pas à un jeton de société, l'adresse de base et le périmètre diffèrent. Notre première commande sur un jeton inconnu est donc GET /me, qui renvoie l'utilisateur, la société et la liste des droits accordés.

Ensuite, chaque ressource est testée au lieu d'être supposée. Un endpoint qui répond 403 n'est pas une panne de l'API : c'est un droit absent, et le code doit le dire clairement plutôt que de s'arrêter sur une pile d'appels. Les listes clients ont d'ailleurs leurs propres pièges : une fiche client peut exposer un champ emails rempli alors que la route des contacts renvoie une liste vide. On se fie au champ, pas à la liste.

Le jeton vit dans un fichier hors du dépôt, lisible par le seul compte qui en a besoin. Une commande qui tourne en tâche de fond n'écrit jamais un jeton dans un journal, et encore moins dans un message. C'est une ligne de conduite, pas une case cochée une fois.

Écrire : les erreurs qui coûtent

Côté écriture, l'API est précise et peu indulgente. Trois constats nous ont fait ajouter des contrôles avant envoi.

  • Le prix unitaire est attendu en texte. Un nombre JSON renvoie une erreur de validation, la chaîne "649.00" passe. Le message d'erreur ne dit pas « vous avez mis un nombre », il dit que la ligne n'appartient à aucune des formes acceptées.
  • Les sections de devis ne se déclarent qu'à la création. Les rangs commencent à un, et chaque ligne porte le rang de sa section. Les ajouter ensuite par une mise à jour est refusé, et pour ajouter des lignes le champ doit être un objet avec une liste create, pas un tableau.
  • Un devis ne se supprime pas. La suppression par l'API n'existe pas. Un devis créé par erreur avec une bonne remise en règle est un document de plus dans les comptes. D'où la règle : la commande affiche le récapitulatif complet et attend une confirmation avant création.

Le cycle d'une facture, dans l'ordre

Facture client : un brouillon d'abord, modifiable, avec son PDF provisoire. Puis l'émission, qui attribue le numéro légal et fige le document. Puis l'envoi, aux adresses enregistrées sur la fiche client ou à une liste fournie. L'envoi juste après l'émission peut répondre que le PDF n'est pas encore prêt : la bonne réaction est d'attendre quelques secondes et de réessayer, pas de renvoyer une seconde fois.

Conséquence pratique : une facture émise n'est plus éditable. Tout ce qui peut être faux doit être vérifié au stade du brouillon, prix, remise, TVA applicable, adresse. C'est l'étape où l'agent apporte le plus, et celle où il doit être le plus lent.

Ce que l'agent ne fait pas

Il ne choisit pas un prix, ne décide pas d'un geste commercial, et ne relance pas un client de sa propre initiative. Ces décisions engagent la société, elles restent humaines. Il prépare le récapitulatif, signale une échéance dépassée, rédige une relance que quelqu'un relit.

Et il ne devine pas les règles. Une consigne qui n'est écrite nulle part est réinventée à chaque session, avec une variante différente. Nos règles vivent dans des fichiers versionnés : format du récap, seuil d'alerte, ton de la relance, TVA applicable. Les corriger une fois suffit.

Ce que ça change, et ce que ça ne change pas

Le gain n'est pas dans une vitesse brute qu'on pourrait afficher. Il est dans la régularité : un récapitulatif daté chaque matin, des retards visibles sans avoir à ouvrir l'outil comptable, des brouillons préparés pendant qu'on répond au téléphone. Et dans la trace : chaque action laisse une ligne, donc une erreur se retrouve au lieu de se deviner.

Ce qui ne change pas : la comptabilité reste la comptabilité. Un récap ne remplace ni un rapprochement bancaire, ni la validation d'un cabinet. L'agent prépare le travail ; il ne le signe pas.

Les limites, assumées

  • Les jetons expirent. Une date de renouvellement se surveille, sinon la panne arrive un matin de clôture.
  • Le PDF n'est pas instantané. Un envoi trop rapide après émission doit être retenté, pas dupliqué.
  • Le débit est limité par jeton. Lecture et écriture méritent des jetons séparés pour ne pas se bloquer mutuellement.
  • Un devis est indélébile par l'API. La prudence se met avant la création, pas après.

Rien de tout cela n'est spectaculaire. C'est le prix d'un agent qu'on laisse tourner sur des données qui comptent : des droits au minimum, un journal, et une validation humaine aux endroits qui engagent.

Reprendre contact

Un projet comparable ? Nous répondons aux questions techniques en rendez-vous, avec les mêmes chiffres que dans ces articles.

L'offre correspondante : l'IA vocale et l'automatisation de tâches.

Appeler maintenant Devis gratuit