Back to flin
flin

Agents parallèles dans le runtime FLIN

Le système d'agents parallèles de FLIN : exécution concurrente, passage de messages et le modèle de runtime basé sur les agents.

Juste A. Gnimavo (Thales) & Claude | March 26, 2026 5 min flin
EN/ FR/ ES
flinagentsconcurrencyparallelruntimeactor-model

La Session 011 a été la première fois que nous avons utilisé des agents parallèles pour construire FLIN. Pas des agents parallèles dans le runtime du langage -- des agents parallèles dans le processus de développement lui-même. Deux sous-agents Claude, s'exécutant simultanément sur des fichiers indépendants, produisant du code qui compilait ensemble en un système fonctionnel.

Mais cet article parle des deux sens d'« agents parallèles » : la méthodologie de développement qui nous a permis de construire FLIN plus vite que n'importe quel processus séquentiel ne le pourrait, et le modèle de concurrence basé sur les agents au sein du runtime FLIN qui permet l'exécution parallèle sans état mutable partagé.


Les agents de développement

Avant la Session 011, chaque fonctionnalité était construite séquentiellement. La Session 011 a changé l'approche. Trois tâches devaient se faire, et les tâches 1 et 3 étaient complètement indépendantes -- elles touchaient des fichiers différents sans état partagé.

Nous avons lancé deux sous-agents parallèles :

AGENT 1 (af469e7) : Créer src/vm/memory.rs
- Tâche : Implémenter la struct Heap et le GC (mark, sweep, collect)
- Fichier : src/vm/memory.rs (NOUVEAU)
- Résultat : 731 lignes, 22 tests GC

AGENT 2 (a307f11) : Créer tests/integration_vm.rs
- Tâche : Écrire des tests de bout en bout pour counter.flin
- Fichier : tests/integration_vm.rs (NOUVEAU)
- Résultat : 638 lignes, 18 tests

Les deux agents se sont exécutés simultanément sur des fichiers différents. L'agent principal a implémenté les opérations d'entités en attendant. Quand les trois ont terminé, le code a compilé du premier coup. Pas de conflits de merge. Pas d'échecs d'intégration.

La Session 011 a produit 1 500 lignes de code et 40 nouveaux tests -- environ le double de la production d'une session séquentielle.


Le modèle de concurrence basé sur les agents

Passons maintenant de comment nous avons construit FLIN à comment FLIN lui-même gère la concurrence.

Le runtime de FLIN utilise un modèle basé sur les agents inspiré du système d'acteurs d'Erlang et des goroutines de Go. Un agent est une unité indépendante de calcul avec son propre état, communiquant avec d'autres agents par passage de messages. Pas d'état mutable partagé. Pas de verrous. Pas de courses aux données.

rustpub struct Agent {
    id: AgentId,
    state: AgentState,
    mailbox: mpsc::Receiver<Message>,
    sender: mpsc::Sender<Message>,
}

pub enum Message {
    Request(HttpRequest),
    EntityChanged(String, ChangeType, EntityInstance),
    Timer(Duration),
    Shutdown,
}

impl Agent {
    pub async fn run(mut self) {
        loop {
            match self.mailbox.recv().await {
                Some(Message::Request(req)) => {
                    self.handle_request(req).await;
                }
                Some(Message::EntityChanged(entity_type, change, entity)) => {
                    self.handle_entity_change(&entity_type, change, &entity).await;
                }
                Some(Message::Timer(duration)) => {
                    self.handle_timer(duration).await;
                }
                Some(Message::Shutdown) | None => {
                    break;
                }
            }
        }
    }
}

Chaque agent a une boîte aux lettres (un mpsc::Receiver) et un expéditeur (un mpsc::Sender que d'autres agents utilisent pour lui envoyer des messages). La méthode run de l'agent boucle, traitant les messages un par un. Au sein d'un seul agent, l'exécution est séquentielle -- pas de préoccupations de concurrence. Entre les agents, l'exécution est concurrente -- ils s'exécutent sur des tâches Tokio séparées et communiquent uniquement par messages.

Cette conception élimine toute une classe de bogues :

  • Pas de courses aux données : chaque agent possède son état exclusivement.
  • Pas d'interblocages : les agents ne tiennent pas de verrous. Ils envoient des messages et continuent.
  • Pas d'état mutable partagé : les seules structures de données partagées sont les canaux de messages eux-mêmes, qui sont thread-safe par construction.

L'histoire parallèle

L'histoire des agents parallèles se déroule sur deux pistes : comment nous avons construit FLIN, et comment FLIN exécute les applications.

Dans les deux cas, le principe est le même : les tâches indépendantes devraient s'exécuter indépendamment. Que ce soit deux sous-agents Claude construisant deux fichiers Rust différents, ou deux agents gestionnaires HTTP traitant deux requêtes différentes, le pattern est l'isolement, l'indépendance et la coordination par messages.

La Session 011 a prouvé que les agents de développement parallèles pouvaient doubler le débit sans introduire d'échecs d'intégration. Le modèle d'agents du runtime FLIN promet la même chose pour l'exécution des applications : gestion concurrente des requêtes sans bogues d'état partagé.

Les deux sont des paris sur la même idée : le coût de la coordination est presque toujours plus élevé que le coût de la duplication. Cloner une valeur est moins cher que la protéger avec un mutex. Spécifier une tâche complètement est moins cher que déboguer un conflit de merge. L'isolement est moins cher que la communication.


Ceci est la partie 30 de la série « Comment nous avons construit FLIN », documentant comment un CEO à Abidjan et un CTO IA ont construit un langage de programmation à partir de zéro.

Navigation de la série : - [21] Construire une machine virtuelle à pile en Rust - [22] Gestion de la mémoire et ramasse-miettes - [23] Fermetures et fonctions d'ordre supérieur dans la VM - [24] Comment la VM exécute les vues - [25] La référence complète des opcodes FLIN - [26] Rechargement à chaud de modules en 42 ms - [27] Async et concurrence dans la VM - [28] Le moteur de réactivité - [29] Le premier rendu dans le navigateur - [30] Agents parallèles dans le runtime FLIN (vous êtes ici)

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles

Thales & Claude deblo

Le Step Zero ne suffisait pas : comment valider un constructeur sans valider le runtime a fait tomber toutes les sessions vocales de Déblo l’heure où nous avons livré le streaming caméra temps réel

La phase 14 a livré Déblo Eyes — streaming caméra temps réel via LiveKit vers Gemini Live native audio. Le premier deploy a fait tomber toutes les sessions vocales en production en quatre-vingt-dix secondes parce que notre Step 0 avait validé le constructeur sans exercer le runtime. Le build log de comment Déblo a eu des yeux, ce qu’un pré-vol incomplet a coûté, et quels points de polish ont été livrés ou reportés.

33 min May 20, 2026
debloclaude-opus-4.7claude-codegemini-live +25
Thales & Claude deblo

Le tiret cadratin qui a tué la production : comment un slogan marketing dans un header HTTP a fait tomber le chat de Déblo pendant 24 heures

Deux jours avant la soumission App Store, tout le produit chat de Déblo s’est cassé silencieusement. Pas de spinner, pas de toast, aucune erreur dans l’UI — juste un silence radio. L’incident de 24 heures se résumait à un seul « é » dans la valeur d’un header HTTP qui levait une UnicodeEncodeError avant qu’aucune requête vers OpenRouter ne quitte le backend. Post-mortem d’une fausse hypothèse, d’une trace Sentry, et d’un fix de six lignes qui a débloqué le lancement.

30 min May 19, 2026
debloclaude-opus-4.7claude-codeincident +19
Thales & Claude deblo

Six heures, d’une page blanche à la review Apple — Comment nous avons soumis Déblo à l’App Store, en direct

Marche à marche en direct de la soumission de Déblo à l’App Store iOS en six heures : ce que les validateurs d’Apple ont rejeté (un superscript Unicode), ce que nous avons corrigé (un Promotional Text gaspillé sur des marques tierces), et les rouages de l’ASO iOS que presque tout le monde rate.

30 min May 13, 2026
debloclaude-opus-4.7claude-codeapp-store +16