đ Quand l'orchestration garantit l'exĂ©cution, et non la valeur
le 9 août 2026
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\JobInterfaceFlow\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Ă©
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âCompleteEventFlow\Event::ERRORâErrorEventFlow\Instrumentation\CostLedger::recordComplete/recordErrorCostLedgerSubscriberpeut Ă©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