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\FlowFactoryFlow\IpFlow\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 :
- Dispersion — une adresse IP par identité d'agent
-
Parallélisme —
MaxIpStrategylimite le travail en cours -
Sac partagé — chaque agent écrit un
AgentResultdansRunStore -
Rejoindre — après
await(),SummaryAgentlit le sac de manière synchrone. - 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é
La pull request Symfony AI #2363 est un exemple technique externe, et non une dépendance de Darkwood. 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 -
CostLedgerSubscriberpeut é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
Top comments (0)