Darkwood Blog Blog
  • Artikel
  • Beobachtung
  • Releases
  • Creators
de
  • en
  • fr
Anmeldung
  • Blog
  • Artikel
  • Beobachtung
  • Releases
  • Creators

🙏 Wenn Orchestrierung die AusfĂŒhrung garantiert, nicht den Wert

vom 9. August 2026

Anmelden um auf diesen Beitrag zu reagieren

🚀 1

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\FlowFactory
  • Flow\Ip
  • Flow\JobInterface
  • Flow\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:

  1. Streuung — eine Ip pro AgentenidentitĂ€t
  2. ParallelitĂ€t – MaxIpStrategy begrenzt die Arbeit wĂ€hrend des Fluges
  3. Gemeinsamer Datenspeicher – jeder Agent schreibt ein AgentResult in RunStore
  4. Join – nach await() liest SummaryAgent den Bag synchron.
  5. 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 → CompleteEvent
  • Flow\Event::ERROR → ErrorEvent
  • Flow\Instrumentation\CostLedger::recordComplete / recordError
  • CostLedgerSubscriber kann 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-UX
  • RunStore-Streutasche
  • App\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.

Artefakte aus Darkwood

  • Demo: https://github.com/matyo91/thanks-agent
  • Folien: https://github.com/matyo91/slidewire

Anmelden um auf diesen Beitrag zu reagieren

🚀 1

Site

  • Sitemap
  • Kontakt
  • Impressum

Network

  • Hello
  • Blog
  • Apps
  • Photos

Social

Darkwood 2026, alle Rechte vorbehalten