Darkwood Blog Blog
  • Articles
  • Veille
  • Releases
  • CrĂ©ateurs
fr
  • de
  • en
Connexion
  • Blog
  • Articles
  • Veille
  • Releases
  • CrĂ©ateurs

🙏 Quand l'orchestration garantit l'exĂ©cution, et non la valeur

le 9 août 2026

Connectez-vous pour réagir à cet article

🚀 1

Que se passe-t-il lorsqu'un systÚme d'orchestration exécute un travail sans valeur ajoutée ?

Il ne s'agit pas d'une question rhétorique. C'est une expérience d'ingénierie.

J'ai mis en place un pipeline multi-agents sur Darkwood Flow. Cinq agents effectuent un travail utile. Puis j'en ai ajouté un sixiÚme.

Il n'a aucun outil. Il ne connaßt rien du code source. Il n'examine jamais les demandes de fusion. Il ne corrige jamais les bugs. Il se contente de dire :

Merci.

ou:

Ça a l'air bien.

Le systÚme d'orchestration en était parfaitement satisfait.

C'est ce qui s'est avĂ©rĂ© ĂȘtre la partie intĂ©ressante.

L'activité n'est pas un débit

Cinq agents participent à l'expérience et effectuent des tùches utiles : récupération de la documentation, lecture des métadonnées Git/PR, exploration des fonctionnalités PHP, extraction des principes de l'IA open source et calcul d'un cadre de coût. Un sixiÚme agent, ThanksAgent, n'analyse ni ne transforme aucune donnée, ne tient compte d'aucun contexte et renvoie un signal social constant.

Et pourtant, le sixiĂšme agent encore :

  • est programmĂ©
  • occupe la concurrence
  • gĂ©nĂšre des Ă©vĂ©nements Flow
  • apparaĂźt dans l'observabilitĂ©
  • consomme des messages
  • contribue Ă  la surcharge d'orchestration
  • donne l'impression d'activitĂ©

Valeur produite = 0.

C’est là la principale distinction de l’article :

L'activité ne correspond pas au débit.

L'exécution n'est pas une valeur.

L'orchestration peut garantir l'exécution des tùches. Elle ne peut pas garantir leur utilité.

Et la phrase qui devrait figurer à cÎté de chaque tableau de bord multi-agents :

Le planificateur ne peut pas faire la distinction entre le travail productif et le travail performatif.

Si nous voulons que les systÚmes d'agents optimisent la valeur plutÎt que l'activité, la valeur doit faire partie du modÚle observable de l'environnement d'exécution.

Cinq agents utiles et un inutile

La démo se trouve dans un projet console Symfony 8 : thanks-agent sous content/thanks-agent. Il ne s'agit pas d'une présentation du framework Symfony, mais d'une démonstration de chargement de flux Darkwood avec une interface en ligne de commande minimale.

Chaque agent est une implémentation de l'interface JobInterface de Flow. Les pondérations des valeurs sont explicites :

Agent Valeur RĂŽle
FetchDocumentationAgent +25 Charger des extraits de code source
GithubAgent +40 Métadonnées PR / git
PHPAgent +30 Sonde de capacité PHP 8.6
MozillaAgent +20 Principes de l'IA open source
CostAgent +15 Analyse coûts-résultats
SummaryAgent +15 SynthĂšse Fan-in
ThanksAgent +0 Toujours "Merci." / "Ça a l'air bien." / "Bon travail."

Le logiciel Thanks Agent est en lui-mĂȘme d'un ennui presque agressif :

final class ThanksAgent extends AbstractAgent
{
    private const RESPONSES = ['Thanks.', 'Looks good.', 'Good job.'];

    protected function produce(AgentPacket $packet): array
    {
        $output = self::RESPONSES[array_rand(self::RESPONSES)];

        return [
            'output' => $output,
            'tokens' => 2,
            'messages' => 28, // noise: many empty acknowledgements
            'didWork' => false,
            'payload' => [
                'analyzed' => false,
                'transformed' => false,
                'expertise' => null,
                'contextHeld' => false,
            ],
        ];
    }
}

Sa disponibilité est excellente. Il n'a jamais entraßné de régression. Il n'a jamais rien produit non plus.

Effectuez la comparaison :

php bin/console thanks-agent:compare --both --save

La machine le planifiera, le mesurera et le signalera — avec le mĂȘme sĂ©rieux qu'elle accorde aux agents qui travaillent rĂ©ellement.

Que consomme exactement un agent ?

C'est là que la blague devient ingénierie.

Le « coût » ne se résume pas à un seul chiffre. Dans un environnement multi-agents, un participant peut consommer :

Dimension Ce que cela signifie
Emplacement du planificateur En cours de développement sous MaxIpStrategy
Heure réelle Latence visible par l'homme
Attente d'E/S Flux, sockets, HTTP
Processeur Analyse syntaxique, notation, sérialisation
Jetons Utilisation du modÚle (simulée dans cette démo)
Messages Accusés de réception informels, échanges sur les outils
Contexte Tranches de mémoire / invite / index
Journalisation / traçage Volume d'observabilité
Examen humain File d'attente d'attention et de décision
Capacité de validation Tests, validations, acceptation

L'agent Thanks utilise trÚs peu de ressources CPU ou de jetons. Il consomme néanmoins des emplacements de planification, des messages, des événements et de l'énergie narrative.

Voilà le schéma organisationnel en miniature : la visibilité et la signalisation sont plus faciles à mesurer que les résultats, les systÚmes tendent donc à récompenser ce qui est bruyant, présent et constamment « vert ».

Les humains le font. Les Ă©quipes le font. L'intĂ©gration continue le fait. Les agents le feront — sauf si les modĂšles d'exĂ©cution le valorisent explicitement.

Darkwood Flow tel qu'il existe aujourd'hui

Avant d'affirmer que Flow « résout le problÚme des agents », précisez ce qu'est Flow.

Darkwood Flow (darkwood/flow, PHP ≄ 8.5) est un pipeline asynchrone linĂ©aire inspirĂ© de FBP :

flowchart LR
    IP[Ip] --> Job[Job]
    Job --> Driver[Driver]
    Driver --> Events[PUSH PULL POP ASYNC POOL]
    Events --> Job

ModĂšle conceptuel :

Ip → Job → Driver

Vous composez des Ă©tapes avec FlowFactory, envoyez des paquets d'informations et utilisez await() jusqu'Ă  ce que le flux soit vidĂ©. La concurrence se traduit par de nombreuses adresses IP en transit, limitĂ©es par des stratĂ©gies telles que MaxIpStrategy — et non par un DAG classique de branches et de jointures.

Flow n'est pas ReactPHP. Ce n'est pas Amp. Il ne prĂ©tend pas les remplacer. Des pilotes optionnels peuvent ĂȘtre installĂ©s sur ces backends ; la question intĂ©ressante pour Darkwood est :

De quel minimum de machinerie d'exécution Flow a-t-il besoin pour orchestrer un véritable travail PHP asynchrone ?

ÉlĂ©ments principaux utilisĂ©s dans la dĂ©mo :

  • Flow\FlowFactory
  • Flow\Ip
  • Flow\JobInterface
  • Flow\Driver\FiberDriver (par dĂ©faut)
  • Flow\Driver\StreamSelectDriver (tĂąches du gĂ©nĂ©rateur + stream_select)
  • Flow\IpStrategy\MaxIpStrategy
  • ÉvĂ©nements : PUSH, PULL, POP, ASYNC, POOL — et, nouveautĂ©, COMPLETE / ERROR

Deux facteurs sont importants pour cet article.

FiberDriver exécute chaque tùche dans une instance PHP Fiber. Les délais coopératifs appellent Fiber::suspend(). Il s'agit du chemin par défaut pour thanks-agent:compare. Un problÚme pratique est apparu lors des mesures : la résolution des délais Fiber dans le pilote actuel est suffisamment grossiÚre pour que les tùches d'agent nécessitant de nombreuses attentes se regroupent prÚs des limites d'une seconde. Il s'agit d'une caractéristique du pilote, et non d'une affirmation concernant l'« intelligence de l'agent ».

StreamSelectDriver est diffĂ©rent : les tĂąches peuvent renvoyer un Generator qui produit des jetons d'attente — waitReadable, waitWritable, waitDelay — et le pilote multiplexe ces attentes avec la fonction native stream_select(). C'est le chemin empruntĂ© par le Flow Runner de thanks-agent:bench-io et par l'option --driver=stream_select lors de la comparaison. Il est considĂ©rĂ© comme expĂ©rimental dans la documentation de Flow, et c'est normal : l'expĂ©rience Thanks Agent nĂ©cessite une vĂ©ritable attente de disponibilitĂ©, et non une simulation avec usleep.

MaxIpStrategy gĂšre la concurrence. Elle encapsule une autre stratĂ©gie IP (FIFO linĂ©aire par dĂ©faut) et refuse de traiter des paquets supplĂ©mentaires tant que processing >= max. Il s'agit de concurrence d'exĂ©cution, et non de capacitĂ© de supervision. Confondre les deux peut mener Ă  une situation oĂč six terminaux et un seul utilisateur Ă©puisĂ©.

flowchart TB
    subgraph fanOut [Fan-out via multiple Ips]
        Dispatch[Push one Ip per agent]
        Dispatch --> Doc[FetchDocumentation]
        Dispatch --> Gh[Github]
        Dispatch --> Php[PHP]
        Dispatch --> Moz[Mozilla]
        Dispatch --> Cost[Cost]
        Dispatch --> Thanks[Thanks]
    end
    subgraph fanIn [Fan-in outside the graph API]
        Doc --> Store[RunStore]
        Gh --> Store
        Php --> Store
        Moz --> Store
        Cost --> Store
        Thanks --> Store
        Store --> Summary[SummaryAgent]
        Summary --> Board[Scoreboard]
    end

Cette honnĂȘtetĂ© est importante. La dĂ©mo ressemble Ă  une fonction de dispersion/rassemblement. Flow n'expose pas encore de moteur DAG gĂ©nĂ©ral. PrĂ©tendre le contraire reviendrait Ă  appliquer le comportement de Thanks Agent Ă  la documentation.

Flow ne sait pas ce que signifie « utile »

Un environnement d'exécution comprend la sémantique opérationnelle :

  • pousser / tirer / Ă©clater
  • rĂ©partition asynchrone
  • profondeur de la piscine
  • succĂšs / erreur
  • durĂ©e

Il ne sait pas automatiquement si la chaßne « Merci. » a créé une valeur.

La valeur doit donc ĂȘtre modĂ©lisĂ©e explicitement.

Dans la dĂ©mo, App\Model\AgentId::valueWeight() et App\Instrumentation\ValueRegistry attribuent des scores de production. didWork: false force ThanksAgent Ă  obtenir un score nul mĂȘme si quelqu'un oublie ultĂ©rieurement la table de pondĂ©ration.

IntĂ©grĂ© Ă  Flow pour ĂȘtre rĂ©utilisé :

namespace Flow\Instrumentation;

final readonly class ValueTag
{
    public function __construct(
        public string $label,
        public int $value,
    ) {}
}

ValueTag est une primitive. Le tableau de bord des agents, qui contient des avis, reste dans l'application. Cette séparation est intentionnelle : tout ce qui est spécifique aux agents reste dans thanks-agent ; tout ce qui concerne l'intégration des jeunes diplÎmés en comptabilité dans Flow.

Coût sans valeur

Coûts simulés, planification réelle

Information importante : dans cette expérience, les coûts des jetons sont simulés. Le registre de démonstration utilise un taux fixe.

public const RATE_PER_1K_TOKENS = 0.002;

Les E/S correspondent à des fichiers de configuration et à des paires de sockets différées, et non à des factures API LLM en temps réel. Les temps d'exécution et le nombre d'événements Flow sont mesurés. Les montants indiqués sont fournis à titre indicatif afin de mieux visualiser l'ampleur du problÚme.

La dĂ©mo connecte l'instrumentation au bus d'Ă©vĂ©nements existant de Flow — elle n'invente pas de systĂšme de tĂ©lĂ©mĂ©trie parallĂšle :

final class MetricsSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            Event::PUSH => ['onPush', -100],
            Event::PULL => ['onPull', -100],
            Event::POP => ['onPop', -100],
            Event::ASYNC => ['onAsync', -100],
        ];
    }

    public function onPull(PullEvent $event): void
    {
        // FiberDriver polls PULL in a tight loop; only meter productive pulls.
        if ([] !== $event->getIps()) {
            $this->ledger->recordPull();
        }
    }
}

Cette garde onPull est en elle-mĂȘme une leçon : si vous considĂ©rez chaque sondage de boucle active comme du « travail », votre tableau de bord FinOps devient une fiction inspirĂ©e de la boucle d’évĂ©nements.

Exécution de la comparaison (PHP 8.5.4, FiberDriver)

À partir des rapports gĂ©nĂ©rĂ©s sous var/reports/ (compare-*-20260808-144317.json) :

Métrique Sans remerciements Avec remerciements Delta
Valeur 145 145 0
Coût (simulé) 0,012474 0,022094 +0,00962
Messages 19 48 +29
Jetons (simulés) 887 897 +10
Temps d'exécution (ms) 958,47 1002,48 +44
Flux push/pull/pop/asynchrone 5 / 5 / 5 / 5 6 / 6 / 6 / 6 +1 chacun

ThanksAgent seul dans cette exécution :

Champ Valeur
Valeur 0
Messages 28
Jetons 2
Coût 0,008904
a travaillé faux
Sortie "Bon travail."

Résultats utiles inchangés. Ressources augmentées. Variation de valeur nulle.

VoilĂ  toute la thĂšse sous forme de tableau.

Le verdict affiché au tableau d'affichage n'est pas un argument marketing ; il est imprimé par le commandement :

Le sixiÚme agent n'apporte aucune valeur ajoutée ; il consomme toujours des ressources en matiÚre de planification, de contexte, de journalisation et d'observabilité.

CoĂ»t par requĂȘte vs coĂ»t par rĂ©sultat utile

La facturation basĂ©e sur les requĂȘtes brutes est une unitĂ© de mesure imprĂ©cise. La facture d'une IA reflĂšte davantage le produit du dĂ©bit, de la consommation et du comportement du tokenizer (et des nouvelles tentatives) que le prix affichĂ© sur une grille tarifaire. L'unitĂ© pertinente est le coĂ»t par rĂ©sultat positif, et non le coĂ»t par requĂȘte.

ThanksAgent rend la pathologie évidente :

  • Le coĂ»t de la demande peut ĂȘtre minime
  • rĂ©sultats utiles = 0
  • le coĂ»t par rĂ©sultat utile tend vers l'infini

Un agent bon marché qui ne produit rien n'est pas bon marché. C'est du bruit subventionné.

Le registre Flow promu prĂ©sente la mĂȘme forme de mĂ©trique :

$ledger->recordComplete('GithubAgent', tokens: 100);
$ledger->recordError('CostAgent', tokens: 32);

$snapshot = $ledger->snapshot();
// totals.costPerSuccessfulOutcome = totalCost / successes

La supervision est également une ressource rare

Une fois que l'expérience peut exécuter six agents sans problÚme, une autre question se pose : l'ajout de capacité d'exécution finit par déplacer le goulot d'étranglement.

Distinguer soigneusement :

Capacité Ce qu'elle mesure
Concurrence des modĂšles Nombre d'appels de modĂšles possibles
Concurrence d'exécution Nombre de tùches que Flow maintient en cours d'exécution
Débit utile Résultats acceptés / fusionnés / validés
Supervision humaine Nombre de contextes ouverts qu'une personne peut suivre
Capacité de validation Bande passante d'acceptation/rejet automatisée

Les agents ne se fatiguent pas. Les superviseurs, si. Déplacer le travail vers des environnements de test distants permet de redistribuer la supervision au sein d'une équipe ; cela ne crée pas une attention infinie.

La mĂ©taphore organisationnelle Ă©merge de l'environnement d'exĂ©cution lui-mĂȘme. Si le planificateur accepte sans problĂšme un participant se contentant de dire « Ça a l'air bien », les humains seront finalement sollicitĂ©s pour surveiller ce participant Ă©galement — ou pour l'ignorer tant qu'il occupe des ressources (travail en cours, journaux, tableaux de bord). Les agents parallĂšles crĂ©ent un inventaire : branches, demandes de fusion, questions ouvertes, contextes inachevĂ©s. L'humain devient le bus de donnĂ©es. L'attente n'est pas forcĂ©ment du gaspillage ; c'est l'intolĂ©rance aux terminaux inactifs qui engendre la fatigue.

Analysez la situation selon la thĂ©orie des contraintes : lorsqu’on supprime un goulot d’étranglement, les stocks s’accumulent devant le suivant. Le parallĂ©lisme des agents rĂ©duit le temps d’attente des machines, mais peut accroĂźtre celui des opĂ©rateurs. La loi de Little sert d’avertissement informel : plus de travail en cours Ă  un rythme de service fixe signifie des dĂ©lais de livraison plus longs, sans pour autant prĂ©tendre que cette dĂ©monstration a Ă©tĂ© rĂ©alisĂ©e Ă  l’échelle d’une usine. Ce que l’expĂ©rience montre est plus simple : on peut ajouter un agent qui augmente le nombre de messages et d’évĂ©nements de planification sans modifier la valeur globale.

ConsĂ©quence opĂ©rationnelle pour la politique d'orchestration : privilĂ©gier une tĂąche bien dĂ©finie avec un processus d'acceptation automatisĂ© plutĂŽt que quatre tĂąches vagues qui renvoient toutes les questions Ă  la mĂȘme personne. Le modĂšle multi-agents n'est viable que si la validation ne l'est pas.

Cessez de mesurer le nombre de tùches en cours d'exécution. Mesurez plutÎt le nombre de décisions en attente.

C’est pourquoi Flow livre dĂ©sormais un budget de ressources, et non une superstition :

use Flow\Budget\SupervisionBudget;

$budget = new SupervisionBudget(5);

if (!$budget->tryAcquire()) {
    // reassign, queue, or refuse — do not silently spawn more agents
}

$concurrency = $budget->clampConcurrency($requested);

max = 5 est une valeur par défaut pratique pour les démonstrations, et non une loi fondamentale. L'abstraction importe plus que la valeur : la concurrence est une ressource limitée et supervisée, et l'environnement d'exécution doit rendre l'épuisement explicite.

Feuille de route (non dĂ©ployĂ©e) : MĂ©triques de profondeur de la file d’attente de dĂ©cision — questions ouvertes en attente de traitement humain, histogrammes des temps de rĂ©ponse, contrĂŽles de validation avant diffusion. La dĂ©mo dĂ©montre la nĂ©cessité ; Flow ne mesure pas encore le temps d’attente humain.

Disperser/rassembler sans prétendre que Flow est un DAG

L'atelier d'orchestration de la dĂ©mo est le vĂ©ritable cƓur de l'architecture :

$flow = $this->flowFactory->create(static function () use ($execute, $errorJob, $concurrency, $dispatcher) {
    yield [
        'job' => $execute,
        'errorJob' => $errorJob,
        'ipStrategy' => new MaxIpStrategy($concurrency),
        'dispatcher' => $dispatcher,
    ];
}, ['driver' => $driver]);

foreach ($agentIds as $agentId) {
    $flow(new Ip(new AgentPacket($agentId, $runId)));
}
$flow->await();

// Fan-in outside the driver loop
$summaryAgent->executeSync(new AgentPacket(AgentId::Summary, $runId));

Ce que cela fait concrÚtement :

  1. Dispersion — une adresse IP par identitĂ© d'agent
  2. ParallĂ©lisme — MaxIpStrategy limite le travail en cours
  3. Sac partagĂ© — chaque agent Ă©crit un AgentResult dans RunStore
  4. Rejoindre — aprùs await(), SummaryAgent lit le sac de maniùre synchrone.
  5. Tableau de bord — rapport au niveau de l'application, et non un nƓud du graphe de flux
flowchart LR
    Ips[Multiple Ips] --> Stage[ExecuteAgentJob]
    Stage --> Store[RunStore]
    Store --> Summary[SummaryAgent executeSync]
    Summary --> Report[RunReport]

Pourquoi ne pas parler de DAG ? Parce que la topologie publique de Flow reste une liste chaßnée d'étapes. L'état de l'application correspond à l'entrée. C'est suffisant pour une démonstration, mais insuffisant pour gérer les jointures typées, les échecs partiels par branche ou la compilation de graphes réutilisables.

Une véritable API de jointure/DAG serait justifiée lorsque :

  • Plusieurs producteurs doivent se synchroniser avec un schĂ©ma, et non avec un ensemble modifiable partagĂ©.
  • L'annulation doit se propager Ă  toutes les succursales
  • Le mĂȘme graphique est rĂ©utilisĂ© pour tous les produits, et non pour une seule dĂ©monstration.

En attendant, l'honnĂȘtetĂ© vaut mieux que les schĂ©mas idĂ©alistes.

L'asynchrone attend efficacement

La deuxiĂšme commande :

php bin/console thanks-agent:bench-io --save

compare quatre exĂ©cuteurs sur les mĂȘmes six tĂąches nĂ©cessitant beaucoup d'attente (cinq utiles + Merci), en utilisant des sockets diffĂ©rĂ©s synthĂ©tiques sur PHP 8.5.4 :

Coureur Mur ms Valeur Statut
séquentiel 599,9 130 ligne de base
stream_select 166,8 130 ~3,6× amĂ©lioration du mur
php86_poll — — ignorĂ© (Io\Poll\Context indisponible sur 8.5.4)
flow_stream_select 178,7 130 Flow StreamSelectDriver (~+12 ms par rapport à la sélection brute)

Contexte : E/S synthétiques locales, coûts de jetons simulés, ThanksAgent inclus, valeur toujours 130 (pas de résumé dans l'ensemble de tùches du banc d'E/S).

L'exécution séquentielle est facile à comprendre et coûteuse en temps réel lorsque la tùche est soumise à des temps d'attente. stream_select() multiplexe l'état de disponibilité. Le StreamSelectDriver de Flow encapsule les tùches génératrices qui génÚrent des jetons d'attente (waitReadable / waitWritable / waitDelay).

L'API Poll native de PHP 8.6 (Io\Poll\*) est la primitive la plus intéressante à long terme : elle utilise des backends de type epoll/kqueue lorsqu'ils sont disponibles, typés avec Time\Duration. Point important : l'interrogation n'est pas une boucle d'événements. La planification reste du ressort de l'utilisateur.

La rĂ©ponse de Flow est une interface lĂ©gĂšre — et non un clone d'Amp :

interface PollerInterface
{
    /**
     * @param list<resource> $read
     * @param list<resource> $write
     * @return array{0: list<resource>, 1: list<resource>}
     */
    public function poll(array $read, array $write, float $timeoutSeconds): array;

    public function name(): string;
}

ImplĂ©mentations actuelles : StreamSelectPoller, NativePollPoll (utilisĂ© par dĂ©faut en l’absence de Poll dans PHP 8.6). Flow\IO\Duration fait le lien avec Time\Duration lorsqu’il est prĂ©sent. clamp() est utilisĂ© dans SupervisionBudget lorsqu’il est disponible.

flowchart TB
    Jobs[Jobs] --> Scheduler[Flow Driver / Scheduler]
    Scheduler --> Poller[PollerInterface]
    Poller --> OS[OS mux stream_select or Io_Poll]
    OS --> Ready[Ready I/O]
    Ready --> Scheduler
    Scheduler --> Cont[Job continuation]

Conclusion modeste seulement :

Dans ce test de performance local, le multiplexage des tĂąches Ă  forte attente a permis de rĂ©duire le temps d'exĂ©cution d'environ 600 ms en mode sĂ©quentiel Ă  environ 167 ms avec stream_select, tandis que le pilote StreamSelect de Flow est restĂ© dans le mĂȘme ordre de grandeur (environ 179 ms). La fonction Poll de PHP 8.6 n'a pas Ă©tĂ© testĂ©e car elle n'est pas disponible sur la version 8.5.4.

Aucune affirmation selon laquelle Flow serait « plus rapide que React/Amp ». Ces bibliothÚques n'ont pas été testées.

L'interrogation n'est pas non plus une valeur

Voici le rappel éditorial.

Un meilleur systÚme de sondage peut exécuter plus rapidement des tùches inutiles.

Améliorer epoll, Fibers, les limites de concurrence ou la densité des agents cloud ne résout pas le problÚme de Thanks Agent. Cela ne fait qu'amplifier ce que le systÚme optimise.

Les performances amplifient tout ce que le systĂšme optimise.

Si l'objectif d'optimisation est l'activité, vous obtenez plus d'activité.

Si l'objectif d'optimisation est d'obtenir des résultats positifs, vous obtenez un débit utile.

Le test d'E/S attribue toujours la valeur 0 Ă  ThanksAgent tout en lui allouant un emplacement de planification. Multiplexeur plus rapide, mĂȘme nombre d'emplacements vides.

Le chemin malheureux doit ĂȘtre facturĂ©

Voici l'information pertinente :

Les flux de donnĂ©es peuvent inclure des mĂ©tadonnĂ©es d'utilisation et gĂ©nĂ©rer une erreur (par exemple, en cas de dĂ©passement du dĂ©bit maximal). Si la comptabilitĂ© ne se finalise que dans le cas d'un fonctionnement normal, le fournisseur vous a quand mĂȘme facturĂ© et votre comptabilitĂ© est erronĂ©e.

Orientation de la PR : terminaux mutuellement exclusifs — complet vs erreur — avec Ă©couteurs d’erreur explicites.

Flow reflÚte désormais ce cycle de vie au niveau de la couche événementielle :

  • Flow\Event::COMPLETE → CompleteEvent
  • Flow\Event::ERROR → ErrorEvent
  • Flow\Instrumentation\CostLedger::recordComplete / recordError
  • CostLedgerSubscriber peut Ă©couter les deux
flowchart TB
    Start[Start] --> Exec[Execute]
    Exec --> Success[Success]
    Exec --> Failure[Failure]
    Exec --> Abandon[Abandon / Cancel]
    Success --> Complete[CompleteEvent]
    Failure --> Error[ErrorEvent]
    Abandon --> Hole[Accounting hole today]
    Complete --> Ledger[CostLedger]
    Error --> Ledger

Commande de démonstration :

php bin/console thanks-agent:run --simulate-error --with-thanks

L'agent de coûts est contraint de suivre le chemin de défaillance ; les jetons sont toujours enregistrés. La valeur utile diminue ; le registre ne prétend pas que la défaillance soit sans conséquence.

Limitation explicitement mentionnĂ©e : l’abandon ou l’annulation d’une tĂąche sans exception constitue toujours une faille de conception. La dĂ©mo ne contient que App\Orchestration\CancellationTicket, un stub, et non le cycle de vie complet de Flow. Tant que l’abandon ne sera pas gĂ©rĂ© comme un terminal Ă  part entiĂšre, FinOps risque de ne pas dĂ©tecter ce cas. La PR de Symfony AI est attentive Ă  ce type de faille ; nous devrions l’ĂȘtre Ă©galement.

Le contexte est aussi une ressource

Un agent de codage ne « comprend » pas comme par magie l'intégralité d'un dépÎt. Il comprend la partie qu'il indexe et dont il fournit les outils. Une couverture linguistique incomplÚte produit des résultats incohérents. La qualité de l'index et la qualité du modÚle sont des variables distinctes.

Pour Flow, l'affirmation « agent exécuté avec succÚs » est insuffisante. Une attribution d'exécution sérieuse nécessite en définitive :

  • modĂšle
  • outils
  • contexte / fraĂźcheur de la carte de code
  • rapide
  • politique de vĂ©rification
  • coĂ»t
  • rĂ©sultat

Non livré : un portage de CodeMap. Non livré : un AgentRouter qui considĂšre le prix comme un champ parmi d’autres, tels que le taux d’achĂšvement, la latence, la modalitĂ©, le coĂ»t de vĂ©rification et l’éligibilitĂ© Ă  la concurrence. Ces Ă©lĂ©ments restent des Ă©lĂ©ments de la feuille de route, imposĂ©s par l’expĂ©rimentation : une fois que l’on peut mesurer la valeur par rapport au coĂ»t, on se rend compte Ă  quel point le simple fait de dire « exĂ©cution rĂ©ussie » est peu informatif.

La neutralitĂ© vis-Ă -vis des fournisseurs est l'autre contrainte majeure. Il est prĂ©fĂ©rable de maĂźtriser la couche d'orchestration plutĂŽt que de louer une pile verticale fermĂ©e. Le rĂŽle de Flow est de rester neutre vis-Ă -vis des fournisseurs : un environnement Symfony natif oĂč les modĂšles sont interchangeables, et non l'identitĂ© du produit.

Coût par résultat positif

Associer l'économie des résultats, le routage et ThanksAgent.

Stratégie Apparence bon marché Souvent le cas
Prix le plus bas par jeton Sur la ligne de facture Erreur si les nouvelles tentatives explosent
Le plus petit modĂšle toujours Sur la grille tarifaire Erreur si le taux d'achĂšvement s'effondre
La plupart des agents en parallÚle Sur le tableau de bord ProblÚme si la file d'attente de décision explose
ThanksAgent Sur jetons (2) Infini par résultat utile

Un modÚle plus coûteux qui s'exécute correctement une seule fois peut surpasser un modÚle bon marché qui échoue trois fois. Une exécution séquentielle plus lente avec validation automatisée peut surpasser un essaim parallÚle qui confie cinq demandes de fusion à un seul humain.

Le champ costPerSuccessfulOutcome de la démo simule des calculs. C'est la forme qui importe pour les systÚmes de production : terminaux de comptage, tentatives de récupération d'attributs, division par les résultats pertinents.

Ce que cela a changé dans Darkwood Flow

Déjà implémenté / promu dans Flow

Vérifié dans darkwood/src/Darkwood/Component/Flow/ :

Primitif RĂŽle
Flux\Instrumentation\Liste des coûts Comptabilité des coûts en fonction des résultats
Flow\Instrumentation\CostLedgerSubscriber ÉvĂ©nement → pont de registre
Flow\Instrumentation\ValueTag Étiquette de valeur de production
Flow\Event::COMPLETE / ERROR Cycle de vie du terminal
Flow\Event\CompleteEvent / ErrorEvent Charges utiles du terminal
Flux\Budget\Budget de supervision En cours / porte de supervision
Flow\IO\PollerInterface Abstraction de multiplexage légÚre
Flow\IO\StreamSelectPoller stream_select backend
Flow\IO\NativePollPoller Sondage PHP 8.6 avec solution de repli
Flow\IO\Duration Assistant secondes → DurĂ©e native si disponible

Documentation : Page d’instrumentation des flux dans l’arborescence de documentation des composants. Les tests couvrent le registre, le budget et le comportement de repli du systùme d’interrogation.

Une nuance importante concernant le cĂąblage est Ă  noter pour les lecteurs qui clonent la dĂ©mo : l'application Symfony utilise toujours principalement App\Instrumentation\MetricsSubscriber pour la mesure via PUSH/PULL/POP/ASYNC. Les Ă©vĂ©nements COMPLETE/ERROR et CostLedgerSubscriber de Flow sont des primitives prĂȘtes Ă  ĂȘtre adoptĂ©es ; le chemin --simulate-error de la dĂ©mo enregistre actuellement les erreurs dans le registre de l'application. Il s'agit lĂ  de la migration en cours, oĂč « la dĂ©mo prouve que Flow est le leader », et non d'une affirmation selon laquelle chaque terminal de l'interface de ligne de commande (CLI) dĂ©clenche dĂ©jĂ  un Ă©vĂ©nement CompleteEvent.

L'application de fonctions partielles de PHP 8.6 mérite une brÚve mention : lier une configuration fixe aux fonctions appelables du pipeline ($invoke = $platform->invoke($model, ?)) pourrait simplifier le langage Flow DSL une fois la version 8.6 devenue la norme. Le code source n'en dépend pas encore. L'intégrer de force serait purement formel, voire paradoxal.

Démontré mais toujours au niveau de l'application (thanks-agent)

  • TĂąches d'agent (ThanksAgent, 
)
  • ValueRegistry / expĂ©rience utilisateur du tableau de bord
  • Sac de dispersion RunStore
  • App\Instrumentation\CostLedger + MetricsSubscriber (version dĂ©mo, compatible avec les agents)
  • Interface de ligne de commande : thanks-agent:compare, thanks-agent:bench-io, thanks-agent:run
  • Ébauche de CancellationTicket

Travaux futurs (feuille de route, et non affirmations de présence)

  • Pilote Poll natif PHP 8.6 intĂ©grĂ© Ă  la boucle await (au-delĂ  de l'assistant Poller)
  • Politique d'annulation et d'abandon de terminal de premiĂšre classe
  • MĂ©triques de la file d'attente de dĂ©cision
  • Graphe rĂ©el / nƓuds de jonction si la demande de dispersion/rassemblement se renforce
  • AgentRouter, CodeMap, ModelPort
  • Application de fonctions partielles sous forme de DSL Ă  pipeline allĂ©gĂ© lorsque PHP 8.6 est la version de base

Ne surestimez pas les objectifs. L'objectif de Thanks Agent était d'imposer un premier niveau de vérité : la valeur et le coût font partie intégrante du vocabulaire de l'environnement d'exécution.

Fermeture

Nous savons déjà comment faire courir les agents.

Les fibres optiques, les collecteurs de données, les environnements de test cloud et les interfaces de ligne de commande multi-agents seront de plus en plus performants pour générer des données dynamiques. Ces données sont faciles à visualiser sur un tableau de bord. Elles sont faciles à mettre en valeur. Par conception, un agent Thanks optimise les données dynamiques.

Le problĂšme le plus difficile consiste Ă  dĂ©cider quel travail devrait exister — et Ă  prouver, avec des chiffres que l'environnement d'exĂ©cution peut observer, que ce travail a produit des rĂ©sultats qui justifient l'utilisation des ressources.

Lorsqu'un systÚme d'orchestration accepte sans problÚme d'exécuter un participant qui ne contribue en rien, la prochaine optimisation ne consistera probablement pas en l'ajout d'un autre agent.

C'est une meilleure définition de la valeur.

Si nous voulons que les systÚmes d'agents optimisent la valeur plutÎt que l'activité, la valeur doit faire partie du modÚle observable de l'environnement d'exécution.

AprĂšs Thanks Agent, la mission de Darkwood Flow est plus claire : continuer Ă  orchestrer le travail PHP asynchrone avec le moins de machinerie possible — et refuser de considĂ©rer les Ă©changes entre agents comme du dĂ©bit.

Références

Matériel technique

FrĂ©dĂ©ric Bouchery — J'ai arrĂȘtĂ© d'exĂ©cuter plusieurs agents (En cours de dĂ©veloppement, chaĂźnes de validation, dĂ©cision humaine comme contrainte)

  • Mozilla — StratĂ©gie d'IA open source (propriĂ©tĂ© de la couche d'orchestration)

Les idées concernant les index de code source, le routage des agents et la variance des factures d'IA circulent largement dans l'industrie ; cet essai les utilise comme contraintes d'ingénierie, et non comme commentaires sur une publication particuliÚre.

Artefacts de Darkwood

  • DĂ©mo : https://github.com/matyo91/thanks-agent
  • Diapositives : https://github.com/matyo91/slidewire

Connectez-vous pour réagir à cet article

🚀 1

Site

  • Plan du Site
  • Contact
  • Mentions lĂ©gales

Network

  • Hello
  • Blog
  • Apps
  • Photos

Social

Darkwood 2026, tous droits réservés