đ Wenn Orchestrierung die AusfĂŒhrung garantiert, nicht den Wert
vom 9. August 2026
Was passiert, wenn ein Orchestrierungssystem Aufgaben ausfĂŒhrt, die keinen Wert haben?
Das ist keine rhetorische Frage. Es handelt sich um ein technisches Experiment.
Ich habe eine Multiagenten-Pipeline in Darkwood Flow erstellt. FĂŒnf Agenten erledigen sinnvolle Aufgaben. Dann habe ich einen sechsten hinzugefĂŒgt.
Es verfĂŒgt ĂŒber keine Werkzeuge. Es weiĂ nichts ĂŒber die Codebasis. Es prĂŒft niemals Pull-Anfragen. Es behebt niemals Fehler. Es sagt einfach nur:
Danke.
oder:
Sieht gut aus.
Das Orchestrierungssystem war damit vollkommen zufrieden.
Das war im Nachhinein betrachtet der interessante Teil.
AktivitÀt ist nicht Durchsatz
FĂŒnf Agenten im Experiment leisten nĂŒtzliche Arbeit: Sie rufen Dokumentationen ab, lesen Git-/PR-Metadaten, prĂŒfen PHP-Funktionen, extrahieren Open-Source-KI-Prinzipien und berechnen eine Kostenstruktur. Ein sechster Agent â ââThanksAgent â analysiert nichts, transformiert nichts, speichert keinen Kontext und gibt ein konstantes soziales Signal zurĂŒck.
Doch der sechste Agent noch immer:
- wird eingeplant
- belegt gleichzeitig
- generiert Flow-Ereignisse
- erscheint in der Beobachtbarkeit
- verarbeitet Nachrichten
- trÀgt zum Orchestrierungsaufwand bei
- erweckt den Eindruck von AktivitÀt
Erzeugter Wert = 0.
Dies ist die zentrale Aussage des Artikels:
AktivitÀt ist nicht gleich Durchsatz.
Die AusfĂŒhrung ist kein Wert.
Die Orchestrierung kann gewĂ€hrleisten, dass die Arbeit ausgefĂŒhrt wird. Sie kann jedoch nicht garantieren, dass die Arbeit nĂŒtzlich ist.
Und die Zeile, die neben jedem Multiagenten-Dashboard stehen sollte:
Der Planer kann nicht zwischen produktiver Arbeit und ausfĂŒhrender Arbeit unterscheiden.
Wenn Agentensysteme auf Wert statt auf AktivitÀt optimieren sollen, muss der Wert Teil des beobachtbaren Modells der Laufzeitumgebung werden.
FĂŒnf nĂŒtzliche Agenten und ein nutzloser
Die Demo befindet sich in einem Symfony-8-Konsolenprojekt: thanks-agent unter content/thanks-agent. Es handelt sich nicht um eine Symfony-Framework-Tour, sondern um eine Demo zum Laden von Darkwood Flow mit einer schlanken CLI-Shell.
Jeder Agent ist eine Flow-JobInterface-Implementierung. Die Wertgewichte sind explizit:
| Agent | Wert | Rolle |
|---|---|---|
FetchDocumentationAgent |
+25 | QuelltextauszĂŒge laden |
GitHubAgent |
+40 | PR / Git-Metadaten |
PHPAgent |
+30 | PHP 8.6-FunktionsprĂŒfung |
MozillaAgent |
+20 | Open-Source-KI-Prinzipien |
CostAgent |
+15 | Ergebnis-Kosten-Framing |
SummaryAgent |
+15 | Fan-in-Synthese |
ThanksAgent |
+0 | Immer "Danke." / "Sieht gut aus." / "Gut gemacht." |
Der Thanks Agent selbst ist beinahe schon aggressiv langweilig:
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,
],
];
}
}
Es ist hervorragend verfĂŒgbar. Es hat noch nie einen RĂŒckschritt verursacht. Es hat auch noch nie etwas produziert.
FĂŒhre den Vergleich durch:
php bin/console thanks-agent:compare --both --save
Die Maschine wird es planen, messen und darĂŒber berichten â mit der gleichen Ernsthaftigkeit, die sie Agenten entgegenbringt, die tatsĂ€chlich arbeiten.
Was genau verbraucht ein Agent?
Hier wird der Witz zur Ingenieurskunst.
âKostenâ sind keine einzelne Zahl. In einer Multiagenten-Laufzeitumgebung kann ein Teilnehmer Folgendes verbrauchen:
| Dimension | Was bedeutet das? |
|---|---|
| Scheduler-Slot | In Arbeit unter MaxIpStrategy |
| Wanduhrzeit | FĂŒr Menschen sichtbare Latenz |
| E/A-Wartezeit | Streams, Sockets, HTTP |
| CPU | Parsing, Scoring, Serialisierung |
| Tokens | Modellnutzung (in dieser Demo simuliert) |
| Nachrichten | Plaudereien mit Danksagungen, Werkzeuggeplauder |
| Kontext | Speicher-/Eingabeaufforderungs-/Index-Ausschnitte |
| Protokollierung / Tracing | Observability-Volume |
| Menschliche ĂberprĂŒfung | Aufmerksamkeits- und Entscheidungswarteschlange |
| ValidierungskapazitÀt | Tests, Gates, Abnahme |
Der Dankesagent beansprucht kaum CPU- oder Token-Ressourcen. Er verbraucht jedoch weiterhin Scheduler-Slots, Nachrichten, Ereignisse und narrative Ressourcen.
Das ist das Organisationsmuster im Kleinen: Sichtbarkeit und Signalwirkung sind leichter zu messen als Ergebnisse, daher tendieren Systeme dazu, alles zu belohnen, was laut, prĂ€sent und stĂ€ndig âgrĂŒnâ ist.
Menschen tun dies. Teams tun dies. CI tut dies. Agenten werden dies tun â es sei denn, die Laufzeitmodelle legen dies explizit fest.
Darkwood Flow, wie er heute existiert
Bevor man behauptet, Flow âlöse Agentenproblemeâ, sollte man genau definieren, was Flow ĂŒberhaupt ist.
Darkwood Flow (darkwood/flow, PHP â„ 8.5) ist eine lineare, FBP-inspirierte asynchrone Pipeline:
flowchart LR
IP[Ip] --> Job[Job]
Job --> Driver[Driver]
Driver --> Events[PUSH PULL POP ASYNC POOL]
Events --> Job
Konzeptuelles Modell:
Ip â Job â Driver
Sie erstellen Phasen mithilfe von FlowFactory, senden Informationspakete und warten mit await(), bis der Datenstrom abgearbeitet ist. Die ParallelitĂ€t entspricht vielen gleichzeitig laufenden IP-Anfragen, begrenzt durch Strategien wie MaxIpStrategy â es handelt sich also nicht um einen herkömmlichen DAG mit Verzweigungen und Joins.
Flow ist nicht ReactPHP. Es ist nicht Amp. Es versucht auch nicht, diese zu ersetzen. Optionale Treiber können auf diesen Backends aufsetzen; die interessante Frage fĂŒr Darkwood ist:
Wie wenig Laufzeitinfrastruktur benötigt Flow, um echte asynchrone PHP-Operationen zu orchestrieren?
Im Demoprogramm verwendete Kernkomponenten:
Flow\FlowFactoryFlow\IpFlow\JobInterfaceFlow\Driver\FiberDriver(Standard)Flow\Driver\StreamSelectDriver(Generator-Jobs +stream_select)Flow\IpStrategy\MaxIpStrategy- Ereignisse:
PUSH,PULL,POP,ASYNC,POOLâ und neu:COMPLETE/ERROR
FĂŒr diesen Artikel sind zwei Fahrer relevant.
FiberDriver fĂŒhrt jeden Job innerhalb eines PHP-Fibers aus. Kooperative Verzögerungen rufen Fiber::suspend() auf. Dies ist der Standardpfad fĂŒr thanks-agent:compare. Bei Messungen zeigte sich eine praktische EinschrĂ€nkung: Die Auflösung der Fiber-Verzögerungen im aktuellen Treiber ist so grob, dass sich wartende Agentenjobs nahe der Ein-Sekunden-Grenze hĂ€ufen. Dies ist ein Treiberdetail und kein Hinweis auf die âIntelligenz des Agentenâ.
StreamSelectDriver funktioniert anders: Jobs können einen Generator zurĂŒckgeben, der Wartetoken â waitReadable, waitWritable, waitDelay â erzeugt. Der Treiber kombiniert diese WartevorgĂ€nge mit der nativen stream_select()-Funktion. Diesen Ansatz verwendet der Flow-Runner von thanks-agent:bench-io und --driver=stream_select beim Vergleich. In der Flow-Dokumentation ist dies als experimentell gekennzeichnet, was aber in Ordnung ist: Das Thanks-Agent-Experiment benötigt echtes Bereitschaftswarten, keine bloĂe usleep-Funktion.
MaxIpStrategy steuert die Parallelverarbeitung. Sie kapselt eine andere IP-Strategie (standardmĂ€Ăig lineares FIFO) und verhindert das Abrufen weiterer Pakete, solange processing >= max ist. Dies betrifft die Laufzeit-Parallelverarbeitung â nicht die ĂberwachungskapazitĂ€t. Die Verwechslung dieser beiden Aspekte fĂŒhrt dazu, dass man am Ende sechs Terminals und einen ĂŒberlasteten Mitarbeiter hat.
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
Ehrlichkeit ist wichtig. Die Demo Ă€hnelt Scatter/Gather. Flow stellt noch keine allgemeine DAG-Engine bereit. Das Gegenteil zu behaupten, hieĂe, das Verhalten des Thanks Agent auf die Dokumentation anzuwenden.
Flow weiĂ nicht, was ânĂŒtzlichâ bedeutet
Eine Laufzeitumgebung versteht operationelle Semantik:
- drĂŒcken / ziehen / knacken
- asynchrone Weiterleitung
- Beckentiefe
- Erfolg / Fehler
- Dauer
Es erkennt nicht automatisch, ob die Zeichenkette "Thanks." einen Wert erzeugt hat.
Der Wert muss also explizit modelliert werden.
In der Demo weisen App\Model\AgentId::valueWeight() und App\Instrumentation\ValueRegistry Produktionsbewertungen zu. didWork: false bewirkt, dass ThanksAgent null Punkte erhÀlt, selbst wenn spÀter jemand die Gewichtungstabelle vergisst.
Zur Wiederverwendung in den Flow-Prozess aufgenommen:
namespace Flow\Instrumentation;
final readonly class ValueTag
{
public function __construct(
public string $label,
public int $value,
) {}
}
ValueTag ist ein primitiver Datentyp. Die vordefinierte Agenten-Bewertungstabelle verbleibt in der Anwendung. Diese Aufteilung ist beabsichtigt: Alles Agentenspezifische verbleibt in thanks-agent; alles, was mit der AusfĂŒhrung von Buchhaltungsabsolventen zu tun hat, wird in Flow gespeichert.
Kosten ohne Wert
Simulierte Kosten, reale Terminplanung
Wichtiger Hinweis: In diesem Experiment werden die Tokenkosten simuliert. Das Demo-Ledger verwendet einen festen Zinssatz.
public const RATE_PER_1K_TOKENS = 0.002;
Die I/O-Daten bestehen aus Fixture-Dateien und verzögerten Socket-Paaren â nicht aus Live-API-Abrechnungen (LLM). Gemessen werden Laufzeiten und Flow-Ereignisse. Die DollarbetrĂ€ge dienen der Veranschaulichung, um das AusmaĂ des Problems sichtbar zu machen.
Die Demo verbindet die Instrumentierung mit dem bestehenden Ereignisbus von Flow â sie erfindet kein paralleles Telemetriesystem:
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();
}
}
}
Dieser onPull-Schutz ist an sich schon eine Lektion: Wenn man jede Abfrage in der Ereignisschleife als âArbeitâ misst, wird das FinOps-Dashboard zu einer Fantasie ĂŒber die Ereignisschleife.
Der Vergleichslauf (PHP 8.5.4, FiberDriver)
Aus generierten Berichten unter var/reports/ (compare-*-20260808-144317.json):
| Metrisch | Ohne Dank | Mit Dank | Delta |
|---|---|---|---|
| Wert | 145 | 145 | 0 |
| Kosten (simuliert) | 0,012474 | 0,022094 | +0,00962 |
| Nachrichten | 19 | 48 | +29 |
| Token (simuliert) | 887 | 897 | +10 |
| Wandzeit (ms) | 958,47 | 1002,48 | +44 |
| Flow push/pull/pop/async | 5 / 5 / 5 / 5 | 6 / 6 / 6 / 6 | +1 je |
ThanksAgent allein in diesem Durchlauf:
| Feld | Wert |
|---|---|
| Wert | 0 |
| Nachrichten | 28 |
| Tokens | 2 |
| Kosten | 0,008904 |
| didWork | false |
| Ausgabe | "Gut gemacht." |
Nutzleistung unverÀndert. Ressourcen erhöht. WertÀnderung null.
Das ist die gesamte These in einer Tabelle.
Die Ergebniszeile auf der Anzeigetafel ist kein Werbetext â sie wird vom Befehl ausgegeben:
Der sechste Agent bietet keinen Mehrwert; er verbraucht weiterhin Ressourcen fĂŒr Planung, Kontext, Protokollierung und Beobachtbarkeit.
Kosten pro Anfrage vs. Kosten pro nĂŒtzlichem Ergebnis
Die reine Abrechnung von Anfragen ist eine ungenaue Einheit. Die Kosten einer KI-Rechnung entsprechen eher dem Produkt aus GebĂŒhr, Verbrauch und Tokenisierungsverhalten (einschlieĂlich Wiederholungsversuchen) als dem angegebenen Preis auf einer Preisliste. Entscheidend sind die Kosten pro erfolgreichem Ergebnis, nicht die Kosten pro Anfrage.
ThanksAgent macht die Pathologie offensichtlich:
Die Anfragekosten können gering sein.
- nĂŒtzliche Ergebnisse = 0
- Die Kosten pro nĂŒtzlichem Ergebnis streben gegen unendlich
Ein billiges Mittel, das nichts bewirkt, ist nicht billig. Es ist subventionierter LĂ€rm.
Das hervorgehobene Flow-Ledger weist dieselbe Metrikform auf:
$ledger->recordComplete('GithubAgent', tokens: 100);
$ledger->recordError('CostAgent', tokens: 32);
$snapshot = $ledger->snapshot();
// totals.costPerSuccessfulOutcome = totalCost / successes
Auch die Aufsicht ist eine knappe Ressource.
Sobald das Experiment sechs Agenten problemlos ausfĂŒhren kann, stellt sich eine weitere Frage: Verschiebt die Erhöhung der AusfĂŒhrungskapazitĂ€t letztendlich den Flaschenhals?
SorgfÀltig unterscheiden:
| KapazitÀt | Was sie misst |
|---|---|
| Modellkonkurrenz | Wie viele Modellaufrufe können Sie gleichzeitig ausfĂŒhren? |
| LaufzeitparallelitĂ€t | Wie viele Jobs Flow gleichzeitig ausfĂŒhrt |
| Nutzbarer Durchsatz | Akzeptierte / zusammengefĂŒhrte / validierte Ergebnisse |
| Menschliche Aufsicht | Wie viele offene Kontexte eine Person verfolgen kann |
| ValidierungskapazitĂ€t | Bandbreite fĂŒr automatisierte Ablehnung/Annahme |
Mitarbeiter ermĂŒden nicht. Vorgesetzte schon. Die Verlagerung von Aufgaben in Remote-Umgebungen kann die Aufsicht innerhalb eines Teams neu verteilen; sie erzeugt aber keine unendliche Aufmerksamkeit.
Die Organisationsmetapher entsteht aus der Laufzeitumgebung selbst. Wenn der Scheduler problemlos einen Teilnehmer empfĂ€ngt, der lediglich âSieht gut aus.â meldet, werden Menschen irgendwann aufgefordert, diesen Teilnehmer ebenfalls zu beobachten â oder ihn zu ignorieren, solange er noch WIP, Protokolle und Dashboards belegt. Parallele Agenten erzeugen Inventar: Branches, Pull Requests, offene Fragen, halbfertige Kontexte. Der Mensch wird zum Datenbus. Warten ist nicht zwangslĂ€ufig Verschwendung; die Intoleranz gegenĂŒber ungenutzten Terminals fĂŒhrt zu ErmĂŒdung.
Betrachten wir es aus der Perspektive der Engpasstheorie: Wird ein Engpass beseitigt, hĂ€uft sich der Lagerbestand vor dem nĂ€chsten an. Parallelverarbeitung durch Agenten reduziert die Wartezeit der Maschinen, kann aber die Wartezeit fĂŒr die Mitarbeiter erhöhen. Littles Gesetz dient als informelle Warnung: Mehr unfertige AuftrĂ€ge bei gleichbleibender Servicegeschwindigkeit bedeuten lĂ€ngere Durchlaufzeiten â ohne dabei so zu tun, als ob diese Demonstration eine reale Produktionshalle simuliert hĂ€tte. Was das Experiment tatsĂ€chlich zeigt, ist einfacher: Man kann einen Agenten hinzufĂŒgen, der die Anzahl der Nachrichten und geplanten Ereignisse erhöht, ohne den Gesamtwert zu beeinflussen.
Operative Konsequenz fĂŒr die Orchestrierungsrichtlinie: Eine klar definierte Aufgabe mit automatisiertem Akzeptanzprozess ist vier unklaren Aufgaben vorzuziehen, die alle Anfragen an dieselbe zentrale Stelle zurĂŒckfĂŒhren. Multiagentensysteme skalieren nur dann, wenn die Validierung nicht skalierbar ist.
Hören Sie auf zu messen, wie viele Aufgaben ausgefĂŒhrt werden. Messen Sie stattdessen, wie viele Entscheidungen anstehen.
Deshalb liefert Flow jetzt ein Ressourcenbudget aus, keinen Aberglauben:
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 ist ein praktischer Standardwert fĂŒr Demos, keine NaturgesetzmĂ€Ăigkeit. Die Abstraktion ist wichtiger als die Zahl: ParallelitĂ€t ist eine knappe, ĂŒberwachte Ressource, und die Laufzeitumgebung sollte deren Erschöpfung explizit signalisieren.
Roadmap (noch nicht veröffentlicht): Metriken zur Entscheidungswarteschlangentiefe â offene Fragen, die auf menschliche Bearbeitung warten, Histogramme der Wartezeiten, ValidierungsbereitschaftsprĂŒfungen vor der Weiterleitung. Die Demo beweist den Bedarf; Flow misst die Wartezeiten der Mitarbeiter noch nicht.
Streuen/Sammeln ohne so zu tun, als wÀre Flow ein DAG
Die Orchestrierungsfabrik der Demo ist das eigentliche HerzstĂŒck der Architektur:
$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));
Was das tatsÀchlich bewirkt:
- Streuung â eine
Ippro AgentenidentitĂ€t - ParallelitĂ€t â
MaxIpStrategybegrenzt die Arbeit wĂ€hrend des Fluges - Gemeinsamer Datenspeicher â jeder Agent schreibt ein
AgentResultinRunStore - Join â nach
await()liestSummaryAgentden Bag synchron. - Scoreboard â Bericht auf Anwendungsebene, kein Flow-Graph-Knoten
flowchart LR
Ips[Multiple Ips] --> Stage[ExecuteAgentJob]
Stage --> Store[RunStore]
Store --> Summary[SummaryAgent executeSync]
Summary --> Report[RunReport]
Warum nennen wir das nicht einen DAG? Weil die öffentliche Topologie von Flow immer noch eine verkettete Liste von Phasen ist. Der Fan-in reprĂ€sentiert den Anwendungszustand. FĂŒr eine Demonstration ist das ausreichend. Es reicht jedoch nicht aus, wenn Sie typisierte Joins, Teilfehler pro Zweig oder die Kompilierung wiederverwendbarer Graphen benötigen.
Eine echte Join-/DAG-API wÀre gerechtfertigt, wenn:
- Mehrere Produzenten mĂŒssen sich mit dem Schema synchronisieren, nicht mit einem gemeinsam genutzten, verĂ€nderlichen Datenspeicher.
- Die Stornierung muss sich ĂŒber alle Zweige hinweg ausbreiten
- Das gleiche Diagramm wird fĂŒr verschiedene Produkte wiederverwendet, nicht nur fĂŒr eine Demo.
Bis dahin ist Ehrlichkeit wichtiger als ambitionierte Diagramme.
Async wartet effizient
Der zweite Befehl:
php bin/console thanks-agent:bench-io --save
Vergleicht vier LĂ€ufer bei denselben sechs wartenden Aufgaben (fĂŒnf nĂŒtzliche + Dankesaufgaben) unter Verwendung synthetischer verzögerter Sockets auf PHP 8.5.4:
| LĂ€ufer | Wand ms | Wert | Status |
|---|---|---|---|
| sequenziell | 599,9 | 130 | Basislinie |
stream_select |
166,8 | 130 | ~3,6Ă Wandverbesserung |
php86_poll |
â | â | ĂŒbersprungen (Io\Poll\Context nicht verfĂŒgbar unter 8.5.4) |
flow_stream_select |
178,7 | 130 | Flow StreamSelectDriver (~+12 ms vs. Rohauswahl) |
Kontext: Lokale synthetische E/A, simulierte Tokenkosten, ThanksAgent enthalten, Wert immer noch 130 (keine Zusammenfassung im E/A-Benchmark-Taskset).
Die sequentielle AusfĂŒhrung ist leicht nachvollziehbar, aber zeitaufwĂ€ndig, wenn die Arbeit an Wartezeiten gebunden ist. stream_select() multiplexiert die Bereitschaft. Flows StreamSelectDriver kapselt Generator-Jobs, die Warte-Tokens (waitReadable / waitWritable / waitDelay) erzeugen.
Die native Poll-API von PHP 8.6 (Io\Poll\*) ist die interessantere langfristige Funktion: epoll/kqueue-Klassen-Backends, sofern verfĂŒgbar, typisiert mit Time\Duration. Wichtig: Polling ist keine Ereignisschleife. Die Terminplanung obliegt weiterhin dem Benutzer.
Flows Antwort ist eine schlanke Schnittstelle â kein Amp-Klon:
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;
}
Aktuelle Implementierungen: StreamSelectPoller, NativePollPoller (Fallback, falls PHP 8.6 Poll fehlt). Flow\IO\Duration dient als BrĂŒcke zu Time\Duration, sofern vorhanden. clamp() wird in SupervisionBudget verwendet, falls verfĂŒgbar.
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]
Nur eine bescheidene Schlussfolgerung:
In diesem lokalen Benchmark reduzierte das Multiplexing von wartensintensiven Aufgaben die Laufzeit mit stream_select von sequenziell ca. 600 ms auf ca. 167 ms. Der StreamSelect-Treiber von Flow blieb in derselben GröĂenordnung (ca. 179 ms). Die Poll-Funktion von PHP 8.6 wurde hier nicht gemessen, da sie in Version 8.5.4 nicht verfĂŒgbar ist.
Es wird nicht behauptet, dass Flow âschneller als React/Ampâ sei. Diese Bibliotheken wurden nicht getestet.
Umfragen sind auch kein Wert
Hier ist der redaktionelle RĂŒckruf.
Ein besserer Poller kann nutzlose Aufgaben schneller erledigen.
Die Verbesserung von epoll, Fibers, ParallelitĂ€tsgrenzen oder der Cloud-Agentendichte löst das Thanks-Agent-Problem nicht. Sie verstĂ€rkt lediglich die OptimierungsmaĂnahmen des Systems.
Die Leistung verstÀrkt das, was das System optimiert.
Wenn das Optimierungsziel AktivitÀt ist, erhÀlt man mehr AktivitÀt.
Wenn das Optimierungsziel erfolgreiche Ergebnisse sind, erzielt man einen brauchbaren Durchsatz.
Der I/O-Benchmark bewertet ThanksAgent weiterhin mit dem Wert 0, obwohl ihm ein Scheduler-Slot zugewiesen wird. Schnellerer Multiplexer, gleiche Leere.
Der unglĂŒckliche Weg muss in Rechnung gestellt werden
Die relevante Erkenntnis:
Streaming-AusfĂŒhrungen können Nutzungsmetadaten anhĂ€ngen und dann eine Ausnahme auslösen (z. B. maximale Ausgabemenge). Wenn die Abrechnung nur im Normalfall abgeschlossen wird, hat Ihnen der Anbieter trotzdem etwas in Rechnung gestellt, und Ihre Buchhaltung war fehlerhaft.
Die Richtung des PR: sich gegenseitig ausschlieĂende Terminals â vollstĂ€ndig vs. Fehler â mit expliziten Fehler-Listenern.
Flow spiegelt diesen Lebenszyklus nun auf der Ereignisebene wider:
Flow\Event::COMPLETEâCompleteEventFlow\Event::ERRORâErrorEventFlow\Instrumentation\CostLedger::recordComplete/recordErrorCostLedgerSubscriberkann beides abhören
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
Demo-Befehl:
php bin/console thanks-agent:run --simulate-error --with-thanks
CostAgent wird in den Fehlerfall gezwungen; Tokens werden weiterhin erfasst. Der Nutzwert sinkt; das Ledger suggeriert nicht, dass der Fehler kostenlos war.
Explizit genannte EinschrĂ€nkung: Das Abbrechen/Stornieren von Projekten ohne Ausnahme stellt weiterhin eine DesignlĂŒcke dar. Die Demo enthĂ€lt lediglich App\Orchestration\CancellationTicket â einen Platzhalter, der den Flow-Lebenszyklus nicht abdeckt. Solange das Abbrechen nicht als vollwertiger Vorgang implementiert ist, kann FinOps diesen Fall weiterhin ĂŒbersehen. Der Pull Request von Symfony AI geht auf diese Art von SicherheitslĂŒcke ein; wir sollten es ebenfalls tun.
Auch der Kontext ist eine Ressource.
Ein Codierungsagent âverstehtâ nicht auf magische Weise ein gesamtes Repository. Er versteht den Ausschnitt, den sein Index und die bereitgestellten Tools enthalten. UnvollstĂ€ndige Sprachabdeckung fĂŒhrt zu fĂ€lschlicherweise generierten Ergebnissen. IndexqualitĂ€t und ModellqualitĂ€t sind voneinander unabhĂ€ngige Variablen.
FĂŒr Flow ist die Aussage âAgent erfolgreich ausgefĂŒhrtâ unzureichend. Eine aussagekrĂ€ftige Zuordnung eines Agentenlaufs erfordert letztendlich Folgendes:
- Modell
- Werkzeuge
- Kontext / AktualitÀt der CodeMap
- Aufforderung
- Verifizierungsrichtlinie
- kosten
- Ergebnis
Nicht ausgeliefert: ein CodeMap-Port. Nicht ausgeliefert: ein AgentRouter, der den Preis als ein Feld neben Abschlussrate, Latenz, ModalitĂ€t, Verifizierungskosten und ParallelitĂ€tsberechtigung behandelt. Diese Punkte bleiben aufgrund des Experiments auf der Roadmap: Sobald man Wert und Kosten messen kann, erkennt man, wie wenig die Aussage âerfolgreich ausgefĂŒhrtâ tatsĂ€chlich aussagt.
AnbieterneutralitĂ€t ist die zweite wichtige Voraussetzung. Der Besitz der Orchestrierungsschicht wird der Anmietung eines geschlossenen vertikalen Stacks vorgezogen. Flows Aufgabe ist es, anbieterneutral zu bleiben â eine Symfony-native Umgebung, in der Modelle austauschbare Schnittstellen und nicht die ProduktidentitĂ€t darstellen.
Kosten pro erfolgreichem Ergebnis
Ergebnisökonomie, Routing und ThanksAgent werden zusammengefĂŒhrt.
| Strategie | Sieht billig aus | Ist es oft auch |
|---|---|---|
| Niedrigster Preis pro Token | In der Rechnungszeile | Fehler bei explodierenden Wiederholungsversuchen |
| Immer das kleinste Modell | Auf der Preisliste | Falsch, wenn die Fertigstellungsrate einbricht |
| Die meisten Agenten parallel | Im Dashboard | Fehler bei Ăberlastung der Entscheidungswarteschlange |
| ThanksAgent | FĂŒr Token (2) | Unendlich viele pro nĂŒtzlichem Ergebnis |
Ein teureres Modell, das einmal korrekt abschlieĂt, kann ein billiges Modell schlagen, das dreimal fehlschlĂ€gt. Ein langsamerer sequenzieller Durchlauf mit automatisierter Validierung kann einen parallelen Schwarm ĂŒbertreffen, der fĂŒnf Pull Requests einem einzelnen Benutzer zuweist.
Das Feld costPerSuccessfulOutcome der Demo simuliert eine Arithmetik. FĂŒr Produktionssysteme ist die Form entscheidend: ZĂ€hlerterminals, Attributwiederholungen, Division durch die tatsĂ€chlich relevanten Ergebnisse.
Was sich dadurch in Darkwood Flow geÀndert hat
Bereits implementiert / in Flow ĂŒbernommen
Verifiziert in darkwood/src/Darkwood/Component/Flow/:
| Primitiv | Rolle |
|---|---|
Flow\Instrumentation\CostLedger |
Ergebniskostenrechnung |
Flow\Instrumentation\CostLedgerSubscriber |
Ereignis â Ledger-BrĂŒcke |
Flow\Instrumentation\ValueTag |
Produktionswertkennzeichnung |
Flow\Event::COMPLETE / ERROR |
Terminallebenszyklus |
Flow\Event\CompleteEvent / ErrorEvent |
Terminal-Nutzdaten |
Flow\Budget\SupervisionBudget |
WIP / Ăberwachungsgate |
Flow\IO\PollerInterface |
DĂŒnne Multiplexer-Abstraktion |
Flow\IO\StreamSelectPoller |
stream_select-Backend |
Flow\IO\NativePollPoller |
PHP 8.6 Poll mit Fallback |
Flow\IO\Duration |
Sekunden-Hilfsfunktion â native Dauer, falls verfĂŒgbar |
Dokumentation: Seite zur Flow-Instrumentierung im Komponentendokumentationsbaum. Die Tests umfassen das Fallback-Verhalten von Ledger, Budget und Poller.
Eine wichtige Detailinformation in der Konfiguration ist fĂŒr Leser relevant, die die Demo nachbilden: Die Symfony-Anwendung misst die Zugriffe weiterhin primĂ€r ĂŒber App\Instrumentation\MetricsSubscriber bei PUSH/PULL/POP/ASYNC. Die Flow-Ereignisse COMPLETE/ERROR und CostLedgerSubscriber sind etablierte Basisfunktionen, die zur Verwendung bereitstehen. Der Pfad --simulate-error der Demo protokolliert Fehler bereits im Anwendungsprotokoll. Dies ist der laufende Demonstrationsprozess nach dem Motto âDie Demo beweist, dass Flow die Lösung istâ â keine Behauptung, dass jedes Terminal in der CLI bereits CompleteEvent auslöst.
Die partielle Funktionsapplikation ab PHP 8.6 verdient nur eine kurze ErwĂ€hnung: Das Binden fester Konfigurationen an Pipeline-Aufrufe ($invoke = $platform->invoke($model, ?)) könnte die KomplexitĂ€t der Flow-DSL reduzieren, sobald PHP 8.6 Standard ist. Die Codebasis ist davon noch nicht abhĂ€ngig. Sie in die Diskussion einzubauen, wĂ€re rein formalistisch â und ironisch.
Demonstriert, aber immer noch auf Anwendungsebene (thanks-agent)
- Agentenjobs (
ThanksAgent, âŠ) ValueRegistry/ Scoreboard-UXRunStore-StreutascheApp\Instrumentation\CostLedger+MetricsSubscriber(demo-förmig, agentenbewusst)- CLI:
thanks-agent:compare,thanks-agent:bench-io,thanks-agent:run CancellationTicket-Stub
ZukĂŒnftige Arbeit (Roadmap, keine Behauptungen ĂŒber PrĂ€senz)
- Nativer PHP 8.6 Poll-Treiber, der in die await-Schleife integriert ist (ĂŒber den Poller-Helper hinaus)
- Stornierungs- und Terminalverlassensrichtlinie der ersten Klasse
- Metriken der Entscheidungswarteschlange
- Wahrer Graph / Knoten verbinden, wenn die Scatter/Gather-Nachfrage steigt
- âAgentRouterâ, âCodeMapâ, âModelPortâ.
- Partielle Funktionsanwendung als schlankere Pipeline-DSL, wenn PHP 8.6 die Basisversion ist
Die Roadmap sollte nicht unnötig aufgeblÀht werden. Der Sinn von Thanks Agent bestand darin, die erste Ebene der Wahrhaftigkeit zu erzwingen: Wert und Kosten gehören in den Wortschatz der Laufzeitumgebung.
Abschluss
Wir wissen bereits, wie man Agenten zum Laufen bringt.
Fibers, Poller, Cloud-Sandboxes und Multi-Agent-CLIs werden immer besser darin, Bewegung zu erzeugen. Bewegung lÀsst sich leicht visualisieren. Bewegung lÀsst sich leicht feiern. Bewegung ist das, worauf ein Thanks Agent von Grund auf optimiert ist.
Das schwierigere Problem besteht darin, zu entscheiden, welche Arbeit ĂŒberhaupt stattfinden soll â und anhand von Zahlen, die die Laufzeitumgebung erfassen kann, nachzuweisen, dass die Arbeit Ergebnisse hervorgebracht hat, die den Ressourcenaufwand wert sind.
Sobald ein Orchestrierungssystem bereitwillig einen Teilnehmer ausfĂŒhrt, der nichts beitrĂ€gt, ist die nĂ€chste Optimierung wahrscheinlich nicht ein weiterer Agent.
Das ist eine bessere Definition von Wert.
Wenn Agentensysteme auf Wert statt auf AktivitÀt optimieren sollen, muss der Wert Teil des beobachtbaren Modells der Laufzeitumgebung werden.
Die Aufgabe von Darkwood Flow ist nach Thanks Agent klarer: weiterhin asynchrone PHP-Arbeit mit so wenig Aufwand wie möglich zu orchestrieren â und sich zu weigern, AgentengesprĂ€che als Durchsatz zu behandeln.
Referenzen
Technisches Material
- FrĂ©dĂ©ric Bouchery â Ich habe mehrere Agenten gestoppt (In Arbeit, Validierungsketten, menschliche Entscheidung als EinschrĂ€nkung)
- Mozilla â Open Source KI-Strategie (Verantwortung fĂŒr die Orchestrierungsschicht)
Ideen zu Codebasisindizes, Agentenrouting und KI-Abrechnungsvarianz sind in der Branche weit verbreitet; dieser Aufsatz verwendet sie als technische EinschrÀnkungen und nicht als Kommentar zu einer bestimmten Veröffentlichung.