Handbücher · Agent-Harnesses

Build: Der Loop

Lektion 6/910 Min. LesezeitProfi

Lernziele

  • Du baust einen Agenten-Loop mit zwei Tools gegen die Messages-API und startest ihn im eigenen Terminal.
  • Du erklärst, welche Rolle stop_reason, tool_use und tool_result im Loop spielen.
  • Du nennst die zwei Lücken, die diesen Loop zur Vorführung machen.

Die Lektion Was ein Harness ist behauptet, dass im Kern jedes HarnessAlles, was festlegt, was der Agent erreichen darf: Tools, Berechtigungen, Sandbox, Zeitlimits und die Prüfung, bevor eine Aktion wirkt. Englisch für Geschirr oder Gestell.Im Glossar eine while-Schleife steckt. Diese Lektion belegt es. In rund 80 Zeilen Python entsteht ein AgentEin System, in dem ein Sprachmodell seinen nächsten Schritt selbst wählt: Es ruft Werkzeuge auf, wertet das Ergebnis aus und macht weiter, bis das Ziel erreicht ist.Im Glossar, der Dateien liest und Befehle ausführt, gegen die echte Claude-API. Die nächste Lektion ergänzt die Teile, die daraus einen Harness machen. Für alle drei Build-Lektionen zusammen planst du einen Abend ein.

Du brauchst Python 3.10 oder neuer, pip install anthropic (getestet mit 2.8.0) und die Umgebungsvariable ANTHROPIC_API_KEY.

Zwei Tools

Ein Tool · engl. toolEin Werkzeug, das das Modell aufrufen kann: eine API, eine Datenbankabfrage, ein Shell-Befehl, eine Suche. Über Tools wirkt das Modell auf die Welt.Im Glossar besteht aus einem JSON-Schema und einer Funktion. Das Schema liest das Modell · engl. model, LLMDas Sprachmodell (LLM, Large Language Model). Es liest Text, schreibt Text und entscheidet in einem Agenten, was als Nächstes passiert.Im Glossar, die Funktion führt dein Code aus. Die Beschreibungen zählen so viel wie der Code, denn das Modell wählt ein Tool nach seiner Beschreibung. Die Lektion Tools und MCP zeigt das ausführlich.

Der Agent bekommt genau zwei Tools:

  • read_file liest eine Textdatei und gibt den Inhalt zurück.
  • run_command führt einen Shell-Befehl aus und gibt Exit-Code, Standardausgabe und Fehlerausgabe zurück. Nach 30 Sekunden bricht der Befehl ab.

Über run_command listet der Agent Dateien, durchsucht sie mit grep und startet Tests.

Der Code

Die Datei heißt agent.py. Der Loop · engl. agent loopDie Schleife eines Agenten: denken, handeln, beobachten, wiederholen. Zwischen den Durchläufen wird der Kontext des Modells jedes Mal neu gebaut.Im Glossar steckt in der Funktion agent, alles darüber ist Vorbereitung.

# agent.py – der nackte Loop: zwei Tools, eine while-Schleife
import json
import subprocess
import sys

import anthropic  # pip install anthropic

MODEL = "claude-opus-5-5"
SYSTEM = "You are a coding agent working in the current directory. Investigate before you conclude."

TOOLS = [
    {
        "name": "read_file",
        "description": "Read a text file and return its full contents. Use for source files, configs and logs. Paths are relative to the working directory.",
        "input_schema": {
            "type": "object",
            "properties": {"path": {"type": "string", "description": "File path, e.g. src/main.py"}},
            "required": ["path"],
        },
    },
    {
        "name": "run_command",
        "description": "Run a shell command and return its exit code, stdout and stderr. Use for listing files, searching and running tests. Times out after 30 seconds.",
        "input_schema": {
            "type": "object",
            "properties": {"command": {"type": "string", "description": "The command, e.g. ls -la"}},
            "required": ["command"],
        },
    },
]


def read_file(path):
    with open(path, "r", encoding="utf-8") as f:
        return f.read()


def run_command(command):
    result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=30)
    return f"exit code {result.returncode}\n{result.stdout}{result.stderr}"


def execute(name, tool_input):
    if name == "read_file":
        return read_file(tool_input["path"])
    if name == "run_command":
        return run_command(tool_input["command"])
    raise ValueError(f"unknown tool: {name}")


def agent(task):
    client = anthropic.Anthropic()  # liest ANTHROPIC_API_KEY
    messages = [{"role": "user", "content": task}]
    while True:
        response = client.messages.create(
            model=MODEL, max_tokens=16000, system=SYSTEM, tools=TOOLS, messages=messages,
            output_config={"effort": "high"},
        )
        for block in response.content:
            if block.type == "text":
                print(block.text)
        if response.stop_reason != "tool_use":
            return
        messages.append({"role": "assistant", "content": response.content})
        results = []
        for block in response.content:
            if block.type != "tool_use":
                continue
            print(f"-> {block.name} {json.dumps(block.input)}")
            try:
                results.append({"type": "tool_result", "tool_use_id": block.id,
                                "content": execute(block.name, block.input)})
            except Exception as exc:
                results.append({"type": "tool_result", "tool_use_id": block.id,
                                "content": f"Error: {exc}", "is_error": True})
        messages.append({"role": "user", "content": results})


if __name__ == "__main__":
    agent(" ".join(sys.argv[1:]) or "List the files here and describe this project.")

Zeilen 8-9

Der Code nennt Claude Opus 5.5, das aktuelle Standardmodell. Der Systemprompt ist ein einziger Satz: Erst untersuchen, dann urteilen.

Was die Teile tun

Die API zeigt über stop_reason, was das Modell vorhat. Steht dort tool_use, enthält die Antwort einen oder mehrere tool_use-Blöcke. Jeder hat eine id, einen name und eine bereits geparste Eingabe input.

Dein Code hängt die gesamte Antwort response.content unverändert an den Verlauf. Aktuelle Modelle liefern darin Thinking-Block · engl. thinking blockEin Block in der Antwort des Modells, der seine Überlegungen trägt, meist ohne sichtbaren Text und mit einer Signatur. Er geht unverändert mit dem Verlauf zurück und gilt nur, solange alles davor gleich bleibt.Im Glossar mit, die mit dem Verlauf zurückgehen müssen. In unseren Läufen mit Haiku 5.5 war der Text dieser Blöcke leer. Jeder trug nur eine Signatur mit 944 Zeichen. Das ist der Standard: Die Überlegungen selbst bleiben verborgen, die Signatur bindet sie an das Gespräch.

Dann führt dein Code jeden Tool-Aufruf aus. Alle Ergebnisse gehen als tool_result-Blöcke in einer Nachricht zurück, zugeordnet über tool_use_id. Auch Fehler gehen zurück, markiert mit is_error. Mit einer guten Fehlermeldung steuert das Modell in einer Runde um.

Speichere die Datei als agent.py und starte sie in einem Projektordner:

python agent.py "find the TODO comments in this repo and summarise them"

So sah ein Lauf in einem kleinen Testprojekt mit drei TODO-Kommentaren und einem FIXME aus:

Der nackte Loop (eigener Lauf mit Haiku 5.5, 13.11.2026, gekürzt)1/5
  1. $python agent.py "find the TODO comments in this repo and summarise them"

Das Modell hat nach dem ersten grep von sich aus weitergesucht, auch nach FIXME. Den zweiten Befehl hat es selbst zusammengesetzt. Thorsten Ball baut in seinem Tutorial denselben Loop in Go, die Ressourcen verlinken es. Der Zweck dieser Lektion ist, dass du den Loop im eigenen Terminal laufen siehst.

Was macht der Loop mit dieser Antwort?

Ordne jede Situation dem Schritt zu, den agent.py als Nächstes ausführt.

Noch offen (5)

  • stop_reason ist end_turn, die Antwort enthält nur Text.
  • Die Antwort enthält zwei tool_use-Blöcke für read_file.
  • read_file bekommt einen Pfad zu einer Datei, die es nicht gibt.
  • Das Modell ruft ein Tool namens write_file auf.
  • stop_reason ist max_tokens, weil das Limit erreicht ist.

Loop endet (0)

    Tool ausführen, Ergebnis zurück (0)

      Fehler als Ergebnis zurück (0)

        Was es noch nicht ist

        Der Agent ist eine Vorführung. Er führt jeden Befehl aus, den das Modell vorschlägt, auch rm. Bei einer langen Aufgabe wächst der Verlauf ohne Grenze, und jede Runde schickt ihn vollständig an die API. Einen Fehler 400 fängt der Code nicht ab, und nichts hält ein Modell auf, das sich im Kreis dreht.

        Für das Rechte-Problem und das Kontext-Problem gibt es zwei Bausteine: ein Permission-Gate und ein Kontextbudget. Beide baut die nächste Lektion, Build: Berechtigungen und Kontext, zusammen mit einer Stoppregel · engl. stop ruleDie Bedingungen, unter denen ein Loop endet: Der Prüfer ist zufrieden, das Runden-Limit ist erreicht oder zwei Versuche hintereinander sind gleich.Im Glossar.

        Merksätze

        • Ein Agent ist ein Loop: API aufrufen, Tool-Aufrufe ausführen, Ergebnisse zurückgeben, bis stop_reason nicht mehr tool_use ist.
        • Die Antwort geht unverändert in den Verlauf, samt Thinking-Blöcken mit ihrer Signatur.
        • Alle Tool-Ergebnisse einer Runde gehen in einer Nachricht zurück, zugeordnet über tool_use_id, Fehler mit is_error.
        • Bei Opus 5.5 setzt du effort selbst, weil der Standardwert medium ist, und gibst max_tokens Platz für das Nachdenken.
        • Ohne Gate und Budget führt der Loop jeden Befehl aus und lässt den Verlauf unbegrenzt wachsen.

        Prüf dich selbst

        Denkfrage

        Warum hängt der Code response.content an und nicht nur den Text der Antwort?

        Denkfrage

        Ein Befehl scheitert. Warum geht der Fehler an das Modell, statt das Programm zu beenden?

        Prüf dich selbst

        1. 1Woran erkennt agent.py, dass das Modell fertig ist?
        2. 2Das Modell schickt drei tool_use-Blöcke in einer Antwort. Wie gehen die Ergebnisse zurück?
        3. 3Warum setzt der Code bei Opus 5.5 effort ausdrücklich?
        4. 4Was fehlt diesem Loop, bevor du ihn unbeaufsichtigt laufen lässt?

        Selbst nachweisen

        0 von 3 erledigt

        Quellen

        1. Tool use with Claude · Anthropic, Stand: Nov. 2026

          Tool-Schemas, tool_use und tool_result.

        2. Parallel tool use · Anthropic, Stand: Nov. 2026

          Mehrere Tool-Aufrufe in einer Antwort, alle Ergebnisse in einer Nachricht.

        3. Preserved thinking · Anthropic, Stand: Nov. 2026

          Warum Thinking-Blöcke unverändert zurückgehen.

        4. How to build an agent · Thorsten Ball, Apr. 2025

          Derselbe Loop als Coding-Agent in Go.

        Dein Fortschritt bleibt nur in diesem Browser gespeichert.