Im vorigen Kapitel haben wir gesehen, dass ein KI-Agent aus den vier Elementen Kopf (LLM), Werkzeuge, Gedächtnis (Memory) und Schleife (Steuerung) besteht. In diesem Kapitel werden wir endlich praktisch. Das Ziel ist schlicht: einen „lauffähigen Agenten“ aus diesen vier Elementen in Minimalform zusammensetzen, ihn tatsächlich laufen lassen und sein Verhalten beobachten. Spektakuläre Funktionen fügen wir noch nicht hinzu. Zuerst bringen wir das Herzstück eines Agenten mit eigener Hand zum Drehen: „das LLM denken lassen, ein Werkzeug aufrufen, das Ergebnis zurückgeben, wieder denken lassen und bei Abschluss anhalten“.
„Einen minimalen Agenten selbst zusammensetzen und zum Laufen bringen“
Was ein minimaler Agent ist
Ein „minimaler Agent“ ist das Zusammensetzen der vier Elemente aus dem vorigen Kapitel in ihrer jeweils kleinsten Form. Kein üppiges Gedächtnis, keine Fülle von Werkzeugen, keine mehreren Agenten. Wie die folgende Tabelle zeigt, beginnen wir mit einem so weit wie möglich abgespeckten Aufbau. Hat man das verstanden, muss man danach nur noch jedes Element auffüllen.
Nur ein einziges Modell wie Claude aufrufen. Im Prompt in einer Zeile die Rolle festhalten: „Du bist ein Assistent, der Werkzeuge nutzen kann.“
Nur ein einziges Werkzeug. Suche oder Berechnung – egal. Nehmen Sie zunächst eine einfache Funktion, die zuverlässig läuft.
Ein einzelnes Array mit dem Gesprächsverlauf genügt. Man stapelt die Wortwechsel einfach der Reihe nach. An Persistenz denken wir noch nicht.
Eine einzige while-Schleife. Sie dreht: „Gibt es eine Werkzeuganforderung, ausführen; wenn nicht, fertig.“ Nur eine Obergrenze für die Rundenzahl festlegen.
💡 Der einzige Unterschied zu „einem einzelnen API-Aufruf“ ist die Schleife. Das LLM einmal zu fragen und eine Antwort zu bekommen ist bloße API-Nutzung. In dem Moment, in dem die Wiederholung hinzukommt – „ein Werkzeug ausführen, das Ergebnis zurückgeben und noch einmal denken lassen“ – wird daraus ein Agent. Faktisch kommt nur diese eine Schleife hinzu. Gerade deshalb ist es die Abkürzung, zuerst die Schleife vollständig zu verstehen.
Das Innere der Agentenschleife
Das Herzstück eines Agenten ist eine einzige Schleife. Dasselbe, was ein Mensch tut – „recherchieren, überlegen, die Hand anlegen, das Ergebnis betrachten und, wenn noch nicht fertig, wiederholen“ –, drehen wir als Programm. Halten wir zuerst den Ablauf einer Runde in einem Schema fest.
Den bisherigen Gesprächsverlauf und die Werkzeugliste ans LLM übergeben. Das LLM entscheidet: „antworten“ oder „ein Werkzeug nutzen“.
Antwortet das LLM „Ich will dieses Werkzeug mit diesen Argumenten nutzen“, führen wir diese Funktion tatsächlich aus.
Das Ausführungsergebnis (den Rückgabewert des Werkzeugs) an den Verlauf anhängen und erneut ans LLM übergeben. Hier geht es zurück zu Schritt 1.
Gibt das LLM ohne Werkzeugnutzung eine Endantwort, gilt das Ziel als erreicht, und wir verlassen die Schleife.
Der Kern ist: Schritte 1 bis 3 drehen immer weiter, und erst bei Schritt 4 wird die Schleife verlassen. Das LLM ist mit einer Runde vielleicht nicht fertig. Wie „erst suchen, dann das Ergebnis betrachten und noch einmal suchen“ nähert es sich über viele Runden dem Ziel. Als Pseudocode geschrieben ist das erstaunlich kurz.
# Minimale Agentenschleife (Pseudocode) messages = [ user("Ermittle die Durchschnittstemperatur des letzten Monats und fasse sie zusammen") ] while True: reply = llm.think(messages, tools=[search_tool]) # SCHRITT1 denken if reply.wants_tool: # Werkzeuganforderung? result = run_tool(reply.tool_name, reply.args) # SCHRITT2 aufrufen messages.append(assistant(reply)) messages.append(tool_result(result)) # SCHRITT3 zurückgeben else: return reply.text # SCHRITT4 bei Abschluss anhalten
⚠️ Immer eine Obergrenze für die Rundenzahl einbauen. Der Pseudocode oben verwendet zur Veranschaulichung while True, aber im Ernstfall bauen Sie stets eine Bremse ein: „bis maximal N Runden“. Eine Endlosschleife, in der das LLM immer weiter Werkzeuge aufruft, ist ein Unfall, der tatsächlich oft passiert. Näheres bei den Stolpersteinen.
Ein Werkzeug übergeben
Als Nächstes geben wir dem LLM ein Werkzeug in die Hand. Wichtig ist dabei: Das LLM kann selbst keinen Code ausführen. Alles, was das LLM kann, ist, in Worten anzufordern: „Ich will dieses Werkzeug mit diesen Argumenten nutzen.“ Die Funktion tatsächlich auszuführen und das Ergebnis zurückzugeben, ist immer unsere Aufgabe (die Ihres Programms).
Dazu übergeben wir dem LLM zunächst eine Werkzeugdefinition. Eine Werkzeugdefinition ist die Gebrauchsanweisung: „Was kann dieses Werkzeug, und welche Argumente nimmt es?“ Das LLM liest sie und entscheidet, wann und wie es das Werkzeug einsetzt.
Beispiel: search_weather „gibt bei Übergabe von Ortsname und Monat die Durchschnittstemperatur zurück“. Die Beschreibung ist die Entscheidungsgrundlage des LLM, also sorgfältig schreiben.
Welche Argumente in welchem Typ entgegengenommen werden, per Schema (Definition im JSON-Format) angeben. Beispiel: city (String) und month (Zahl).
Der tatsächlich laufende Code. Er nimmt die vom LLM zurückgegebenen Argumente entgegen und liefert ein Ergebnis. Das darf eine ganz normale Funktion sein.
Der Kniff bei diesem Dreierset: ① und ② ans LLM übergeben, ③ bei sich behalten. Fordert das LLM „Ich will search_weather(city=\"Paris\", month=6) nutzen“ an, nehmen wir Name und Argumente entgegen, rufen die Funktion aus ③ auf und geben deren Rückgabewert als Werkzeugergebnis ins Gespräch zurück. Schauen wir uns das im Pseudocode an.
# ① und ② … die Werkzeugdefinition, die ans LLM geht search_tool = { "name": "search_weather", "description": "Gibt bei Übergabe von Stadt und Monat die Durchschnittstemperatur (°C) zurück", "input_schema": { "city": "string", "month": "number", }, } # ③ … die eigentliche Funktion, bei uns behalten. Nur eine Funktion def run_tool(name, args): if name == "search_weather": return weather_db.lookup(args["city"], args["month"]) return "unknown tool"
📊 Die Beschreibung ist Teil des Prompts. Die description eines Werkzeugs ist der einzige Anhaltspunkt, an dem das LLM entscheidet, „wann es es nutzt“. Ist sie vage, nutzt es das Werkzeug nicht oder in seltsamen Situationen. Der Kniff: „Was gibt es zurück, wann sollte man es nutzen“ so schreiben, als erklärte man es einem Menschen. Werkzeugdesign vertiefen wir im nächsten Kapitel bei MCP.
Umsetzung – handgeschriebene Schleife und SDK
Fügt man die bisherigen Teile zusammen, läuft der erste Agent. Für die Umsetzung gibt es grob zwei Wege. Wer die Funktionsweise lernen will, schreibt selbst; wer sich in der Praxis Arbeit sparen will, nimmt ein SDK – in beiden steckt dieselbe Schleife. Ordnen wir zuerst die Unterschiede.
API-Aufruf und Werkzeugausführung in der eigenen while-Schleife drehen. Man sieht alles, was im Inneren passiert – ideal zum Lernen. Die Steuerung ist völlig frei.
Passt, wenn: Sie die Funktionsweise verstehen / fein steuern wollen.
Der Werkzeug-Ausführungsschleife, die etwa Claude-SDKs bereitstellen, Werkzeugdefinition und Funktion übergeben und sie machen lassen. Man muss den Standardteil nicht schreiben, und es ist robust.
Passt, wenn: Sie schnell bauen / die Standardabläufe der Produktion abgeben wollen.
Das Gesamtbild von A. der handgeschriebenen Schleife verbindet nur schlicht die bisherigen Teile. Einen Gesprächsverlauf halten, das LLM aufrufen, bei Werkzeuganforderung ausführen und das Ergebnis zurückgeben, sonst die Schleife verlassen – mehr nicht.
# A. Handgeschriebene Schleife (Pseudocode / im Stil der Claude-Messages) messages = [ user(goal) ] for step in range(MAX_STEPS): # ← Bremse per Obergrenze reply = client.messages.create( model="claude-…", messages=messages, tools=[search_tool], ) log(step, reply) # ← zum Beobachten immer protokollieren if reply.stop_reason == "tool_use": out = run_tool(reply.tool_name, reply.tool_args) messages += [ assistant(reply), tool_result(out) ] else: break # Endantwort da → Ende
Mit B. dem Tool-Runner eines SDK kümmert sich die Bibliothek um genau diese for-Schleife. Sie schreiben nur „Werkzeugdefinition“, „die eigentliche Funktion“ und „das anfängliche Ziel“. Schleife, Verlaufsverwaltung und das Zurückgeben der Werkzeugergebnisse werden intern erledigt.
# B. Dem Tool-Runner eines SDK überlassen (Pseudocode) runner = ToolRunner( model="claude-…", tools=[search_tool], # Definition handlers={"search_weather": run_tool}, # eigentliche Funktion ) answer = runner.run(goal) # die Schleife dreht intern
💡 Die genauen Methodennamen in der offiziellen Doku nachschlagen. Das client.messages.create und ToolRunner hier sind Pseudocode, der nur die Idee vermittelt. Die tatsächlichen Argumentnamen, die Form der Rückgabewerte und die Modell-IDs unterscheiden sich je SDK und werden häufig aktualisiert, prüfen Sie also unbedingt die aktuelle Fassung in der offiziellen Doku. Zuerst das Konzept fassen, die Details aus der Doku ergänzen – so machen Sie keinen Umweg. Für einen Schritt-für-Schritt-Einstieg ist auch Wie man einen KI-Agenten baut (Einstieg) hilfreich.
Empfohlen ist: „erst mit A einmal von Hand schreiben, danach mit B Arbeit sparen“. Hat man die Schleife einmal selbst gedreht, ist das SDK keine Blackbox mehr, und bei Problemen können Sie sich vorstellen, was drinnen passiert.
Laufen lassen und beobachten
Ist alles zusammengesetzt, lassen wir es laufen. Wichtig ist dabei, nicht bloß laufen zu lassen, sondern zu beobachten: „wo wurde was gedacht, und wo ist es gescheitert“. In der Agentenentwicklung entscheidet die Qualität dieser Beobachtung über das Ergebnis. Deshalb bauen wir von Anfang an Logging ein.
Protokollieren Sie mindestens pro Runde das Folgende. Bei einer handgeschriebenen Schleife genügt die eine Zeile log(step, reply).
Ob das LLM in der Runde „ein Werkzeug nutzen“ oder eine Endantwort beschlossen hat. Der Entscheidungspunkt.
Werkzeugname und Argumente. Ist das falsch, gerät auch das Ergebnis durcheinander. Hier zeigt sich am ehesten ein Missverständnis des LLM.
Der Rückgabewert des Werkzeugs. Zu groß, leer oder ein Fehler – hier lauert der Stoff, der die nächste Entscheidung verdirbt.
Lässt man es tatsächlich laufen, zeigt sich interessantes (und lästiges) Verhalten. Etwa: Das LLM ruft ein Werkzeug auf, obwohl es nicht nötig ist. Umgekehrt ruft es dort, wo es sollte, nicht auf und antwortet nur aus dem Gedächtnis. Es verwechselt den Städtenamen im Argument leicht. Was mit einem Mal erledigt wäre, wiederholt es dieselbe Suche mehrfach. Solche „Entscheidungsmacken“ bemerkt man erst, wenn man das Log betrachtet.
✅ Logging ist keine „gehobene Funktion“, sondern von Anfang an Pflicht. Weil das Innere eines Agenten schwer zu sehen ist, weiß man ohne Log überhaupt nicht, „warum er so gehandelt hat“. Vorerst genügt eine Zeile print. Die systematisierte Form dieser Beobachtung – Evaluierung und Beobachtbarkeit – behandeln wir in Kapitel 5 ausführlich. Legen Sie sich hier zunächst „die Gewohnheit des Hinschauens“ zu.
Stolpersteine
Auch im Minimalaufbau stößt man beim Laufenlassen zwangsläufig an ein paar Wände. Alle sind klassische Stolpersteine der Agentenentwicklung, die wir in den folgenden Kapiteln nacheinander lösen. Hier fassen wir „das Wesen“ und „die Erste Hilfe, die jetzt möglich ist“, und überlassen die gründliche Behandlung den späteren Kapiteln.
Dasselbe Werkzeug wird endlos aufgerufen und nie fertig. Der Agent kann nicht erkennen, dass das Ziel erreicht ist, und dreht leer.
Erste Hilfe: Immer eine Obergrenze für die Rundenzahl setzen. Aufeinanderfolgende Aufrufe mit denselben Argumenten erkennen und stoppen.
Das Werkzeug gibt riesiges JSON oder eine ganze Seite zurück, das komplett ins Gespräch fließt, was Kosten und Latenz aufbläht.
Erste Hilfe: Auf der Werkzeugseite nur die nötigen Felder behalten / vor der Rückgabe zusammenfassen. Nicht den ganzen Text unbearbeitet übergeben.
Je mehr Runden, desto höher stapelt sich der Gesprächsverlauf; er nähert sich der Obergrenze und wird langsam, teuer und instabil.
Erste Hilfe: Alte Wortwechsel zusammenfassen und komprimieren / unnötige Werkzeugergebnisse verwerfen. Gründliche Behandlung ab dem nächsten Kapitel.
📊 Alle drei sind Probleme des „Kontext-Designs“. Endlosschleife, aufgeblähter Rückgabewert und Kontext-Aufblähung laufen an der Wurzel alle auf das Kontext-Design hinaus: „Was und wie viel übergebe ich dem LLM?“ Diese Denkweise ist als Context Engineering systematisiert und bildet das Rückgrat der Agentenentwicklung. Zunächst als Losung: „nicht zu viel übergeben, nicht zu viel anhäufen“.
- Minimaler Agent = die vier Elemente in kleinster Form zusammengesetzt. Der Unterschied zu einer einzelnen API-Nutzung ist nur die Schleife.
- Die Schleife wiederholt eine Runde: „denken → Werkzeug aufrufen → Ergebnis zurückgeben → wieder denken → bei Abschluss anhalten“. Eine Obergrenze für die Rundenzahl ist Pflicht.
- Beim Werkzeug die Definition (Name, Beschreibung, Argumente) ans LLM übergeben, die eigentliche Funktion bei sich ausführen. Das LLM fordert nur an.
- Die Umsetzung geht auf zwei Wegen: handgeschriebene Schleife (zum Lernen) und Tool-Runner eines SDK (für die Praxis). Das Innere ist dasselbe.
- Von Anfang an per Log beobachten und die klassischen Stolpersteine finden: Endlosschleife, aufgeblähter Rückgabewert, Kontext-Aufblähung.
Läuft ein Agent, ist als Nächstes das Werkzeug ernsthaft zu erweitern. In Kapitel 3 „MCP und Werkzeuganbindung“ binden wir Werkzeuge auf standardisierte Weise (MCP) an externe Dienste und Daten an und weiten die Hand des Agenten schlagartig aus. Wollen Sie das Gesamtbild des vorigen Kapitels prüfen, kehren Sie zu Kapitel 1 zurück.