Viele Hände, ein Stift: Sieben Regeln für die Orchestrierung von KI-Agenten
Sieben Regeln für die Orchestrierung von KI-Agenten: Wann ein einfacher Workflow gewinnt, warum der Orchesterer keine Tools besitzt, zurückkehrende typisierte Subagenten und schriftliche Stoppsbedingungen.
Quellen: Many Hands, One Pen: Orchestrating Agents Without Losing the Plot
Stellen Sie sich die US-Marine im Jahr 1942 vor, die mit Koordinationsproblemen konfrontiert war, die viel über moderne Software aussagen. Kriegsschiffe verfügten über Radar, Sonar, Funkabhörungen sowie menschliche Beobachter, und jeder Bericht erreichte gleichzeitig und in zufälliger Reihenfolge die Brücke. Ein Kapitän, der einen Kampf führen wollte, war unter unverarbeiteten Signalen begraben.
Die Lösung der Marine war ein fensterloser Raum namens Kampfinformationszentrum. Jeder Sensordatenbericht wurde auf einer einzigen gemeinsamen Karte in einem vereinbarten Format eingetragen. Die Bediener, die die Instrumente lasen, gaben keine Befehle; ihre Aufgabe bestand darin, die Karte aktuell zu halten, während ein einziger Offizier die nächste Bewegung des Schiffes entschied. Die Informationen kamen aus allen Richtungen, die Entscheidungen wurden auf einen Punkt eingegrenzt, und das standardisierte Berichtsformat ermöglichte es, die Einträge miteinander zu vergleichen.
Mehre-Agenten-Systeme entdecken diesen Raum immer wieder aufs Neue. Die Phase, in der „einen weiteren Agenten hinzufügen“ die Lösung für alles war, ist vorbei, und 2026 wurde größtenteils damit verbracht, die Kosten dieser Lösung zu messen. Das Muster, das übrig bleibt, ist das, auf das die Marine gestoßen ist: Parallel sammeln, in einem disziplinierten Format berichten, an einem Ort entscheiden und das Erreichte explizit definieren.
Ein nützliches Rahmenkonzept: Die meisten Mehr-Agenten-Probleme sind eigentlich keine Agentenprobleme. Es handelt sich dabei um Kontextprobleme und Steuerflussprobleme in Agentenverkleidung. Ein Lauf geht in der Regel schief, weil zwei Agenten inkompatible Entscheidungen trafen, die keiner von ihnen sehen konnte, weil Informationen beim Überschreiten einer Grenze an Bedeutung verloren oder weil niemand aufgeschrieben hat, wie etwas abgeschlossen aussieht.
Es folgen sieben Praktiken, die jeweils aus Fehlern in bereits im Einsatz befindlichen Systemen stammen. Gemeinsam helfen sie Ihnen dabei, zu beurteilen, wann ein einfacher Workflow einem Agenten überlegen ist, wann sich ein Orchestrierer die Nutzung seiner Token leisten kann, wie Arbeit entlang von Kontextgrenzen aufgeteilt werden sollte, warum der Orchestrierer die Tools nicht selbst bedienen sollte, wie Subagenten einen überprüfbaren Rückgabevertrag erhalten können und wie ein Lauf absichtlich beendet werden kann – und nicht nach dem Willkürentschluss des Modells.
Verwenden Sie standardmäßig einfache Workflows; Autonomie muss erarbeitet werden
Was schiefgeht. Nehmen wir einen Rückerstattungsprozess mit vier möglichen Ausgängen, wobei jeder bereits durch eine schriftliche Regel geregelt ist. Ein Team umschließt diesen Prozess in einen autonomen Kreislauf mit sechs Werkzeugen und einer Zielvorgabe. Plötzlich verläuft das Ticket vom Dienstag einen anderen Weg als das vom Montag, und jeder Ausführungsvorgang kostet zehn bis fünfzig Mal so viel wie der alte Code. Die Genauigkeit bleibt unverändert, weil kein Teil des Ablaufs so unklar ist, dass Intelligenz erforderlich wäre.
Die Lösung. Zeichnen Sie zunächst den Flussdiagramm. Alles, was im Voraus dargestellt werden kann, gehört zum normalen Kontrollfluss – daher kann einfacher Code jede benennbare Abzweigung handhaben. Rufen Sie das Modell nur dann auf, wenn die Eingabe tatsächlich mehrdeutig ist. Ein Agent sollte nur dann die Kontrolle über eine Abzweigung übernehmen, wenn nachgewiesen wurde, dass diese nicht schriftlich festgelegt werden kann.
REFUND_LIMIT = 50.00
def llm_step(prompt: str) -> str:
"""Called only where the written rules run out."""
return model.complete(prompt).strip().lower()
def handle_refund(ticket):
if ticket.days_since_purchase > 30:
return deny(ticket, reason="outside window")
if ticket.amount <= REFUND_LIMIT:
return approve(ticket) # a rule, not a judgement call
intent = llm_step(
f"Classify as fraud, defect, or remorse:\n{ticket.body}"
)
if intent == "fraud":
return escalate(ticket, queue="risk")
if intent == "defect":
return approve(ticket)
return route_to_human(ticket)
Das Problem. Man kann in ein Dickicht aus verschachtelten Bedingungen geraten, die heimlich Regeln kodieren, die die KI tatsächlich nicht umsetzen kann. Wenn man eine fünfte Bedingung für freien Text schreibt, entsteht genau diese Mehrdeutigkeit, wofür das Modell eigentlich da ist.
Vermeiden Sie den Orchestrator, wenn das Problem bereits bekannt ist
Was schiefgeht. Ein vierstufiger Berichtsprozess wird in einen Orchestrator-Loop eingebettet, der auf fünfzehn Durchläufe begrenzt ist. Jeder Durchlauf verbringt Zeit mit der Planung, was als Nächstes getan werden soll, und jede dieser Planungsschritte kommt zu derselben Antwort, die man bereits festgelegt hat: Daten abrufen, extrahieren, zusammenfassen, formatieren. Das sind insgesamt fünfzehn Berechnungsschritte à einige tausend Token, nur um eine Liste wiederzufinden, die man in fünf Zeilen eingeben könnte.
Die Lösung. Verwenden Sie eine schnelle Regel, bevor Sie etwas kodieren. Wenn die vollständige Liste der Unteraufgaben bereits vor Beginn der Ausführung bekannt ist, führen Sie sie als einfache Schleife mit fester Verteilung aus und behalten die Tokens für etwas anderes. Modellgetriebene Orchestrierung eignet sich dort, wo die Aufteilung selbst unbekannt ist oder sich auf der Grundlage dessen entwickeln muss, was frühere Schritte ergeben haben.
# Before: up to 15 planning calls to rediscover a fixed list
def run_orchestrated(doc):
state = {"doc": doc}
for _ in range(15):
decision = orchestrator.plan(state) # 1 LLM call per pass
if decision.action == "finalize":
break
state = WORKERS[decision.worker](state)
return state
# After: 0 planning calls, same four workers, same result
PIPELINE = [fetch, extract, summarize, format_report]
def run_static(doc):
state = {"doc": doc}
for step in PIPELINE: # 0 LLM calls here
state = step(state)
return state
Der Haken. Dieser Ratschlag hat auch eine Kehrseite. Ein Pipeline-System, das jeden Monat einen neuen Sonderfall erstellt oder bei dem die Ausgabe des zweiten Schritts tatsächlich entscheidet, ob der dritte Schritt ausgeführt wird, betreibt echte Planung. Wenn man den Planer dort entfernt, verlagert sich die Entscheidungsfindung lediglich in eine Konfigurationsdatei, um die sich niemand kümmert.
Teilen Sie Agenten nach Kontext, nicht nach Jobbezeichnung
Was schiefgeht. Die Organigramm-Version des Mehr-Agenten-Ansatzes sieht ordentlich aus: Planer, Implementierer, Tester, Prüfer – jeweils arbeiten sie nacheinander an einer Funktion. In der Praxis führt jede Übergabe zu Annahmen, die niemand schriftlich festgehalten hat. Der Tester überprüft Verhaltensweisen, die der Implementierer nie beabsichtigt hat, und der Prüfer lehnt eine Entscheidung ab, die der Planer absichtlich getroffen hat. Man zahlt viermal den Preis für diese ineffiziente Vorgehensweise, während ein einziger Agent, der alle vier Aufgaben übernimmt, bessere Ergebnisse liefern würde.
Die Lösung. Schneiden Sie entlang der Kontextlinien. Bevor Sie einen zweiten Agenten hinzufügen, stellen Sie der Gestaltung folgende Frage: Kann diese Unteraufgabe innerhalb eines Kontextfensters abgeschlossen werden, das nichts mit dem des Nachbarn gemeinsam hat? Wenn die Antwort nein lautet, gehören beide zu einem Agenten – genau deshalb sollte der Agent, der eine Funktion entwickelt, auch die Tests dafür schreiben.
from dataclasses import dataclass
@dataclass
class Subtask:
name: str
needs: set[str] # facts this subtask must read
produces: set[str] # facts this subtask decides
def should_split(a: Subtask, b: Subtask) -> bool:
"""Split only when neither side needs what the other decides."""
shared = (a.needs & b.produces) | (b.needs & a.produces)
return not shared
implement = Subtask("implement", {"spec"}, {"api_shape", "error_semantics"})
test = Subtask("test", {"spec", "api_shape", "error_semantics"}, {"cases"})
assert not should_split(implement, test) # one agent writes both
Das Problem. Wirklich isolierte Unteraufgaben kommen seltener vor, als es ein Organigramm vermuten lässt. Deshalb gibt der Test oft an „einer Agent“, und das ist die richtige Antwort – nicht ein Mangel an Vorstellungskraft. Die Aufteilung lohnt sich bei umfangreichen Aufgaben, wie zum Beispiel fünf Agenten, die fünf unverwandte Quellen lesen, denn Entscheidungen der einen ändern nicht das, was die anderen benötigen.
Lassen Sie den Orchesterer eine Entscheidung ausgeben und rufen Sie niemals ein Tool auf
Was schiefgeht. Ein Orchesterer erhält ein Suchtool für Notfälle. Bald hört er auf, Aufgaben zuzuweisen, und beginnt stattdessen selbst Unteraufgaben zu bearbeiten. Die Rohausgaben der Tools häufen sich in seinem Fenster an, wodurch seine Planung mit zunehmender Laufzeit, in der Planung besonders wichtig ist, immer schlechter wird. Auch die Nachvollziehbarkeit leidet, da unklar ist, welcher Agent welche Erkenntnis erbracht hat.
Die Lösung. Jegliche Pläne sollten ebenfalls nicht heruntergeladen werden, daher sollte dem Orchesterleiter keine Werkzeuge zur Verfügung gestellt werden. Es gibt nur eine kompakte, typisierte Entscheidung heraus: Delegieren, neu planen oder abschließen – zusammen mit dem zu verwendenden Worker und dem Aufgabentext. Eine zugehörige Schleife liest diese Entscheidung, führt den benannten Worker aus und speichert das Ergebnis im gemeinsamen Zustand, bereit für die nächste Entscheidung.
from typing import Literal
from pydantic import BaseModel
class OrchestratorDecision(BaseModel):
next_action: Literal["delegate", "replan", "finalize"]
target_worker: str | None = None
task_description: str | None = None
reasoning: str
def orchestrator_step(state):
d = decide(state) # model has zero tools attached
if d.next_action == "finalize":
return finalize(state, d.reasoning)
if d.next_action == "replan":
return state.reset_plan(d.reasoning)
worker = WORKERS[d.target_worker] # workers own every tool
result = worker.run(d.task_description)
return state.record(d.target_worker, result)
Das Problem. Ohne Werkzeuge kann ein Orchesterleiter nur das sehen, was die Arbeiter zurücksenden. Ein Arbeiter, der nur eine knappe Zusammenfassung liefert, lässt den Planungsprozess blind. Bieten Sie stattdessen einen nur zum Lesen zugänglichen Überblick über den gemeinsamen Zustand an, anstatt Zugriff auf aktuelle Werkzeuge, und stellen Sie sicher, dass die Rückmeldungen der Arbeiter strukturiert genug sind, um darauf aufbauend planen zu können.
Jeder Unteragent muss sich an einen festgelegten Rückgabevertrag halten
Was schiefgeht. Stellen Sie sich einen Forschungsunteragenten vor, der ein 2.500 Wörter umfassendes Tagebuch über alles zurückgibt, was er versucht hat – einschließlich der fehlgeschlagenen Ansätze. Multiplizieren Sie das mit sieben Arbeitern, und bereits vor Beginn jeder Synthese gelangen etwa 20.000 Tokens in das Fenster des übergeordneten Systems. Die Delegation sollte dieses Fenster schützen. Stattdessen wird die Erkundung doppelt bezahlt, und das übergeordnete System befolgt die Anweisungen gerade dann nicht richtig, wenn es am wichtigsten ist.
Die Lösung. Betrachten Sie die Rückgabe als eine API-Grenze, bei der jeder Unteragent ein Antwort-Schema besitzt. Die Abschlussnachricht ist ein JSON-Objekt mit benannten Feldern: Erkenntnisse, Quellen, unbeantwortete Fragen sowie ein Abschlussstatus. Überprüfen Sie die Nachricht bei Erhalt und leiten Sie alles, was fehlerhaft oder zu lang ist, zur erneuten Verarbeitung zurück, damit es den übergeordneten Agenten niemals erreicht.
from pydantic import BaseModel, Field, ValidationError
class SubagentResult(BaseModel):
findings: list[str] = Field(max_length=5) # hard cap, one sentence each
sources: list[str]
open_questions: list[str] = []
completion_status: str # complete | partial | blocked
def parse_or_retry(worker, task, attempts=2):
for _ in range(attempts):
raw = worker.run(task, response_format=SubagentResult)
try:
return SubagentResult.model_validate_json(raw)
except ValidationError as err:
task = f"{task}\n\nRejected: {err}\nReturn only JSON in the schema."
raise RuntimeError(f"{worker.name} returned no valid result")
Das Problem. Schemata legen nur ein Minimum fest und nichts weiter. Ein Worker kann immer noch einen 400-Wörter-Paragrafen in einen einzigen Ergebnisstring packen und ihn als JSON ausliefern – dabei bleibt die Menge an Daten unverändert. Begrenzen Sie sowohl die Anzahl der Elemente als auch die Länge jedes Feldes und geben Sie im Ablehnungstext an, welches Feld überladen wurde, damit der erneute Versuch weiß, was korrigiert werden muss.
Lesvorgänge parallelisieren und Schreibvorgänge über einen Agenten leiten
Was schiefgeht. Zwei Agenten arbeiten gleichzeitig an derselben Funktion und melden jeweils Erfolg. Der eine erstellte einen Hintergrund im Stil von Super Mario, während der andere ein Sprite von Flappy Bird zeichnete – beides bestand die Tests, die für das jeweilige eigene Design erstellt wurden. Durch Zusammenführen lassen sich die Entscheidungen, von denen keiner der Agenten wusste, nicht auflösen, wodurch entweder ein Ergebnis oder beide Ergebnisse verworfen werden.
Die Lösung. Das Lesen kann parallel stattfinden; das Schreiben nicht. Beschränken Sie jeden Prozess auf eine Liste von nur zum Lesen zugelassenen Werkzeugen, damit die Sammelphase so weit wie nötig erweitert werden kann, und geben Sie einem Prozess niemals ein Schreibwerkzeug. Das Ergebnis wird anschließend in einem einzigen Aufruf erzeugt, der die Ergebnisse aller Prozesse zusammen erhält.
import asyncio
READ_TOOLS = ["search_repo", "read_file", "fetch_docs"]
async def gather_context(subtasks):
workers = [Agent(name=t.name, tools=READ_TOOLS) for t in subtasks]
return await asyncio.gather(
*(w.run(t.prompt) for w, t in zip(workers, subtasks))
)
async def build_feature(spec, subtasks):
findings = await gather_context(subtasks) # wide, parallel, read-only
writer = Agent(name="writer", tools=["write_file", "apply_patch"])
return await writer.run(spec, context=findings) # one writer, one pass
Das Problem. Jener einzelne Schreiber stellt ein Engpass dar und muss die Ergebnisse aller Arbeiter gleichzeitig verarbeiten, wodurch man bereits lange vor einem logischen Limit am Tokenbudget ankommt. Wenn das Ergebnis tatsächlich sauber geteilt werden kann, wie bei drei Dateien ohne gemeinsame Schnittstelle, sollte jeder Datei ein eigener Schreiber zugewiesen werden, wobei innerhalb jeder Datei dieselbe Disziplin eingehalten werden muss.
Legen Sie die Beendigungsbedingungen fest
Was schiefgeht. Eine Ausführung endet, es tritt kein Fehler auf – doch die Aufgabe bleibt unvollendet. Eine Analyse von 1.600 Mehr-Agenten-Verläufen in sieben Frameworks ergab, dass 12,4 % der Fehler auf das Fehlen eines Bewusstseins der Agenten für ihre Beendigungsbedingungen zurückzuführen sind, während weitere 6,2 % vorzeitig abbrechen. Fast ein Fünftel aller Fehler zeigt sich daher als ordentliche Beendigung mit einem halbfertigen Ergebnis.
Die Lösung. Verwandeln Sie die Ziellinie in etwas Konkretes statt in ein Gefühl. Geben Sie jeder Aufgabe eine ausdrückliche Abnahmekontrolle und setzen Sie eine Freigabekontrolle, die anhand des ursprünglichen Ziels gemessen wird, auf den einzigen Weg zum endgültigen Zustand. Laut derselben Studie erhöhte das Überprüfungsverfahren den Erfolg von ChatDev um 9,4 %, während die Überprüfung der Hochlevel-Ziele ihn um 15,6 % steigerte.
CHECKLIST = [
"every requested section exists",
"each claim cites a retrieved source",
"open questions are listed, or explicitly none",
]
def verify_complete(objective, checklist, output) -> bool:
for item in checklist:
verdict = judge(f"Objective: {objective}\nCheck: {item}\n\n{output}")
if not verdict.passed:
log.info("termination blocked by: %s", item)
return False
return judge(f"Does this satisfy the objective?\n{objective}\n\n{output}").passed
def finish(state):
if verify_complete(state.objective, CHECKLIST, state.draft):
return state.done()
return state.keep_working(reason="checklist not satisfied")
Das Problem. Wenn das Erstellungsmodell seinen eigenen Checkliste bewertet, wird es seine Arbeit einfach durchwinken. Wählen Sie möglichst mechanische Kriterien, wie zum Beispiel das Vorhandensein einer Datei, das Ausfüllen eines Feldes oder die Korrektur einer Quelle. Ein Gate, das niemals geöffnet wird, stellt ebenfalls eine Störung dar – begrenzen Sie daher die Anzahl der Versuche und geben Sie bei deren Aufgebrauch einen Fehler an.
Wo man anfangen sollte
Falls Sie nur eine Sache ändern, wählen Sie die günstigste Lösung: Definieren Sie schriftlich, was „abgeschlossen“ bedeutet. Eine Checkliste zusammen mit einem Überprüfungsschritt auf dem Weg zum Endzustand erfordert nur einen Nachmittag, funktioniert sowohl für einen einzelnen Agenten als auch für eine ganze Flotte und beseitigt eine ganze Kategorie stiller Fehler. Machen Sie das zu der Aufgabe dieser Woche.
Danach kommt die Entfernung. Prüfen Sie Ihren Orchestrierer und testen Sie, ob seine Auswahlmöglichkeiten auf eine feste Liste sowie eine Aggregationsfunktion reduziert werden können. Falls ja, entfernen Sie ihn – dadurch sinken der Tokenverbrauch und die Latenz, und die Ergebnisse bleiben stabil. Da er leicht rückgängig gemacht werden kann, stellt er eine sichere erste Maßnahme dar.
Halten Sie die aufwändigeren Lösungen zurück, bis es wirklich notwendig wird. Typisierte Rückgabeverträge lohnen sich ab etwa fünf Arbeitern, und die read-only-Allowliste ist wichtig, wenn zwei Agenten tatsächlich gleichzeitig schreiben. Die Ausnahme bildet der toollose Orchestrierer: Er ist zu Beginn nahezu kostenlos, doch seine Einführung später ist aufwendig.
Die Konfigurationen, die bis 2026 halten, verfügen nicht über die meisten Agenten. Bei ihnen sind die Verbindungen zwischen den Agenten der kleinste und deutlichste Bestandteil des Designs. Weniger Akteure, festere Verträge – und nur ein Stift.
Verwandte Artikel
- Parallel Coding Agents With Git Worktrees, Conductor und Antigravity 2.0 — Wie ein Koordinationsagent, per-Agent Git-Worktrees sowie issue-basierte Arbeitsweisen es ermöglichen, etwa ein Dutzend SRE-Funktionen in etwa fünf Stunden zu entwickeln, sowie Lektionen zu HITL-Fragen und Merge-Hygiene.
- Agentic RAG mit Agno Teams: Abfragen umschreiben, ein Kritikloop und Qdrant — Ein Koordinationsteam überschreibt Abfragen, wiederholt die Datenerfassung in Zusammenarbeit mit einem Kritiker und gibt nur Antworten aus genehmigtem Kontext, wobei hybride Suchmethoden wie dichte Suchalgorithmen, BM25 und ColBERT in Qdrant genutzt werden.