Jeder, der 2026 Multi-Agent-Systeme baut, schreibt immer noch gerade Linien. Schritt eins, dann Schritt zwei, dann Schritt drei – jeder wartet auf den vorherigen. Hier ist, warum das langsam ist und wie man es behebt.

Das Problem, das niemand überprüft
Du hast einen mehrstufigen Agenten gebaut. Er funktioniert. Er ist auch langsam.
Du denkst, das Modell sei der Flaschenhals. Ist es nicht.
Der Flaschenhals ist die Form, die du gezeichnet hast. Eine Kette – Schritt 1 wartet auf Schritt 2, Schritt 2 wartet auf Schritt 3 – erzwingt eine sequenzielle Ausführung, selbst wenn die Hälfte dieser Schritte nichts miteinander zu tun haben.
„Dieses Dokument zusammenfassen, dann das Wetter prüfen“ sind zwei unabhängige Aufgaben, die als ein Workflow verkleidet sind. Die Wetteraufgabe braucht die Zusammenfassung nicht. Hat sie nie. Aber wenn du sie als Kette geschrieben hast, wartet sie trotzdem.
Diese verschwendete Wartezeit, multipliziert über Dutzende von Schritten, ist der Ort, an dem der Großteil deiner Laufzeit verschwindet.
Kapitel 1 – Schleifen vs. Graphen
Eine Schleife ist eine Einheit der Selbstverbesserung:
1Etwas versuchen → Ergebnis prüfen → anpassen → erneut versuchen
Das ist das Atom. Ein Agent, eine Metrik, die sich durchläuft, bis sie konvergiert.
Schleifen haben eine bekannte Fehlerart: Sie optimieren genau das, was du misst, und sonst nichts. Ein Support-Bot, der darauf getrimmt ist, Tickets schnell zu schließen, wird Tickets schnell schließen – während die Zufriedenheit leise einbricht. Die Schleife kann nicht über ihre eigene Metrik hinaussehen. Das ist Goodharts Gesetz in deiner Agentenarchitektur.
Ein Graph behebt das von Natur aus. Statt einer Schleife, die einer Zahl hinterherjagt, baust du ein Netzwerk von Schleifen, die sich gegenseitig beobachten und korrigieren. Die Ausgabe von Knoten A speist Knoten B. Knoten C läuft unabhängig und überprüft beide. Keine einzelne Metrik treibt das gesamte System – die Struktur tut es.

Für Agentensysteme bedeutet das eine konkrete Verschiebung: Hör auf, einen Agenten zu schreiben, der alles von oben bis unten erledigt. Entwirf zuerst die Form der Arbeit – was muss vor was passieren, was kann gleichzeitig laufen, was muss wirklich warten.
Kapitel 2 – Knoten, Kanten und der Test, der sie trennt
Ein Graph hat genau zwei Komponenten:
Knoten – eine Arbeitseinheit. Ein Agent, eine Aufgabe, eine Eingabe, eine Ausgabe.
Kante – eine echte Abhängigkeit. Die Eingabe von Knoten B benötigt die Ausgabe von Knoten A.
Der Fehler, den fast alle machen: „und dann“ standardmäßig als Kante zu behandeln.
1„Lies diese Codebasis und schreibe dann das Changelog“2„Rufe die Preisseite ab und fasse dann die Funktionen der Konkurrenz zusammen“
Stelle für jedes „und dann“ in deinem Workflow eine Frage:
Liest der nächste Schritt tatsächlich die Ausgabe des vorherigen Schrittes?
Wenn ja → echte Kante. Behalte die sequenzielle Reihenfolge. Wenn nein → keine Kante. Das Warten ist verschwendet. Führe sie parallel aus.
Wenn keine Daten die Grenze zwischen zwei Aufgaben überschreiten, sind sie unabhängig – und jedes unabhängige Paar, das du sequenziell ausführst, ist Laufzeit, die du gratis wegwirfst.
Hier ist der Test, angewendet in Code:
1from dataclasses import dataclass23@dataclass4class TaskNode:5 id: str6 prompt: str7 depends_on: list[str] # IDs der Knoten, die dieser tatsächlich benötigt89def has_real_edge(node_a: TaskNode, node_b: TaskNode) -> bool:10 """11 Der Kern-Graphen-Engineering-Test:12 Benötigt die Eingabe von node_b tatsächlich die Ausgabe von node_a?13 """14 return node_a.id in node_b.depends_on1516# Beispiel: Die meisten "Ketten" zerfallen in 2-3 echte Abhängigkeitsgruppen17nodes = [18 TaskNode("audit_routes", "Liste alle API-Routen-Dateien auf", []),19 TaskNode("check_auth", "Überprüfe die Abdeckung der Auth-Middleware", []),20 TaskNode("fetch_weather", "Hole das heutige Wetter", []),21 TaskNode("summarize", "Fasse Routen- und Auth-Ergebnisse zusammen",22 depends_on=["audit_routes", "check_auth"]),23]2425# audit_routes, check_auth, fetch_weather haben KEINE Kanten zwischen sich26# Sie laufen parallel. Nur "summarize" hat echte Kanten – es wartet.
Dein aktueller „Mach A, dann B, dann C“-Agent ist technisch gesehen bereits ein Graph. Es ist nur der schlechtestmögliche – eine einzelne Kette, bei der, wenn C ins Stocken gerät, niemals etwas nachgelagertes läuft.
Kapitel 3 – Deinen ersten Graphen bauen

Voraussetzungen:
- Claude Code (aktuelle Version mit Dynamic Workflows-Unterstützung).
- Max-, Team- oder Enterprise-Plan – Workflows standardmäßig aktiviert. Bei Pro manuell aktivieren.
Öffne ein echtes Repository. Kein Spielzeugbeispiel – der Nutzen zeigt sich erst in echtem Maßstab.
Der Prompt, der deinen ersten Graphen startet:
1Erstelle einen Workflow, um jede Routen-Datei in dieser Codebasis zu überprüfen.23Überprüfe für jede Routen-Datei unabhängig:4- Authentifizierungs-Middleware vorhanden5- Eingabevalidierung für alle Parameter6- Rate Limiting konfiguriert7- Fehlerbehandlung gibt keine Stack-Traces preis89Führe diese Prüfungen parallel über alle Routen-Dateien aus –10sie hängen nicht voneinander ab.1112Nachdem alle Dateien geprüft wurden, erstelle einen konsolidierten13Bericht, gruppiert nach Schweregrad: kritisch, Warnung, Info.1415Der Konsolidierungsschritt sollte warten, bis alle Prüfungen abgeschlossen sind.16Alles davor sollte das nicht tun.
Beachte die im Prompt selbst eingebettete Struktur: Parallele Arbeit explizit genannt, die eine echte Abhängigkeit (Konsolidierung wartet auf alle Prüfungen) explizit benannt. Du hoffst nicht, dass der Agent den Graphen ableitet – du beschreibst ihn.
Was unter der Haube passiert – eine vereinfachte Version der Orchestrierung:
1import asyncio2from anthropic import Anthropic34client = Anthropic()56async def audit_route_file(filepath: str) -> dict:7 """Ein Knoten. Läuft unabhängig von jeder anderen Routen-Datei."""8 response = await client.messages.create(9 model="claude-sonnet-5",10 max_tokens=1000,11 messages=[{12 "role": "user",13 "content": f"""Überprüfe diese Routen-Datei auf:14 - Auth-Middleware, Eingabevalidierung,15 Rate Limiting, Fehlerbehandlung1617 Datei: {filepath}1819 Gib JSON zurück: {{"file": "", "issues": [], "severity": ""}}"""20 }]21 )22 return {"file": filepath, "result": response.content[0].text}2324async def consolidate(results: list[dict]) -> str:25 """Die eine echte Kante – wartet, bis alle Audit-Knoten fertig sind."""26 response = await client.messages.create(27 model="claude-opus-4-8",28 max_tokens=2000,29 messages=[{30 "role": "user",31 "content": f"""Konsolidiere diese {len(results)} Routen-Audits32 zu einem Bericht, gruppiert nach Schweregrad:3334 {results}"""35 }]36 )37 return response.content[0].text3839async def run_graph(route_files: list[str]):40 # Auffächern – alle unabhängigen Knoten laufen gleichzeitig41 audit_tasks = [audit_route_file(f) for f in route_files]42 results = await asyncio.gather(*audit_tasks)4344 # Zusammenführen – der eine Knoten mit einer echten Abhängigkeit45 report = await consolidate(results)46 return report4748# 40 Routen-Dateien, ein Prompt, ein paralleler Durchlauf49results = asyncio.run(run_graph([50 f"routes/{f}.py" for f in ["auth", "users", "billing", "orders"]51 # ...36 weitere
40 sequenzielle API-Aufrufe mit jeweils ~8 Sekunden sind über 5 Minuten. Dieselben 40 Aufrufe parallel aufgefächert: unter 15 Sekunden, begrenzt durch deine langsamste einzelne Datei, nicht durch die Summe aller.
Kapitel 4 – Wo Graphen tatsächlich brechen
Graph-Engineering scheitert an drei vorhersagbaren Stellen. Kenne sie, bevor du auf sie triffst.
Kontext-Kollaps. Fächere 1.000 Knoten auf und versuche, alle 1.000 Ausgaben in einen Konsolidierungsschritt zu speisen, und du sprengst jedes Kontextfenster, bevor die Synthese überhaupt beginnt. Fix: Schichte dein Zusammenführen. Gruppiere Knoten in Batches von 20–50, fasse jeden Batch zusammen, konsolidiere dann die Zusammenfassungen – nicht die Rohausgaben.
1async def layered_consolidate(results: list[dict], batch_size: int = 30):2 """Mehrschichtiges Zusammenführen – niemals rohe Ausgaben in großem Maßstab synthetisieren."""3 batches = [results[i:i+batch_size]4 for i in range(0, len(results), batch_size)]56 batch_summaries = await asyncio.gather(*[7 summarize_batch(batch) for batch in batches8 ])910 # Die endgültige Konsolidierung arbeitet mit Zusammenfassungen, nicht mit 1.000 Rohergebnissen11 return await consolidate(batch_summaries)
Falsche Unabhängigkeit. Du wirst annehmen, dass zwei Knoten unabhängig sind, weil ihre Prompts sich nicht aufeinander beziehen – aber sie schreiben beide in dieselbe Datei oder greifen auf dieselbe ratenbegrenzte API zu. Das ist eine versteckte Kante. Fix: Überprüfe auf gemeinsame Ressourcen, nicht nur auf gemeinsame Daten. Zwei Knoten mit einem Schreibkonflikt brauchen eine Kante, selbst wenn keine Datenabhängigkeit besteht.
Stiller Knotenfehler. In einer Kette stoppt ein Fehler alles – ärgerlich, aber offensichtlich. In einem Graphen kann ein fehlgeschlagener Knoten unter 200 in einem Bericht verschwinden, der vollständig aussieht. Fix: Jeder Zusammenführungsschritt prüft die Knotenanzahl gegen die erwartete Anzahl, bevor synthetisiert wird, und kennzeichnet Lücken explizit, anstatt stillschweigend mit Teildaten zu arbeiten.
1async def safe_consolidate(results: list[dict], expected_count: int):2 if len(results) < expected_count:3 missing = expected_count - len(results)4 print(f"WARNUNG: {missing} Knoten sind stillschweigend fehlgeschlagen. "5 f"Der Bericht wird unvollständig sein.")6 return await consolidate(results)
Kapitel 5 – Skalierung auf eine echte Flotte

Sobald das Muster bei 40 Knoten funktioniert, ist die Skalierung auf Hunderte eine Konfigurationsänderung, kein Neudesign – vorausgesetzt, du hast den Graphen ab Kapitel 2 korrekt gebaut.
Die vollständige Produktionsform:
1 Orchestrator2 |3 +--------+-------+-------+--------+4 v v v v v5 Node 1 Node 2 Node 3 ... Node N6 (parallel, no edges between any of them)7 | | | |8 +--------+-------+-------+-------+9 v10 Batch Summary <- layered fan-in11 (groups of 30)12 v13 Final Report <- the one true edge
Die einzige Aufgabe des Orchestrators: Die Aufgabe in Knoten zerlegen, echte Kanten identifizieren und ausliefern. Er selbst erledigt keine Arbeit – er zeichnet den Graphen.
1async def orchestrate(task: str, resources: list[str]):2 """3 Der Orchestrator-Knoten – zerlegt, führt nicht aus.4 """5 plan = await client.messages.create(6 model="claude-opus-4-8",7 max_tokens=2000,8 messages=[{9 "role": "user",10 "content": f"""Aufgabe: {task}11 Verfügbare Ressourcen: {resources}1213 Zerlege in einen Graphen:14 - Liste jeden unabhängigen Knoten (keine gemeinsamen Kanten)15 - Liste alle echten Abhängigkeiten zwischen Knoten16 - Gruppiere Knoten in Zusammenführungs-Batches, wenn Anzahl > 501718 Gib JSON zurück mit: nodes, edges, batch_groups"""19 }]20 )2122 graph = parse_plan(plan.content[0].text)2324 # Führe unabhängige Knoten parallel aus25 node_results = await asyncio.gather(*[26 execute_node(n) for n in graph["nodes"] if not n["depends_on"]27 ])2829 # Führe dann abhängige Knoten aus, respektiere nur echte Kanten30 final = await execute_dependent_chain(graph["edges"], node_results)3132 return final
Das ist die eigentliche Verschiebung, die Graph-Engineering darstellt: Du hörst auf, die Person zu sein, die jeden Schritt schreibt, und wirst zur Person, die die Abhängigkeitsstruktur entwirft. Die Agenten füllen die Knoten. Du besitzt die Kanten.
Was sich ändert, wenn du in Graphen statt in Linien denkst
Ein linearer Agent mit 40 Schritten hat 40 Punkte sequenziellen Fehlers und die 40-fache Latenz seines langsamsten einzelnen Schritts.
Ein Graph mit denselben 40 Arbeitseinheiten hat so viele Punkte parallelen Fehlers, wie du echte Abhängigkeiten hast – normalerweise 3 bis 5 in den meisten Workflows – und eine Latenz, die durch deine langsamste Schicht begrenzt wird, nicht durch deine Gesamtschrittzahl.
Das ist kein marginaler Geschwindigkeitsschub. Es ist der Unterschied zwischen einem Workflow, der 5 Minuten dauert, und einem, der 15 Sekunden dauert, bei exakt derselben zugrunde liegenden Arbeit.
Das Modell war nie der Flaschenhals. Die Linie, die du gezeichnet hast, war es.
Dies ist eine technische Aufschlüsselung von Multi-Agenten-Orchestrierungsmustern, Stand Juli 2026. Codebeispiele sind illustrativ – passe Fehlerbehandlung, Ratenbegrenzung und Wiederholungslogik an deine Produktionsumgebung an, bevor du in großem Maßstab bereitstellst.
Vielen Dank fürs Lesen.





