Lektion 01 · Grundlagen

Ohne Schleife kein Agent

Das ganze Geheimnis von Claude Code lässt sich in einer Zeile ausdrücken: while stop_reason == "tool_use"

⏱ ~10 Min · 📝 3 interaktive Widgets · 🧑‍💻 Basiert auf shareAI-lab · s01_agent_loop.py

Was macht ein Agent eigentlich?

Wenn du Claude Code im Terminal startest und ihm sagst, "erstelle eine Liste aller TODO-Kommentare", siehst du Folgendes: Es entscheidet selbst, zunächst grep auszuführen, dann ein paar Dateien per cat zu lesen und schließlich Markdown auszugeben. Das Modell führt keinen Code direkt aus — es fordert lediglich die Ausführung an. Was es so aussehen lässt, als hätte es "Hände und Füße", ist der etwa 30-zeilige Glue-Code drumherum.

In dieser Lektion nehmen wir diesen Glue-Code auseinander. Er heißt Agent Loop und hat folgende Struktur:

while response.stop_reason == "tool_use":
    response = LLM(messages, tools)      # 1. ask the model
    execute_tools(response.tool_calls)   # 2. run what it asked for
    messages.append(tool_results)        # 3. feed results back

Das war's. Mehr nicht. In der Produktionsversion von Claude Code kommen Berechtigungen, Hooks, Subagents, Worktree-Isolierung und Speicherkomprimierung hinzu — aber der Kern sind immer noch diese vier Zeilen.

Grundlegende Intuition: Jede Modellantwort bedeutet entweder "ich möchte ein Tool aufrufen" oder "ich bin fertig". Solange ersteres gilt, läuft die Schleife weiter; sobald letzteres eintritt, endet sie. Das Kriterium ist das Feld stop_reason in der Antwort.

messages[] Schritt für Schritt wachsen sehen

Die folgende Schleife simuliert diese Aufgabe: "Welche Dateien gibt es im aktuellen Verzeichnis? Und lies dann package.json." Klicke auf Step, um jeweils eine Aktion innerhalb der Schleife voranzuschreiten. Links siehst du die Konversation als Sprechblasen, rechts das eigentliche messages[]-Array, das ans Modell übergeben wird — beobachte, wie es wächst.

Tool-Ergebnisse müssen zurück in den Nachrichtenverlauf

Der häufigste Anfängerfehler ist, die "Tool-Ausführung" als Nebeneffekt zu betrachten — ausgeführt und fertig. Aber das Modell kann beim nächsten Durchlauf nur messages[] sehen. Was nicht darin steht, existiert für das Modell nicht. Fehlt das append, bricht die gesamte Schleife.

Die Fehler unterscheiden sich dabei:

  • append vergessen: Das Modell sieht das Ergebnis im nächsten Durchlauf nicht und fragt dasselbe Tool erneut — eine Endlosschleife entsteht.
  • append vorhanden, aber tool_use_id fehlt: Die Anthropic API antwortet direkt mit dem Fehler tool_result must have tool_use_id, die Schleife bricht beim API-Aufruf ab.

Dieselbe Aufgabe: "Zähle alle Python-Dateien im Projekt". Zwei Versionen nebeneinander — schau dir den Unterschied an.

stop_reason verstehen

Jede Modellantwort enthält ein stop_reason-Feld, das bestimmt, ob die Schleife weiterläuft:

  • tool_use — Das Modell möchte ein Tool aufrufen, Schleife weiter.
  • end_turn — Das Modell ist fertig, Schleife beenden.
  • max_tokens — Das Token-Limit wurde erreicht und die Ausgabe abgeschnitten, Schleife beenden (als Fehler behandeln, Nutzer informieren).
  • stop_sequence — Eine benutzerdefinierte Stop-Sequenz wurde erkannt, Schleife beenden.

Häufige Bugs: "Schleife weiter solange nicht tool_use" oder max_tokens als normales Ende behandeln.

Lokal ausprobieren

Klone shareAI-lab/learn-claude-code lokal:

git clone https://github.com/shareAI-lab/learn-claude-code
cd learn-claude-code
pip install -r requirements.txt
cp .env.example .env  # fill in ANTHROPIC_API_KEY
python agents/s01_agent_loop.py

Gib ihm dann eine echte Aufgabe: Wie viele .py-Dateien gibt es in diesem Repository? Du wirst sehen, wie es ls -R ausführt, die Ausgabe betrachtet, dann find . -name "*.py" | wc -l ausführt und dir die Antwort gibt. Der gesamte Ablauf ist dieser Loop.

Interaktiv

Widget 1 · Loop Stepper · messages[] wachsen sehen

Verstehen: Tool-Ergebnisse werden im speziellen Format (tool_result-Block mit tool_use_id) in messages zurückgeschrieben — das ist der einzige Weg, wie das Modell beim nächsten Durchlauf weiß, dass das Tool fertig ist.

KonversationsansichtNicht gestartet
Step klicken zum Starten →
messages[] JSONlength: 0
[]
stop_reason:
Interaktiv

Widget 2 · Break the Loop · Korrekt vs. append vergessen

Verstehen: Fehlt nur eine Zeile messages.append(tool_results), ist der Agent kein Agent mehr — er wird zur Maschine, die jede Runde das Gleiche vergisst.

while True:
    resp = LLM(msgs, tools)
    msgs.append({"role":"assistant",
                 "content": resp.content})
    if resp.stop_reason != "tool_use":
        return
    results = execute(resp.tool_uses)
    msgs.append({"role":"user",
                 "content": results})
Simulierter Ablauf
while True:
    resp = LLM(msgs, tools)
    msgs.append({"role":"assistant",
                 "content": resp.content})
    if resp.stop_reason != "tool_use":
        return
    results = execute(resp.tool_uses)
    # BUG: forgot to append results
    # msgs.append(...)
Simulierter Ablauf
Interaktiv

Widget 3 · stop_reason erkennen · 4 echte Antworten beurteilen

Jedes Beispiel ist ein realistisches Modell-Antwort-Fragment. Klicke auf Weiter oder Beenden und erhalte sofortiges Feedback.

0 / 4 richtig