Article

Mistral Workflows : orchestrer des applications IA durables en Python

Schéma Mistral Workflows montrant le workflow, les activités, le worker et l’historique durable

Table des matières

TL;DR

  • Un workflow décrit quoi exécuter, dans quel ordre et selon quelles décisions.
  • Une activité réalise le travail qui touche le monde extérieur : appel LLM, requête HTTP, base de données, fichier ou outil.
  • Le code du workflow doit être déterministe, car Mistral peut le rejouer à partir de son historique pour reconstruire son état.
  • Un worker exécute le code applicatif. Le quickstart officiel demande de le démarrer avec make start-worker.
  • Les échecs temporaires d’une activité peuvent être repris automatiquement selon sa politique de retry.
  • Les signaux modifient l’état sans réponse, les queries lisent l’état et les updates modifient l’état avec une réponse attendue.
  • Mistral Workflows convient aux traitements IA multi-étapes et longs. Pour un appel LLM isolé, une fonction classique reste souvent plus simple.

La vidéo de référence

La vidéo de Xavki introduit Mistral Workflows par la démonstration. Elle met notamment en évidence une question structurante : où s’arrête le service d’orchestration et où tourne le code de l’utilisateur ? La réponse passe par trois objets qu’il faut distinguer dès le départ : le workflow, l’activité et le worker.

La vidéo dure environ 28 minutes et a été publiée le 31 mai 2026. Sa description renvoie vers les dépôts GitLab de Xavki, mais ne désigne pas de dépôt compagnon propre à cette démonstration. Le dépôt courant est celui de la formation vLLM ; il sert ici de contexte éditorial, pas de source pour inventer un exemple Workflows absent du chapitre.

Mistral Workflows, c’est quoi exactement ?

Mistral Workflows est une couche d’orchestration durable pour construire des applications en plusieurs étapes. Elle ne se limite pas à enchaîner deux fonctions. Elle conserve un historique d’événements qui permet de reconstruire l’état d’une exécution après le redémarrage d’un worker, une panne d’infrastructure ou une erreur transitoire.

Le modèle mental minimal est le suivant :

Workflow
  décide de l'ordre, des branches et des attentes
       |
       +--> Activité : appeler un LLM
       +--> Activité : lire ou écrire dans une base
       +--> Attente   : recevoir une validation humaine
       +--> Activité : publier le résultat

Worker
  exécute le code du workflow et de ses activités

Plateforme Mistral
  planifie, enregistre l'historique et coordonne les exécutions

Un workflow peut vivre quelques secondes, plusieurs jours ou plusieurs mois. La documentation le présente comme la couche de composition de l’application : il définit ce qu’il faut faire et quand le faire. Les activités définissent comment effectuer le travail concret.

Cette distinction est particulièrement utile avec l’IA générative. Un processus réel ne se résume pas toujours à « envoyer un prompt puis afficher la réponse ». Il peut devoir télécharger un document, en extraire des champs, demander une validation, reprendre plus tard, appeler un système métier et conserver la trace de chaque étape.

Le vrai problème que résout un workflow durable

Une chaîne Python naïve fonctionne tant que tout réussit dans le même processus :

télécharger -> extraire -> valider -> enregistrer

Mais plusieurs questions apparaissent rapidement :

  • que se passe-t-il si le processus tombe après l’extraction ?
  • faut-il recommencer l’appel LLM et le facturer une seconde fois ?
  • comment attendre une approbation pendant deux jours ?
  • comment reprendre sans dupliquer une écriture en base ?
  • comment connaître l’étape courante depuis un tableau de bord ?
  • comment appliquer des retries différents à un appel réseau et à une opération métier ?

Un orchestrateur durable transforme ces questions en éléments explicites du modèle d’exécution. L’historique des événements devient la référence pour savoir ce qui a déjà eu lieu. Le workflow peut être rejoué afin de reconstruire son état, tandis que les effets externes restent isolés dans les activités.

« Durable » ne veut donc pas dire que le même processus Python reste vivant indéfiniment. Cela signifie que l’état logique de l’exécution peut survivre au processus qui l’exécute.

Workflow et activité : la séparation essentielle

La documentation officielle donne une règle simple :

Élément Responsabilité Exemples
Workflow Orchestration, état, décisions, temporisation branchement, boucle, attente d’approbation
Activité Travail réel et effets de bord appel LLM, HTTP, SQL, lecture de fichier
Worker Exécution du code utilisateur charge les workflows et attend les tâches
Plateforme Coordination et historique planification, événements, reprise

Le workflow est le cerveau de l’orchestration. Il doit rester rapide et déterministe. L’activité est l’unité de travail isolée, susceptible d’être retentée après un échec.

Prenons le traitement d’une facture :

  1. le workflow demande à une activité de télécharger le PDF ;
  2. une activité appelle un modèle pour extraire les données structurées ;
  3. le workflow examine le montant ;
  4. au-dessus d’un seuil, il attend un signal d’approbation ;
  5. une dernière activité écrit l’opération dans le logiciel comptable.

Le téléchargement, l’appel LLM et l’écriture comptable touchent des systèmes externes : ce sont des activités. Le seuil, la branche conditionnelle et l’attente définissent le déroulement : ils appartiennent au workflow.

Pourquoi le workflow doit rester déterministe

Mistral reconstruit l’état d’une exécution par replay. Le code du workflow est réexécuté depuis le début et chaque décision est comparée à l’historique déjà enregistré. À conditions initiales identiques, il doit produire la même suite d’opérations.

Ces appels ordinaires sont donc dangereux directement dans un workflow :

datetime.now()
uuid.uuid4()
random.random()

Ils peuvent renvoyer une nouvelle valeur lors du replay. Le SDK fournit des versions compatibles avec l’historique :

from mistralai.workflows import workflow

current_time = workflow.now()
request_id = workflow.uuid4()
rand_value = workflow.random()

Une lecture de fichier, une requête HTTP ou un accès à une base ne doit pas davantage être placé dans le workflow. Le résultat extérieur peut changer entre deux exécutions du même code. Cette opération doit être déplacée dans une activité et son résultat devient alors un événement connu de l’orchestrateur.

La documentation indique que le SDK active par défaut un bac à sable qui intercepte des API non déterministes connues. Il est possible de désactiver cette protection, mais Mistral recommande de la conserver : sans elle, l’erreur peut n’apparaître qu’au prochain replay, longtemps après l’appel fautif.

Découvrez  Ponytail : faire ecrire moins de code aux agents IA sans supprimer les garde-fous

Premier projet Mistral Workflows

Le quickstart officiel demande un compte Mistral, Python 3.12 ou plus récent et uv. La création du squelette s’effectue avec :

uvx mistralai-workflows-cli@latest setup

L’assistant crée un projet Python configuré avec le SDK, un exemple minimal et des commandes pour lancer le worker et déclencher une exécution. Il demande également une clé API Mistral. Une clé n’étant affichée qu’une fois lors de sa génération, elle doit être traitée comme un secret et ne doit pas être ajoutée au dépôt Git.

L’exemple généré suit cette structure :

from pydantic import BaseModel
import mistralai.workflows as workflows


class HelloInput(BaseModel):
    name: str = "World"


@workflows.activity()
async def greet(name: str) -> str:
    return f"Hello, {name}! Welcome to Mistral Workflows."


@workflows.workflow.define(
    name="hello-world",
    workflow_display_name="Hello World",
    workflow_description="A minimal hello-world workflow.",
)
class HelloWorkflow:
    @workflows.workflow.entrypoint
    async def run(self, input: HelloInput) -> str:
        return await greet(input.name)

Même si l’activité greet est volontairement simple, l’exemple matérialise déjà la séparation :

  • HelloWorkflow.run orchestre l’exécution ;
  • greet est l’activité appelée ;
  • HelloInput définit et valide l’entrée ;
  • les décorateurs rendent ces objets découvrables par le SDK.

Le worker est ensuite démarré depuis la racine du projet :

make start-worker

Il se connecte à l’API Mistral, enregistre le workflow et attend des tâches. Une exécution peut ensuite être lancée depuis la Console Mistral, le SDK Python, l’API ou la commande fournie par le Makefile du projet généré.

Le worker doit-il tourner chez vous ?

C’est une conséquence importante de l’architecture montrée par le quickstart : make start-worker lance un processus qui exécute le code de l’utilisateur. Pour une démonstration, il peut tourner sur le poste local. Pour un service continu, il faut prévoir un environnement d’exécution adapté et maintenir le worker disponible.

La plateforme Mistral coordonne les exécutions et conserve leur progression, mais cela ne transforme pas automatiquement le code Python local en fonction hébergée sans infrastructure. Le worker reste la capacité de calcul qui reçoit les tâches et exécute workflows et activités.

Cette séparation apporte plusieurs avantages :

  • le code peut accéder aux ressources et réseaux autorisés dans votre environnement ;
  • les dépendances Python et la capacité de calcul restent contrôlées par l’équipe ;
  • plusieurs workers peuvent servir le même déploiement pour augmenter la capacité ;
  • un redémarrage ne fait pas perdre la position logique du workflow.

Elle entraîne aussi des responsabilités : déploiement, secrets, supervision, mises à jour, dimensionnement et disponibilité des workers. Il faut donc intégrer le worker à la plateforme d’exécution de l’organisation plutôt que de laisser un terminal de développeur ouvert en production.

Entrées, sorties et validation avec Pydantic

La méthode marquée @workflow.entrypoint accepte des types sérialisables en JSON : primitives, dictionnaires ou modèles Pydantic. Avec un unique BaseModel, ses champs deviennent directement les clés de l’entrée :

from pydantic import BaseModel


class ReportParams(BaseModel):
    report_type: str
    include_details: bool = False

L’entrée correspondante est :

{
  "report_type": "daily",
  "include_details": true
}

Pour accepter plusieurs formes structurées, la documentation autorise une union de modèles Pydantic. Elle conseille extra="forbid" afin d’éviter qu’un objet comportant des champs inattendus corresponde silencieusement au mauvais modèle.

En revanche, une union mélangeant directement un BaseModel et un type primitif, comme PromptInput | str, n’est pas prise en charge. Un RootModel nommé permet de représenter explicitement ce besoin et de générer un schéma plus clair.

Signaux, queries et updates

Un workflow long doit pouvoir communiquer avec le reste du système pendant son exécution. Mistral distingue trois mécanismes :

Mécanisme Modifie l’état Attend une réponse Usage typique
Signal Oui Non approbation, callback externe
Query Non Oui statut, progression, valeur calculée
Update Oui Oui changement validé avec confirmation

Signal : envoyer un événement sans attendre

Un signal est un message « fire-and-forget ». Une validation humaine peut, par exemple, faire passer self.approved à True. Le workflow attend ensuite cette condition avec workflow.wait_condition.

Query : lire l’état sans le modifier

Une query expose le statut courant à un client ou à un tableau de bord. Elle ne doit provoquer aucun effet de bord. On peut l’utiliser pour lire un pourcentage de progression, l’étape active ou un résultat intermédiaire.

Update : modifier et recevoir une confirmation

Une update ressemble à un signal, mais son appelant attend que le workflow traite la demande et retourne une réponse. Elle convient à un changement de configuration qui doit être validé et persisté avant de poursuivre.

Le choix dépend donc du contrat attendu, pas seulement de la donnée transportée.

Retries, idempotence et effets de bord

Les activités peuvent être automatiquement retentées. Cette propriété est utile pour les erreurs réseau temporaires, mais elle impose de réfléchir aux effets de bord.

Imaginons une activité qui facture une carte bancaire. Si le service distant reçoit la requête mais que la réponse se perd, le worker peut croire que l’appel a échoué et le recommencer. Sans clé d’idempotence, le client risque d’être facturé deux fois.

Une activité correctement conçue doit converger vers le même résultat observable lorsqu’elle est rejouée après un échec partiel. Les approches courantes sont :

  • fournir une clé d’idempotence stable au service externe ;
  • utiliser un identifiant métier unique avec contrainte en base ;
  • vérifier l’état existant avant une écriture ;
  • séparer les opérations qui peuvent être retentées de celles qui demandent une compensation ;
  • régler les timeouts et retries selon la nature de l’opération.

La durabilité de l’orchestrateur ne dispense pas de concevoir correctement les intégrations. Elle rend au contraire leurs contrats de reprise plus visibles.

Fonctionnalités utiles pour les scénarios longs

Attendre une condition

workflow.wait_condition suspend le workflow jusqu’à ce qu’une condition devienne vraie, souvent après un signal ou une update. D’après la documentation, cette attente ne consomme pas de ressources de calcul en continu. Un timeout peut lever TimeoutError si l’événement n’arrive pas à temps.

Planifier avec cron

Une définition de planning peut associer une ou plusieurs expressions cron et une entrée à un workflow. Ce mécanisme convient aux rapports quotidiens ou aux synchronisations périodiques.

Lancer des workflows enfants

Un workflow peut exécuter un autre workflow et attendre son résultat. Avec wait=False, le parent poursuit immédiatement. Il faut alors comprendre la politique de fermeture du parent : la documentation indique que la valeur par défaut est ABANDON, ce qui laisse l’enfant continuer si le parent se termine. Une politique telle que TERMINATE change explicitement ce comportement.

Continue-as-new

Une exécution très longue peut accumuler un historique volumineux. continue-as-new réinitialise cet historique tout en conservant la continuité logique du traitement. Ce mécanisme devient utile pour une boucle indéfinie ou lorsqu’on approche la limite d’événements.

Reset

Le reset redémarre une exécution depuis un événement donné de son historique avec la version courante du code. Les événements antérieurs sont recopiés, tandis que les progrès postérieurs au point choisi sont perdus. La documentation recommande de corriger la cause du problème avant d’effectuer le reset et d’enregistrer une raison explicite.

Limites à connaître avant de concevoir

La documentation des concepts fondamentaux mentionne plusieurs limites importantes :

Limite Valeur documentée Conséquence
Temps de code entre deux activités 2 secondes déplacer le calcul lourd dans une activité
Entrée d’un workflow 2 Mo déporter les gros objets vers un stockage blob
Sortie d’un workflow 2 Mo retourner une référence plutôt que le contenu massif
Historique d’exécution 51 200 événements ou 50 Mo prévoir continue-as-new pour les longues boucles
Timeout d’exécution par défaut 1 heure déclarer une durée supérieure si nécessaire
Découvrez  Agent Sandbox Kubernetes SIG : des sandboxes isolees et stateful pour vos agents AI

Le execution_timeout couvre la durée totale du workflow, retries et itérations continue-as-new inclus. Il ne remplace pas les timeouts propres aux activités, comme start_to_close_timeout ou schedule_to_close_timeout.

Ces valeurs sont celles de la documentation consultée pour cet article. Elles peuvent évoluer ; il faut les vérifier avant de figer une architecture ou un SLO.

Activité régulière, locale ou session sticky

Mistral documente trois modes d’activité :

Mode Isolation Partage en mémoire Bon usage
Activité régulière processus isolé non API, logique complexe, retries
Activité locale pas de processus isolé non applicable calcul ou lookup inférieur à une seconde
Session sticky processus isolé oui modèle chargé ou connexion réutilisée

L’activité régulière constitue le choix par défaut pour un effet externe ou un traitement nécessitant une reprise robuste. L’activité locale évite le coût de planification pour une opération très courte, mais n’offre pas la même isolation. Une session sticky épingle une série d’activités au même worker afin de réutiliser une ressource en mémoire, par exemple un modèle ML déjà chargé.

Ce dernier cas peut intéresser les applications IA qui hébergent elles-mêmes un modèle ou un composant coûteux à initialiser. Il faut néanmoins gérer la consommation mémoire et le cycle de vie du worker.

Mistral Workflows et vLLM : deux couches différentes

Le dépôt courant documente vLLM, notamment la tokenisation, les API de complétion et le serving de modèles. Mistral Workflows répond à un autre niveau du système.

Technologie Problème principal
vLLM servir efficacement un modèle de langage
Mistral Workflows orchestrer durablement un processus applicatif

Un workflow peut appeler un endpoint d’inférence dans une activité. Cet endpoint pourrait être fourni par Mistral ou par un serveur vLLM selon l’architecture choisie. L’activité encapsulerait alors l’appel réseau, tandis que le workflow déciderait quand l’appeler, quoi faire du résultat et comment poursuivre après une attente ou une erreur.

Il ne faut donc pas présenter Mistral Workflows comme un remplaçant de vLLM, ni vLLM comme un orchestrateur durable. Les deux outils peuvent occuper des couches complémentaires.

Quand utiliser Mistral Workflows ?

Mistral Workflows devient pertinent lorsque le processus comporte plusieurs de ces propriétés :

  • plusieurs appels externes avec des politiques de reprise ;
  • une exécution longue ou une attente humaine ;
  • des branches métier dépendant de résultats intermédiaires ;
  • un besoin de statut et d’historique ;
  • des callbacks provenant d’autres systèmes ;
  • une reprise après redémarrage sans repartir de zéro ;
  • une planification récurrente ;
  • des sous-processus réutilisables.

Exemples : traitement documentaire, validation de contrat, pipeline éditorial, génération de rapport, investigation avec approbation humaine, synchronisation multi-systèmes ou agent durable qui attend de nouveaux événements.

Quand ne pas l’utiliser ?

Un workflow durable ajoute un modèle d’exécution, un worker et des contraintes de déterminisme. Ce coût n’est pas justifié pour chaque fonction.

Une implémentation plus simple peut suffire si :

  • le besoin se limite à un appel LLM synchrone ;
  • toutes les étapes se terminent rapidement dans une seule requête ;
  • aucune reprise fine n’est nécessaire ;
  • l’application accepte de recommencer entièrement après un échec ;
  • une file de tâches existante couvre déjà le besoin ;
  • l’équipe ne souhaite pas exploiter des workers supplémentaires.

Le bon critère n’est pas « utilisons-nous de l’IA ? », mais « avons-nous besoin d’un état d’orchestration durable et observable ? ».

Bonnes pratiques de conception

Garder le workflow léger

Placez dans le workflow les décisions et l’enchaînement. Déplacez le calcul lourd et tout I/O vers les activités.

Rendre les activités idempotentes

Supposez qu’une activité puisse être retentée après une réponse perdue. Utilisez des identifiants métier stables et des opérations qui ne dupliquent pas les effets.

Versionner prudemment le code

Une exécution démarrée avec un historique existant peut être rejouée avec une nouvelle version du worker. Une modification qui change la séquence de commandes peut provoquer une non-détermination. Les évolutions doivent donc préserver la compatibilité des exécutions actives ou prévoir une stratégie de migration.

Ne pas transporter de gros documents dans l’historique

Stockez les PDF, images ou grands résultats dans un stockage objet et transmettez une référence. Cela réduit la taille des événements et respecte la limite de charge utile.

Séparer timeout global et timeout d’activité

Le timeout du workflow définit sa durée de vie maximale. Les timeouts d’activité encadrent chaque opération. Un appel LLM et une validation humaine ne doivent pas partager aveuglément les mêmes valeurs.

Superviser workers et exécutions

Surveillez au minimum les workers disponibles, les files d’attente, les activités en échec, le nombre de retries, les timeouts et l’âge des exécutions. L’historique facilite le diagnostic, mais ne remplace pas les alertes opérationnelles.

Protéger les secrets

Les clés API et identifiants de bases appartiennent à un gestionnaire de secrets ou à l’environnement de déploiement. Ils ne doivent pas être codés dans le workflow, enregistrés dans Git ou renvoyés dans les sorties.

Liens utiles

FAQ sur Mistral Workflows

Qu’est-ce qu’un workflow Mistral ?

Un workflow Mistral est une orchestration durable écrite en Python. Il coordonne des activités, conserve un état logique, attend des événements et peut reprendre après un redémarrage grâce à son historique d’exécution.

Quelle différence entre un workflow et une activité ?

Le workflow décide de l’ordre, des branches et des attentes. Une activité réalise un travail concret avec effets de bord, comme appeler un LLM, lire un fichier, envoyer une requête HTTP ou écrire en base.

Pourquoi le code d’un workflow doit-il être déterministe ?

La plateforme peut rejouer le code afin de reconstruire son état depuis l’historique. Si le même code prend une décision différente pendant ce replay, l’historique et l’exécution divergent.

Où placer un appel à un modèle de langage ?

Dans une activité. Un appel LLM est un I/O externe, potentiellement lent et non déterministe. Le workflow appelle cette activité puis orchestre le traitement du résultat.

Le worker doit-il rester actif ?

Un worker disponible est nécessaire pour exécuter les tâches. Le quickstart le lance localement avec make start-worker. Pour un usage continu, il faut le déployer dans un environnement supervisé et adapté à la disponibilité attendue.

Que se passe-t-il si le worker redémarre ?

L’historique conservé par la plateforme permet de reconstruire l’état logique du workflow par replay. Le traitement reprend à partir de la progression connue, sous réserve que le nouveau code reste compatible et déterministe.

Signal, query ou update : lequel choisir ?

Utilisez un signal pour notifier sans attendre de réponse, une query pour lire l’état sans le modifier et une update pour modifier l’état tout en attendant une confirmation ou un résultat.

Peut-on attendre une validation humaine plusieurs jours ?

Oui, un workflow peut attendre un événement externe. Il faut toutefois configurer un execution_timeout compatible, car la valeur par défaut documentée est d’une heure.

Les activités sont-elles exécutées exactement une fois ?

Il ne faut pas concevoir les effets externes sur cette hypothèse. Une activité peut être rejouée après un échec partiel ou une réponse perdue. Elle doit être idempotente ou utiliser un mécanisme empêchant les doublons.

Mistral Workflows remplace-t-il vLLM ?

Non. vLLM sert des modèles de langage ; Mistral Workflows orchestre des processus applicatifs. Un workflow peut appeler un serveur vLLM depuis une activité, mais les deux produits ne résolvent pas le même problème.

Le code de cet article a-t-il été exécuté dans le dépôt courant ?

Non. Le chapitre courant est consacré à la tokenisation vLLM et ne contient pas de projet Mistral Workflows. Les commandes et extraits reproduisent les modèles de la documentation officielle ; ils n’ont pas été exécutés faute de projet compagnon et d’identifiants Mistral fournis.

Conclusion

Mistral Workflows apporte un modèle clair aux applications IA qui ne peuvent pas être réduites à un appel API : une orchestration déterministe, des activités isolées pour les effets externes, un historique durable et des workers chargés d’exécuter le code.

Le point central n’est pas la syntaxe des décorateurs, mais la séparation des responsabilités. Le workflow décide. L’activité agit. Le worker exécute. La plateforme coordonne et conserve l’historique. Cette architecture permet de traiter proprement les retries, les attentes humaines, les redémarrages et l’observation d’un processus long.

Pour démarrer, le quickstart officiel et son exemple hello-world suffisent à visualiser le cycle complet. Avant d’aller en production, il faut ensuite travailler les sujets moins visibles dans une démo : idempotence des activités, compatibilité des versions, secrets, supervision, limites de charge utile et exploitation des workers.

Explorer les formations Xavki

Pour apprendre dans l ordre, repartez depuis la roadmap ou une playlist thematique.