Agent Frameworks

Construire une orchestration déterministe d'agents avec Temporal et les workflows

Les applications d'intelligence artificielle modernes peinent souvent avec la fiabilité. Bien que les grands modèles de langage (LLM) excellent en créativité et raisonnement, ils sont intrinsèquement probabilistes et sans état. Lors de l'enchaînement d'appels LLM multiples, de requêtes API externes et d'approbations humaines, la complexité explose. Un simple timeout réseau ou une erreur API transitoire peut laisser votre système dans un état incohérent, créant des agents « zombies » qui ont payé pour le calcul mais n'ont produit aucune valeur.

C'est ici que l'orchestration déterministe devient critique. En combinant la puissance probabiliste de l'IA avec les garanties déterministes des moteurs de workflows comme Temporal, vous pouvez construire des systèmes d'agents durables, observables et corrects. Cet article explore comment architecturer des agents IA robustes en utilisant les Workflows Temporal.

Le problème des chaînes d'agents naïves

Dans une implémentation naïve, un agent pourrait exécuter une séquence d'étapes :

  1. Récupérer l'intention de l'utilisateur.
  2. Appeler le LLM pour l'analyse.
  3. Interroger une base de données.
  4. Appeler une API tierce.
  5. Envoyer une réponse.

Si l'étape 4 échoue en raison d'un micro-coupure réseau, un microservice traditionnel pourrait réessayer indéfiniment ou échouer complètement, entraînant une incohérence des données. Plus important encore, parce que l'exécution est éphémère, vous perdez le contexte nécessaire pour reprendre l'agent là où il s'était arrêté. Vous ne pouvez pas « mettre en pause et reprendre » facilement un flux de requête HTTP standard. Temporal résout ce problème en persistant l'état de chaque exécution d'activité dans son stockage durable, permettant au workflow d'être reconstitué exactement comme il était avant l'échec.

Concepts clés : Activités et Workflows

Dans Temporal, la logique de votre agent est divisée en deux composants distincts :

  • Workflows : Le plan de contrôle. Ce sont des unités de code déterministes et à longue durée de vie qui définissent le flux logique (boucles, conditions, retours en arrière). Ils doivent être purement déterministes, ce qui signifie qu'aucun nombre aléatoire, date ou appel réseau ne doit être effectué directement à l'intérieur.
  • Activités : Le plan d'exécution. Ce sont les véritables travailleurs qui effectuent des tâches non déterministes comme appeler un LLM, interroger une base de données ou envoyer des e-mails. Les activités sont de courte durée et peuvent échouer.

Implémentation pratique

Regardons comment structurer un agent de recherche simple en utilisant Python. Nous définirons un workflow qui récupère des données, les traite via un LLM et gère les retours en arrière de manière élégante.

from temporalio.worker import Worker
from temporalio.activity import activity
from temporalio.workflow import workflow, define, current_datetime
from pydantic import BaseModel
import httpx

# Définir l'activité non déterministe
@activity.defn
async def fetch_context_data(url: str) -> dict:
    async with httpx.AsyncClient() as client:
        response = await client.get(url)
        response.raise_for_status()
        return response.json()

# Définir l'activité de traitement LLM
@activity.defn
async def llm_generate_summary(context: dict) -> str:
    # Logique pour appeler OpenAI ou un LLM local
    return "Résumé généré basé sur le contexte..."

# Définir le workflow déterministe
@workflow.defn
class ResearchAgentWorkflow:
    @workflow.run
    async def run(self, query_url: str) -> str:
        # Étape 1 : Récupérer les données avec retry automatique en cas d'échec
        data = await workflow.execute_activity(
            fetch_context_data,
            query_url,
            retry=workflow.Retry(max_attempts=3)
        )
        
        # Étape 2 : Traiter avec le LLM
        summary = await workflow.execute_activity(
            llm_generate_summary,
            data,
            schedule_to_close_timeout=timedelta(minutes=5)
        )
        
        return summary

Dans cet exemple, si fetch_context_data échoue, Temporal le réessaie automatiquement jusqu'à 3 fois. S'il continue d'échouer, le workflow peut être configuré pour passer à une activité impliquant un humain ou notifier un administrateur. L'avantage clé est que lorsque le worker revient en ligne, Temporal rejoue les événements d'historique pour reconstituer l'état du workflow, garantissant que llm_generate_summary n'est appelé qu'une fois les données récupérées avec succès.

Avantages du déterminisme

En imposant le déterminisme dans les workflows, vous bénéficiez de plusieurs avantages :

  • Durabilité : Votre agent survit aux redémarrages de serveur, aux déploiements et aux pannes réseau.
  • Déboguabilité : Temporal fournit une interface utilisateur où vous pouvez voir l'état exact de chaque étape du cycle de vie de l'agent, ce qui facilite le débogage des raisons pour lesquelles un agent est bloqué.
  • Gestion de la complexité : Vous pouvez implémenter des machines à états complexes, y compris des branches parallèles, des sous-workflows et des workflows enfants, sans gérer manuellement les verrous distribués ou l'état de la base de données.

Conclusion

Construire des agents IA ne consiste pas seulement en l'ingénierie des prompts ; c'est de l'ingénierie logicielle. À mesure que vos agents deviennent plus critiques pour les opérations commerciales, la nécessité de fiabilité devient primordiale. Temporal fournit la colonne vertébrale pour l'orchestration déterministe, permettant aux développeurs de se concentrer sur la logique IA tandis que le moteur gère la complexité de la durabilité, de la logique de retry et de la gestion de l'état. En adoptant ce modèle, vous transformez des scripts fragiles et éphémères en systèmes autonomes résilients et prêts pour la production.

Share: