ChatGPT · Multi-Agent-Orchestrierung: Handoffs und parallele Agenten
Ein einzelner Agent, vollgepackt mit zwölf Tools und einem System-Prompt von 2.000 Wörtern, ist ein Wartungsalbtraum, und ererDas Verhältnis von Interaktionen (Likes, Kommentare, Shares) zur Reichweite eines Inhalts. Zeigt, wie stark die Zielgruppe reagiert, gemessen an der Zahl der Personen, die den Inhalt gesehen haben.Vollständige Definition ansehen → argumentiert meist schlechter als drei fokussierte Agenten, 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 GuardrailsGuardrailsRegeln und Kontrollen, die ein KI-System in sicheren, rechtskonformen und markengerechten Grenzen halten und unerwünschte Ausgaben blockieren.Vollständige Definition ansehen → und das Tracing, die verhindern, dass ein Multi-Agent-System zu einem nicht nachvollziehbaren Wirrwarr wird.
Warum einen Agenten in mehrere aufteilen
Ein einzelner Agent verschlechtert sich auf vorhersehbare Weise, sobald 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 sie jedem Agenten ein enges Instruction-Set und eine kurze Tool-Liste gibt. Ein Billing-Agent weiß nur über Rechnungen und Rückerstattungen Bescheid. Ein Tech-Support-Agent weiß nur über Diagnose und Reset-Abläufe Bescheid. Jeder ist leichter zu prompten, zu testen und auszutauschen.
Die zwei Kernmuster:
- Handoff: Ein Agent entscheidet, dass ein anderer Agent besser passt, und delegiert die gesamte Konversation an ihn. Sequenziell, wie eine Anrufweiterleitung.
- Parallel: Sie lassen mehrere Agenten gleichzeitig an unabhängigen Teilaufgaben arbeiten und führen die Ergebnisse zusammen. Fan-out, als würden Sie drei Rechercheure in drei Bibliotheken gleichzeitig 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 Agenten zu übergeben. Sie schreiben keine Routing-Logik von Hand. Sie geben einem Agenten eine Liste möglicher Handoff-Ziele, und das Modell entscheidet anhand der Konversation, wann es übergibt.
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. Er hat selbst keine Domain-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 machen das funktionsfähig. 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 ist das, was jeden Spezialisten zu einem aufrufbaren Ziel für den Triage-Agenten macht.
Was tatsächlich die Grenze überschreitet
Standardmäßig wandert die komplette Konversationshistorie mit dem Handoff, der Billing-Agent sieht also die ursprüngliche Beschwerde, ohne dass Sie sie erneut übergeben. Das ist meist genau das, was Sie wollen. Wenn nicht (etwa weil der Spezialist eine frühere sensible Nachricht nicht sehen soll), kkDie durchschnittliche Zahl neuer Nutzer, die jeder bestehende Nutzer über Empfehlungen generiert. Über 1,0 verstärkt sich das Wachstum selbst und wird exponentiell.Vollständige Definition ansehen →önnen Sie den Handoff anpassen, um den Input zu filtern oder zusätzlichen Kontext einzuspielen. 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 geht die Kontrolle nicht automatisch an den Triage-Agenten zurück. Der Spezialist besitzt jetzt die Konversation. Wenn Sie ein Hub-and-Spoke-Muster wollen, bei dem Spezialisten zur Triage zurückspringen, geben Sie jedem Spezialisten einen Handoff zurück zum Triage-Agenten. Entwerfen Sie die Topologie bewusst.
Parallele Agenten: Fan-out, dann Zusammenführen
Handoffs sind sequenziell. Manchmal wollen Sie Arbeit gleichzeitig erledigen lassen, weil die Teilaufgaben nicht voneinander abhängen. Klassische Fälle: drei Antwortkandidaten entwerfen und den besten auswählen, oder Billing-Historie und technische Logs gleichzeitig einsammeln, bevor ein Spezialist über beides nachdenkt.
Das SDK läuft auf asyncio, Parallelität heißt also einfach, mehrere Agenten mit asyncio.gather laufen zu lassen und die Outputs zu kombinieren. Hier ein Fan-out, das zwei unabhängige Entwürfe erzeugt und dann einen dritten Agenten 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 samplen und auswählen). Sie kostet TokensTokensEin Token ist die grundlegende Texteinheit, die Sprachmodelle verarbeiten, oft ein Wortfragment, ein ganzes Wort oder ein Satzzeichen und nicht ein einzelnes Zeichen.Vollständige Definition ansehen →: den Drafter zweimal laufen zu lassen verdoppelt die Ausgaben dieses Schritts in etwa. Machen Sie Fan-out nur dort, wo sich die Parallelität rechnet.
Ein verwandtes Muster sind Agenten als Tools. Statt zu übergeben (Kontrolle abzutreten), kann ein übergeordneter Agent einen anderen Agenten über agent.as_tool(...) wie eine Funktion aufrufen, das Ergebnis zurückbekommen und die Kontrolle behalten. So bauen Sie einen Top-Level-Orchestrator, der parallel an Sub-Agenten verteilt und für die endgültige Antwort zuständig bleibt. Handoffs übertragen die Zuständigkeit; Agents-as-Tools behalten sie.
Guardrails: schlechten Input und Output früh abfangen
Mehr Agenten bedeutet mehr Angriffsfläche für Fehler. Guardrails sind Prüfungen, die parallel zu Ihren Agenten laufen und Input oder Output validieren. Sie können einen tripwire auslösen, der die Ausführung stoppt, bevor Sie Tokens verschwenden oder etwas nach außen dringt.
Ein Input-Guardrail läuft auf der eingehenden Nachricht des Triage-Agenten. Ein günstiges, schnelles Modell kann themenfremde oder missbräuchliche Anfragen aussortieren, bevor überhaupt ein teurer Spezialist läuft.
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 finalen Antwort, nützlich etwa um zu prüfen, dass ein Billing-Agent nie eine Rückerstattung verspricht, die er nicht gewähren darf. Beachten Sie die Verwendung von output_type mit einem Pydantic-Modell oben: Hier sorgen Structured Outputs für die Durchsetzung, der Screener liefert also einen typisierten Boolean statt Prosa, die Sie parsen müssten. Den Ablauf der Tripwire-Exception finden Sie im Guardrails-Guide.
Wissenscheck
1. Warum verbessert es laut der Lektion typischerweise die Ergebnisse, einen großen Agenten in mehrere fokussierte Agenten 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 einen Handoff an einen anderen Agenten aus?
4. Wählen Sie ALLE Arten aus, wie ein einzelner überladener Agent laut der Lektion schlechter wird, wenn sich Verantwortlichkeiten häufen.
Wählen Sie alle richtigen Antworten aus.
5. Wählen Sie ALLE Aussagen aus, die einen Triage-Agenten so beschreiben, wie er in der Lektion dargestellt wird.
Wählen Sie alle richtigen Antworten aus.
Tracing: sehen, was Ihre Agenten tatsächlich getan haben
Sobald Sie drei Agenten, Handoffs, parallele Zweige und Guardrails haben, lässt sich „es hat eine komische 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 Agentenaufruf, jeden Tool-Call, jeden Handoff und jedes Guardrail. Ansehen können Sie sie im Traces-Dashboard auf der OpenAI-Plattform. Das ist der wichtigste Grund, das SDK zu nutzen statt eine eigene Orchestrierungsschleife zu basteln: Sie bekommen die Observability gratis.
Gruppieren Sie zusammengehörige Runs unter einem Trace, damit eine komplette Kundensession als ein einzelner 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 die Rechnungsabfrage gedauert hat und ob ein Guardrail ausgelöst wurde. Wenn ein Handoff beim falschen Spezialisten landet, zeigt Ihnen der Trace die Routing-Entscheidung, sodass Sie die handoff_description korrigieren kö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 Agenten, wenn:
- Die Verantwortlichkeiten wirklich unterschiedlich sind und jede andere Tools oder Anweisungen braucht (Triage vs. Billing vs. Tech).
- Sie unabhängige Evaluation wollen: Sie können den Billing-Agenten isoliert testen.
- Teilaufgaben unabhängig sind und Parallelität die Latenz senkt oder durch Sampling die Qualität verbessert.
Bleiben Sie bei einem Agenten, 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 jedes Guardrail ist ein zusätzlicher Modellaufruf, und paralleles Fan-out vervielfacht die Token-Ausgaben.
- Sie noch prototypen. Starten Sie mit einem Agenten und teilen Sie erst auf, wenn eine klare Nahtstelle sichtbar wird.
Der eigentliche Preis von Multi-Agent-Design ist Koordinationskomplexität: Routing kann fehlgehen, Kontext kann bei einem schlecht konfigurierten Handoff verloren gehen, und eine geschwätzige Topologie kann zwischen Agenten hin- und herspringen und dabei Tokens verbrennen. Tracing und Guardrails existieren genau dafür, diese Komplexität handhabbar zu machen, nicht um sie zu beseitigen. Fügen Sie Agenten hinzu, wenn die Nahtstelle offensichtlich ist, und lassen Sie Traces Ihnen zeigen, ob eine Aufteilung hilft oder schadet.
Key Takeaways
- Teilen Sie nach Verantwortung auf, nicht aus Eitelkeit. Nutzen Sie einen leichtgewichtigen Triage-Agenten fürs Routing und geben Sie jedem Spezialisten ein enges Instruction-Set und eine kurze Tool-Liste. Schreiben Sie die
handoff_descriptionwie eine Stellenanzeige; der Router liest sie für seine Entscheidung. - Handoffs übertragen die Kontrolle; Agents-as-Tools behalten sie. Nutzen Sie Handoffs für Delegation (Anrufweiterleitung) und
agent.as_tool(), wenn ein Orchestrator das Teilergebnis zurückbraucht und zuständig bleibt. - Machen Sie Fan-out nur, wo es sich rechnet. Parallele Agenten via
asyncio.gathersenken die Latenz oder heben durch Sampling die Qualität, vervielfachen aber die Token-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 den Output, bevor er beim Nutzer landet. Nutzen Sie
output_typemit Pydantic, damit Prüfungen typisierte Werte zurückgeben. - Tracing ist im Maßstab nicht optional. Klammern Sie Sessions in
trace(...)und lesen Sie das Traces-Dashboard, um Routing zu debuggen und zu messen, ob jede Aufteilung wirklich 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