◄ ALLE POSTS
CrewAI

Multi-Agent AI Systeme mit CrewAI: Teams statt Einzelkämpfer

NW Nils Weiser •15. November 2024 •Aktualisiert: 06.10.2026 •—

Wie man spezialisierte KI-Agenten mit CrewAI orchestriert – und was sich ändert, wenn die Crew in Produktion läuft. Mit Lektionen aus zwei eigenen Systemen.

Ein einzelner KI-Agent stößt bei komplexen, mehrstufigen Aufgaben schnell an Grenzen. Die naheliegende Lösung: mehrere spezialisierte Agenten, die wie ein Team zusammenarbeiten.

CrewAI ist ein Python-Framework genau dafür, Stand Oktober 2026 in Version 1.15. Ich setze es in zwei eigenen Systemen ein: bei Erst Recht, einer KI-Plattform für rechtliche Ersteinschätzungen nach deutschem Recht, und in einem Research-Projekt, in dem ein autonomes Multi-Agenten-System Studien zu Nahrungsergänzungsmitteln auswertet. Dieser Artikel zeigt zuerst die Grundlagen und dann, was davon in Produktion übrig bleibt. Kurz gesagt: weniger Agenten-Magie, mehr Code.

Die drei Kernkonzepte

Statt eines Agenten, der alles kann, stellst du ein Team zusammen: Rollen, Aufgaben, Ablauf. Die Beispiele zeigen eine generische Crew, die eingehende Support-Anfragen einordnet.

1. Agents: Die Spezialisten

Jeder Agent hat eine Rolle, ein Ziel und einen Hintergrund. Das Modell bindest du über die LLM-Klasse ein, mit einem Provider-Präfix im Modellnamen.

from crewai import Agent, LLM

llm = LLM(
    model="provider/model-name",
    max_tokens=4096,
    timeout=120,  # harte Obergrenze pro Aufruf
)

analyst = Agent(
    role="Support-Analyst",
    goal="Anfragen einordnen und ihre Dringlichkeit bewerten",
    backstory="""Du analysierst Support-Anfragen für eine B2B-Software.
    Antworte nur mit der Einschätzung, ohne Einleitung.""",
    llm=llm,
    allow_delegation=False,
)

Best Practice: Spezifische Rollen

Statt „Analyst“ lieber „Support-Analyst für B2B-Software“ mit klar umrissenem Ziel. Genauso wichtig ist, was der Agent nicht tun soll.

2. Tasks: Die Aufgaben

Tasks definieren, was getan werden soll. Über context bekommt eine Task das Ergebnis einer vorherigen Task, über output_pydantic erzwingst du ein festes Ausgabeformat statt Freitext.

from crewai import Task

task_bewertung = Task(
    description="Bewerte diese Anfrage: {anfrage}",
    expected_output="Kategorie, Priorität und kurze Begründung",
    agent=analyst,
    output_pydantic=TicketAssessment,  # Schema statt Freitext
    context=[task_klassifizierung],    # Ergebnis des vorherigen Agents
)

3. Crew: Das Team

Die Crew bringt Agents und Tasks zusammen und legt fest, wie sie zusammenarbeiten.

from crewai import Crew, Process

crew = Crew(
    agents=[klassifizierer, analyst, autor],
    tasks=[task_klassifizierung, task_bewertung, task_antwort],
    process=Process.sequential,
)

result = crew.kickoff(inputs={"anfrage": text})
bewertung = result.tasks_output[1].pydantic  # typisiert, kein Regex

Alternativ gibt es Process.hierarchical: Ein Manager-LLM verteilt die Tasks dynamisch und prüft die Ergebnisse. Dafür brauchst du laut Doku ein manager_llm oder einen manager_agent. In Produktion setze ich auf feste Reihenfolgen. Einen Ablauf, den ich vorher kenne, kann ich testen und debuggen.

Crews vs. Flows: der Teil, den Tutorials überspringen

Eine Crew ist eine Gruppe von Agenten. Ein Flow ist ein ereignisgesteuerter Ablauf drumherum: Methoden mit @start() und @listen(), Verzweigungen mit @router(), dazu ein typisierter Zustand als Pydantic-Modell. In einem Flow-Schritt kann eine Crew laufen – oder normaler Python-Code. CrewAI selbst empfiehlt für Produktion, mit einem Flow zu beginnen. So sieht das Prinzip, stark vereinfacht, in meinem Research-Projekt aus:

from crewai.flow.flow import Flow, listen, start
from pydantic import BaseModel

class RunState(BaseModel):
    topic_id: str = ""
    paper_ids: list[str] = []
    evaluation_ids: list[str] = []
    draft_id: str | None = None

class ResearchFlow(Flow[RunState]):
    @start()
    async def discover(self):
        # reiner Code: Studien laden und deduplizieren
        self.state.paper_ids = await discover_papers(self.state.topic_id)

    @listen(discover)
    async def evaluate(self):
        # feste Bewertungsformel
        self.state.evaluation_ids = await evaluate_papers(self.state.paper_ids)

    @listen(evaluate)
    async def synthesize(self):
        # LLM-Schritt mit festem Ausgabeschema
        self.state.draft_id = await write_draft(self.state.evaluation_ids)

    # danach: redigieren → Fakten prüfen → validieren → veröffentlichen

Bemerkenswert ist, was fehlt: In diesem System gibt es keine einzige Crew. Geplant hatte ich pro Stufe eine Crew. Gebaut habe ich die Stufen als normale async-Funktionen, die das Modell direkt aufrufen, jede mit festem Ausgabeschema. Von CrewAI nutze ich dort nur die Flows: Reihenfolge, Zustand, zeitgesteuerter Start. Jede Stufe hat einen klaren Input und einen klaren Output. Für einen Agenten, der selbst plant, bleibt da wenig zu entscheiden.

Zwei Systeme im Überblick

Erst Recht

Mehrere spezialisierte Agents, orchestriert mit CrewAI, dazu eine juristische Wissensbasis. Das Ergebnis ist eine strukturierte rechtliche Ersteinschätzung für Laien.

Research-Projekt Nahrungsergänzungsmittel

Ein Flow mit festen Stufen: Studien finden, bewerten, Artikel entwerfen, redigieren, Fakten prüfen, Evidenz validieren, veröffentlichen. Die letzte Stufe ist reiner Code ohne LLM.

Fünf Regeln für Crews in Produktion

1. Ein zu strenges Schema kann den ganzen Lauf abbrechen

Harte Wertebereiche im Ausgabeschema, etwa ein Literal, sind riskant. Liefert das Modell ein Synonym, wirft Pydantic einen ValidationError, und je nach Version reicht CrewAI ihn aus crew.kickoff() heraus. Dann bricht der ganze Lauf ab, bezahlte Tokens sind verloren, und Fallback-Code hinter kickoff() läuft nie.

Die Lösung: Das Schema beschreibt nur die Struktur. Die erlaubten Werte prüft der Code nach dem Parsen. Am Beispiel eines Prioritätsfelds:

# vorher: zu streng, ein Synonym bricht den ganzen Lauf ab
class TicketAssessment(BaseModel):
    priority: Literal["hoch", "mittel", "niedrig"]

# nachher: Schema für die Struktur ...
class TicketAssessment(BaseModel):
    priority: str = Field(description="Erlaubt: 'hoch', 'mittel', 'niedrig'")

# ... und Code für die Werte, nach dem Parsen
ALLOWED = {"hoch", "mittel", "niedrig"}

assessment = result.tasks_output[1].pydantic
if assessment.priority.strip().lower() not in ALLOWED:
    flag_for_review(assessment)  # Wert markieren, der Lauf bleibt erhalten

Neuere CrewAI-Versionen bieten zusätzlich Task-Guardrails: Eine Funktion prüft die Ausgabe, bei einem Fehlschlag geht der Fehler zurück an den Agenten, standardmäßig bis zu dreimal (guardrail_max_retries). Für Formatfehler ist das sauberer. Jeder Retry ist aber ein weiterer bezahlter Modell-Aufruf.

2. Agents erfinden Quellen

Im Research-Projekt muss jede Aussage im Artikel mit Paper-IDs belegt sein. Der Prompt verbietet erfundene IDs. Der Code verlässt sich trotzdem nicht darauf:

known_ids = set(paper_abstracts.keys())
for p in parsed.paragraphs:
    support = [pid for pid in p.supporting_paper_ids if pid in known_ids]
    if p.is_claim and not support:
        continue  # Aussage ohne echten Beleg fliegt raus
    paragraphs.append(...)

Jede zitierte ID wird gegen die Paper geprüft, die tatsächlich im Prompt standen. Danach folgen weitere harte Prüfungen: Lässt sich eine Aussage nicht auf eine echte Quelle zurückführen, bricht die Stufe ab, ohne Retry. Der Fact-Check prüft, ob zitierte DOIs existieren und ob das Paper die Aussage tatsächlich stützt.

3. Kein Modell prüft sich selbst

Im Research-Projekt stammen das Modell, das schreibt, und das Modell, das prüft, aus unterschiedlichen Modellfamilien. Ein Modell, das seinen eigenen Text gegenliest, übersieht leicht dieselben Fehler, die es gemacht hat. Die Prüfung ist Pflicht: Läuft sie nicht, wird nicht veröffentlicht, statt still auf „ungeprüft“ herunterzustufen.

4. Nutzereingaben sind Daten, keine Befehle

Alles, was von außen kommt, ist Datum, kein Befehl: Nutzereingaben, hochgeladene Dokumente, Abstracts aus Datenbanken. Solche Texte gehören im Prompt klar abgegrenzt vom Auftrag. Im Research-Projekt prüft zusätzlich ein deterministischer Scanner jeden Abstract auf typische Injection-Muster, bevor er ein Modell erreicht. Auffällige Texte gehen nicht ungefiltert weiter. Warum das kein Luxus ist, steht im Artikel zur Lethal Trifecta.

5. Kosten und Laufzeit brauchen harte Grenzen

Im Research-Projekt geht jeder Modell-Aufruf vorher durch einen Cost Governor mit festen Limits pro Lauf, Tag und Monat. Reißt ein Lauf sein Limit, wird er abgebrochen. Reißt der Monat sein Limit, schaltet sich das Veröffentlichen automatisch ab.

Genauso wichtig ist ein Timeout für jeden Modell-Aufruf. Ein hängender Call darf keinen Worker blockieren. Lange Crew-Läufe gehören außerdem nicht in einen synchronen API-Request; die CrewAI-Doku empfiehlt dafür kickoff_async. Wer Agents mit Tools baut, sollte die Limits pro Agent bewusst setzen: max_iter (Standard: 20), max_execution_time, max_rpm.

Code oder Agent? Wo ich die Grenze ziehe

Die wichtigste Lektion aus beiden Systemen: Ein großer Teil der Arbeit gehört gar nicht in einen Agenten.

Faustregel

Alles mit einer eindeutig richtigen Antwort gehört in Code. Agents bekommen die Schritte, die Urteilsvermögen brauchen. Und auch dort prüft Code das Ergebnis.

Und dann ist da der Mensch. Im ursprünglichen Design war das Research-Projekt „vollständig autonom“. Gebaut habe ich ein Freigabe-Gate: Die ersten Artikel gehen nur mit menschlicher Freigabe live. Wie das System seine Fehlschläge in Issues und Pull Requests verwandelt, beschreibe ich in Loops statt Prompts.

Wann du keine Crew brauchst

Checkliste für die erste Crew in Produktion

  1. Mit einem Flow starten. Langlebiger Zustand gehört in die Datenbank, nicht in den Flow-State.
  2. Jede Task mit output_pydantic: Schema für die Struktur, Code für die Werte.
  3. Jede Quelle, ID und Zahl im Code gegen den Input prüfen.
  4. Mit einer anderen Modellfamilie prüfen als mit der, die geschrieben hat.
  5. Timeouts und Kostendeckel einbauen, bevor der erste Nutzer kommt.
  6. Nutzereingaben und externe Texte klar abgrenzen und als Daten behandeln.
  7. Am Anfang steht ein Mensch vor dem Veröffentlichen.

Fazit

CrewAI macht den Einstieg leicht: Rollen, Tasks, Crew, fertig. In Produktion verschiebt sich der Schwerpunkt. Die meiste Arbeit steckt bei mir im Code um die Agents herum: Schemas, die keinen Lauf abbrechen, Prüfungen, die erfundene Quellen aussortieren, Limits, die Kosten deckeln. Die Agents übernehmen, was Urteilsvermögen braucht. Alles andere erledigt Code.


Verwendete Tools:

CrewAI CrewAI Docs DeepLearning.AI

Planst du ein Multi-Agent-System oder willst du eine bestehende Crew produktionsreif machen? Schreib mir, ich helfe gerne bei Architektur und Implementierung.

NW
Nils WeiserAI Agent Specialist · Bodenseeraum
MIT MIR ARBEITEN ▸

Weitere Field Notes

ALLE POSTS ▸