Multi-Agent-Orchestrierung: Handoffs und parallele Agents
# Multi-Agent-Orchestrierung: Handoffs und parallele Agents
Ein Agent, vollgepackt mit zwölf Tools und einem System-Prompt von 2.000 Wörtern, ist ein Wartungsalbtraum, und ererThe ratio of interactions (likes, comments, shares) to reach for a given piece of content, used to gauge how well audiences respond relative to how many people saw it.Vollständige Definition ansehen → argumentiert meist schlechter als drei fokussierte Agents, die jeweils eine Sache gut machen. Echte Workflows zerfallen in Spezialisten, die entweder aneinander übergeben oder nebeneinander laufen. Diese Lektion geht in die Tiefe, wie Sie das im OpenAI Agents SDK bauen: Handoffs, paralleles Fan-out sowie die Guardrails und das Tracing, die ein Multi-Agent-System davor bewahren, ein unnachvollziehbares Durcheinander zu werden.
Warum einen Agent in mehrere aufteilen
Ein einzelner Agent verschlechtert sich auf vorhersehbare Weise, wenn Sie ihm immer mehr Verantwortung aufladen. Der System-Prompt wächst, bis sich Anweisungen widersprechen. Die Tool-Liste wird so lang, dass das Modell das falsche Tool wählt. Evaluation wird unmöglich, weil jede Prompt-Änderung alle Aufgaben gleichzeitig betrifft.
Die Aufteilung löst das, indem jeder Agent einen engen Anweisungssatz und eine kurze Tool-Liste erhält. Ein Billing-Agent weiß nur über Rechnungen und Rückerstattungen Bescheid. Ein Tech-Support-Agent kennt nur Diagnosen und Reset-Abläufe. Jeder ist leichter zu prompten, zu testen und auszutauschen.
Die zwei Kernmuster:
- Handoff: Ein Agent entscheidet, dass ein anderer Agent besser geeignet ist, und delegiert die ganze Konversation an ihn. Sequenziell, wie eine Telefonweiterleitung.
- Parallel: Sie lassen mehrere Agents gleichzeitig an unabhängigen Teilaufgaben arbeiten und führen die Ergebnisse dann zusammen. Fan-out, als würden Sie drei Rechercheure in drei Bibliotheken schicken.
Handoffs: Delegation als First-Class-Primitive
Im Agents SDK ist ein Handoff ein spezielles Tool, das das Modell aufrufen kann, um die Kontrolle an einen anderen Agent zu übergeben. Sie schreiben keine Routing-Logik von Hand. Sie geben einem Agent eine Liste möglicher Handoff-Ziele, und das Modell entscheidet anhand der Konversation, wann übergeben wird.
Die kanonische Form ist ein Triage-Agent: ein leichtgewichtiger Router, dessen einzige Aufgabe darin besteht, die Anfrage des Nutzers zu lesen und an den richtigen Spezialisten zu übergeben. ErErThe ratio of interactions (likes, comments, shares) to reach for a given piece of content, used to gauge how well audiences respond relative to how many people saw it.Vollständige Definition ansehen → hat selbst keine Domänen-Tools.
from agents import Agent, Runner
billing_agent = Agent(
name="Billing Agent",
handoff_description="Handles invoices, charges, and refunds.",
instructions=(
"You resolve billing issues. Look up the customer's latest "
"invoice and explain charges or process a refund. If the "
"problem is technical, say so clearly."
),
tools=[lookup_invoice, issue_refund],
)
tech_agent = Agent(
name="Tech Support Agent",
handoff_description="Handles login, errors, and device issues.",
instructions=(
"You diagnose technical problems. Walk the user through "
"resets and known fixes. If the issue is about money, "
"say so clearly."
),
tools=[run_diagnostic, send_reset_link],
)
triage_agent = Agent(
name="Triage Agent",
instructions=(
"Route the user to the right specialist. Do not answer "
"billing or technical questions yourself. Hand off."
),
handoffs=[billing_agent, tech_agent],
)
result = Runner.run_sync(
triage_agent,
"I was charged twice for my subscription this month.",
)
print(result.final_output)Zwei Dinge lassen das funktionieren. Die handoff_description ist der Text, den das Routing-Modell liest, um zu entscheiden, wohin die Anfrage geht, schreiben Sie sie also wie eine Stellenanzeige, nicht wie einen Kommentar. Und die handoffs-Liste macht jeden Spezialisten zu einem aufrufbaren Ziel für den Triage-Agent.
Was tatsächlich über die Grenze geht
Standardmäßig wandert die komplette Konversationshistorie mit dem Handoff, der Billing-Agent sieht die ursprüngliche Beschwerde also, ohne dass Sie sie erneut übergeben müssen. Das ist meist gewollt. Wenn nicht (etwa wenn der Spezialist eine frühere sensible Nachricht nicht sehen soll), kkThe average number of new users each existing user generates through referrals. Above 1.0, growth compounds on itself and becomes exponential.Vollständige Definition ansehen →önnen Sie den Handoff anpassen, um den Input zu filtern oder zusätzlichen Kontext einzuspeisen. Die Handoffs-Dokumentation behandelt Input-Filter und on_handoff-Callbacks für Logging oder das Vorabladen von Daten im Moment der Übergabe.
Ein feiner Punkt: Nach einem Handoff kehrt die Kontrolle nicht automatisch zum Triage-Agent zurück. Die Konversation gehört jetzt dem Spezialisten. Wenn Sie ein Hub-and-Spoke-Muster wollen, in dem Spezialisten zur Triage zurückspringen, geben Sie jedem Spezialisten einen Handoff zurück zum Triage-Agent. Entwerfen Sie die Topologie bewusst.
Parallele Agents: Fan-out, dann einsammeln
Handoffs sind sequenziell. Manchmal wollen Sie Arbeit gleichzeitig erledigen, weil die Teilaufgaben nicht voneinander abhängen. Klassische Fälle: drei Antwortkandidaten entwerfen und den besten wählen, oder Rechnungshistorie und technische Logs gleichzeitig einsammeln, bevor ein Spezialist über beides nachdenkt.
Das SDK läuft auf asyncio, Parallelität heißt also einfach, mehrere Agents mit asyncio.gather laufen zu lassen und die Ausgaben zu kombinieren. Hier ein Fan-out, das zwei unabhängige Entwürfe erzeugt und dann einen dritten Agent zur Synthese nutzt:
import asyncio
from agents import Agent, Runner
drafter = Agent(
name="Drafter",
instructions="Write one concise support reply to the user.",
)
synthesizer = Agent(
name="Synthesizer",
instructions=(
"You are given two candidate replies. Merge their best "
"parts into one final reply. Remove redundancy."
),
)
async def main(user_msg: str) -> str:
draft_a, draft_b = await asyncio.gather(
Runner.run(drafter, user_msg),
Runner.run(drafter, user_msg),
)
merged = await Runner.run(
synthesizer,
f"Reply A:\n{draft_a.final_output}\n\nReply B:\n{draft_b.final_output}",
)
return merged.final_output
print(asyncio.run(main("How do I export my data?")))Parallele Arbeit bringt Ihnen Latenz (zwei Dinge passieren gleichzeitig) oder Qualität (mehrfach sampeln und auswählen). Sie kostet TokensTokensA token is the basic unit of text that language models process, often a word fragment, whole word, or punctuation mark rather than a single character.Vollständige Definition ansehen →: den Drafter zweimal laufen zu lassen, verdoppelt die Ausgaben für diesen Schritt annähernd. Machen Sie Fan-out nur dort, wo sich die Parallelität rechnet.
Ein verwandtes Muster ist Agents als Tools. Statt zu übergeben (Kontrolle abtreten), kann ein übergeordneter Agent einen anderen Agent über agent.as_tool(...) wie eine Funktion aufrufen, das Ergebnis zurückerhalten und die Kontrolle behalten. So bauen Sie einen Top-Level-Orchestrator, der parallel an Sub-Agents verteilt und für die endgültige Antwort zuständig bleibt. Handoffs geben die Verantwortung ab; Agents-as-Tools behalten sie.
Guardrails: schlechten Input und Output früh abfangen
Mehr Agents heißt mehr Angriffsfläche für Fehler. Guardrails sind Prüfungen, die parallel zu Ihren Agents laufen, um Input oder Output zu validieren, und sie kkThe average number of new users each existing user generates through referrals. Above 1.0, growth compounds on itself and becomes exponential.Vollständige Definition ansehen →önnen einen tripwire auslösen, der die Ausführung stoppt, bevor Sie TokensTokensA token is the basic unit of text that language models process, often a word fragment, whole word, or punctuation mark rather than a single character.Vollständige Definition ansehen → verbrennen oder etwas nach außen dringt.
Ein Input-Guardrail läuft auf der eingehenden Nachricht des Triage-Agents. Ein günstiges, schnelles Modell kann themenfremde oder missbräuchliche Anfragen aussortieren, bevor ein teurer Spezialist überhaupt startet.
from agents import (
Agent, Runner, GuardrailFunctionOutput, input_guardrail,
)
from pydantic import BaseModel
class Relevance(BaseModel):
is_support_request: bool
screener = Agent(
name="Screener",
instructions="Is this a customer support request? Answer strictly.",
output_type=Relevance,
)
@input_guardrail
async def on_topic(ctx, agent, user_input):
result = await Runner.run(screener, user_input, context=ctx.context)
flagged = not result.final_output.is_support_request
return GuardrailFunctionOutput(
output_info=result.final_output,
tripwire_triggered=flagged,
)
triage_agent = Agent(
name="Triage Agent",
instructions="Route to the right specialist.",
handoffs=[billing_agent, tech_agent],
input_guardrails=[on_topic],
)Output-Guardrails funktionieren genauso auf der endgültigen Antwort, nützlich, um zu prüfen, dass ein Billing-Agent nie eine Rückerstattung verspricht, die ererThe ratio of interactions (likes, comments, shares) to reach for a given piece of content, used to gauge how well audiences respond relative to how many people saw it.Vollständige Definition ansehen → nicht gewähren darf. Beachten Sie oben die Nutzung von output_type mit einem Pydantic-Modell: Das sind Structured Outputs, die die Durchsetzung übernehmen, der Screener liefert also einen typisierten Boolean statt Prosa, die Sie parsen müssten. Der Guardrails-Guide beschreibt den Ablauf der Tripwire-Exception.
Wissenscheck
1. Warum verbessert es laut Lektion typischerweise die Ergebnisse, einen großen Agent in mehrere fokussierte Agents aufzuteilen?
2. Was unterscheidet ein Handoff am besten von einem parallelen Muster in der Multi-Agent-Orchestrierung?
3. Wie führt ein Agent im Agents SDK tatsächlich ein Handoff an einen anderen Agent aus?
4. Wählen Sie ALLE Arten, auf die sich ein einzelner überladener Agent laut Lektion verschlechtert, wenn sich Verantwortlichkeiten häufen.
Wählen Sie alle richtigen Antworten aus.
5. Wählen Sie ALLE Aussagen, die einen Triage-Agent so beschreiben, wie er in der Lektion dargestellt wird.
Wählen Sie alle richtigen Antworten aus.
Tracing: sehen, was Ihre Agents wirklich getan haben
Sobald Sie drei Agents, Handoffs, parallele Zweige und Guardrails haben, lässt sich „es hat eine seltsame Antwort gegeben" nicht mehr durch das Lesen eines einzelnen Transkripts debuggen. Sie müssen den gesamten Run als Baum sehen.
Das Agents SDK hat Tracing eingebaut und standardmäßig aktiviert. Jeder Run erzeugt einen Trace mit Spans für jeden Agent-Aufruf, jeden Tool-Call, jeden Handoff und jeden Guardrail. Sie sehen sie im Traces-Dashboard auf der OpenAI-Plattform. Das ist der größte Einzelgrund, das SDK zu nutzen statt eine eigene Orchestrierungs-Loop zusammenzuschustern: Sie bekommen die Observability gratis.
Gruppieren Sie zusammengehörige Runs unter einem Trace, damit eine komplette Kundensitzung als ein Baum erscheint:
from agents import Runner, trace
async def handle_session(msg: str):
with trace("support-session"):
result = await Runner.run(triage_agent, msg)
return result.final_outputIm Dashboard sehen Sie genau, wohin die Triage die Anfrage geschickt hat, wie lange das Rechnungs-Lookup gedauert hat und ob ein Guardrail ausgelöst wurde. Wenn ein Handoff beim falschen Spezialisten landet, zeigt der Trace die Routing-Entscheidung, sodass Sie die handoff_description korrigieren kkThe average number of new users each existing user generates through referrals. Above 1.0, growth compounds on itself and becomes exponential.Vollständige Definition ansehen →önnen statt zu raten.
Building Multi-Agent Systems with the OpenAI Agents SDK
Wann Multi-Agent besser ist als Single-Agent, und was es kostet
Greifen Sie zu mehreren Agents, wenn:
- Verantwortlichkeiten wirklich unterschiedlich sind und jede andere Tools oder Anweisungen braucht (Triage vs. Billing vs. Tech).
- Sie unabhängige Evaluation wollen: Sie kkThe average number of new users each existing user generates through referrals. Above 1.0, growth compounds on itself and becomes exponential.Vollständige Definition ansehen →önnen den Billing-Agent isoliert testen.
- Teilaufgaben unabhängig sind und Parallelität Latenz senkt oder die Qualität durch Sampling verbessert.
Bleiben Sie bei einem Agent, wenn:
- Die Aufgabe ein einziger zusammenhängender Ablauf ist, bei dem jeder Schritt den vollen Kontext braucht.
- Latenz und Kosten wichtiger sind als Modularität. Jeder Handoff und jeder Guardrail ist ein zusätzlicher Modellaufruf, und paralleles Fan-out vervielfacht die TokenTokenA token is the basic unit of text that language models process, often a word fragment, whole word, or punctuation mark rather than a single character.Vollständige Definition ansehen →-Ausgaben.
- Sie noch prototypisieren. Starten Sie mit einem Agent, teilen Sie erst, wenn eine klare Naht sichtbar wird.
Die echten Kosten eines Multi-Agent-Designs sind Koordinationskomplexität: Routing kann fehlschlagen, Kontext kann bei einem schlecht konfigurierten Handoff verloren gehen, und eine geschwätzige Topologie kann zwischen Agents hin- und herspringen und TokensTokensA token is the basic unit of text that language models process, often a word fragment, whole word, or punctuation mark rather than a single character.Vollständige Definition ansehen → verbrennen. Tracing und Guardrails existieren genau dafür, diese Komplexität handhabbar zu machen, nicht um sie zu beseitigen. Fügen Sie Agents hinzu, wenn die Naht offensichtlich ist, und lassen Sie Traces Ihnen sagen, ob eine Aufteilung hilft oder schadet.
Wichtigste Erkenntnisse
- Teilen Sie nach Verantwortung, nicht aus Eitelkeit. Nutzen Sie einen leichtgewichtigen Triage-Agent zum Routing und geben Sie jedem Spezialisten einen engen Anweisungssatz und eine kurze Tool-Liste. Schreiben Sie die
handoff_descriptionwie eine Stellenanzeige; der Router liest sie zur Entscheidung. - Handoffs geben die Kontrolle ab; Agents-as-Tools behalten sie. Nutzen Sie Handoffs zur Delegation (Telefonweiterleitung) und
agent.as_tool(), wenn ein Orchestrator das Teilergebnis zurückbraucht und die Verantwortung behält. - Fan-out nur dort, wo es sich rechnet. Parallele Agents über
asyncio.gathersenken Latenz oder erhöhen Qualität durch Sampling, aber sie vervielfachen die TokenTokenA token is the basic unit of text that language models process, often a word fragment, whole word, or punctuation mark rather than a single character.Vollständige Definition ansehen →-Kosten. Reservieren Sie sie für unabhängige Teilaufgaben. - Guardrails gehören an die Ränder. Screenen Sie Input mit einem günstigen Modell, bevor teure Spezialisten laufen, und validieren Sie Output, bevor ererThe ratio of interactions (likes, comments, shares) to reach for a given piece of content, used to gauge how well audiences respond relative to how many people saw it.Vollständige Definition ansehen → beim Nutzer ankommt. Nutzen Sie
output_typemit Pydantic, damit Prüfungen typisierte Werte zurückgeben. - Tracing ist im Maßstab nicht optional. Kapseln Sie Sitzungen in
trace(...)und lesen Sie das Traces-Dashboard, um Routing zu debuggen und zu messen, ob jede Aufteilung tatsächlich hilft.
Was Sie aus dieser Lektion umsetzen
Diese Maßnahmen sind im Playbook der Rolle zusammengefasst.
- Systeme als kleine Spezialisten-Agents mit Handoffs und Guardrails auf günstigen Modellen modellieren