Zum Inhalt springen
OpenClaw Akademie

Modul 06 · 11 min

OpenClaw Anti-Patterns - Häufige Fehler und wie du sie vermeidest

Die zwölf häufigsten Fehler beim Bauen mit OpenClaw und wie du sie identifizierst, bevor sie dich Geld oder Reputation kosten.

Wer einmal einen OpenClaw-Agent bis in Production gebracht hat, kennt diese zwölf Anti-Patterns aus eigener, schmerzhafter Erfahrung. Sie sind keine theoretischen Fingerzeige aus einem Architekturpapier, sondern echte Stolperfallen, die zwischen einem funktionierenden Prototyp und einem teuren Ausfall am Wochenende stehen. In dieser Lektion gehen wir die häufigsten Fehler gemeinsam durch, schauen uns Beispiele an und besprechen, wie du jedes Pattern frühzeitig erkennst. Am Ende bekommst du eine Checkliste, die du vor jedem Production-Push abarbeiten kannst.

1. Generische Tools mit “Mach was Sinnvolles”-Docstring

Das mit Abstand häufigste Anti-Pattern beim Bauen mit OpenClaw ist das generische Tool. Du registrierst eine Funktion namens process_data mit dem Docstring “verarbeitet Daten” und überlässt es dem LLM, herauszufinden, was das eigentlich heißen soll. Das funktioniert in 60 Prozent der Fälle, weil moderne Sprachmodelle sehr nachsichtig mit unklaren Spezifikationen umgehen. In den restlichen 40 Prozent rät das Modell und du bekommst Tool-Calls, die formal korrekt sind, semantisch aber komplett am Ziel vorbeigehen.

Der Kern des Problems ist, dass der Docstring nicht für Menschen geschrieben ist, sondern für das LLM. Er ist das einzige Stück Kontext, das der Agent über das Tool hat, bevor er entscheidet, ob er es ruft. Ein vager Docstring zwingt das Modell zu Annahmen, und Annahmen sind teuer: jede falsche Tool-Wahl kostet Tokens, Latenz und im schlimmsten Fall echte API-Kosten gegen Drittsysteme. Schreibe Docstrings deshalb wie eine Mini-API-Doku, mit klaren Erwartungen an Inputs, Outputs und Fehlerfällen.

Eine gute Regel ist die Drei-Sätze-Probe. Satz eins: was tut das Tool, in einem Satz. Satz zwei: wann sollte es gerufen werden, mit einem konkreten Beispiel. Satz drei: was kommt zurück und wie sieht ein Fehler aus. Wer diese drei Sätze nicht in den Docstring bekommt, sollte das Tool entweder feiner schneiden oder die Spezifikation überdenken.

# Schlecht: zu generisch, das LLM muss raten
@tool
def process_data(input: str) -> str:
    """Verarbeitet Daten und gibt Ergebnis zurück."""
    return run_pipeline(input)
# Gut: prazise, mit Beispiel und Fehlerverhalten
@tool
def extract_invoice_total(pdf_url: str) -> dict:
    """Extrahiert den Rechnungsbetrag aus einer PDF-Rechnung.

    Rufe dieses Tool, wenn ein Nutzer nach dem Gesamtbetrag einer
    PDF-Rechnung fragt, deren URL bekannt ist. Beispiel-Input:
    'https://example.com/invoice-2026-04.pdf'.

    Rueckgabe: {'total': float, 'currency': str, 'date': str}.
    Wirft ValueError, wenn die PDF nicht gelesen werden kann.
    """
    return parse_pdf_invoice(pdf_url)

2. Memory ohne Obergrenze

Der zweite Klassiker ist Memory ohne Obergrenze. Du nutzt einen Buffer-Memory, weil das die Standardeinstellung ist, und schreibst jedes Tool-Ergebnis in den Kontext zurück. Beim ersten Test merkt niemand etwas, weil die Konversation kurz ist. Drei Tage später meldet sich ein Power-User mit einer Sitzung, die 80 Iterationen lang ist, und der Token-Counter explodiert in den vierstelligen Eurobereich pro Stunde.

Das Problem ist nicht der Memory selbst, sondern die fehlende Begrenzung. Jeder Memory-Typ in OpenClaw lässt sich mit einem max_tokens-Parameter, einer Token-Window-Strategie oder einer Summary-Funktion konfigurieren. Wer das nicht aktiv setzt, übernimmt schweigend den Default, und Defaults sind in einem Prototyp grosszügig gewählt. Eine sinnvolle Production-Strategie ist Window-Memory plus Summary, sobald das Window voll wird: die letzten zwei Iterationen bleiben wortwörtlich, alles davor wird auf eine kompakte Zusammenfassung reduziert.

Genauso wichtig wie das Limit ist das Monitoring. Logge bei jeder Iteration die aktuelle Token-Zahl im Memory und schicke sie als Metrik an dein Observability-System. Wenn die Kurve stetig steigt, statt sich um einen Mittelwert einzupendeln, hast du ein Leck: irgendwo wird in den Memory geschrieben, ohne dass je etwas verworfen wird. Solche Lecks fallen erst in Production auf, weil Tests selten lang genug laufen, um sie zu provozieren.

3. Try/Except über den ganzen Agent-Loop

Es gibt eine besondere Sorte von Defensiv-Code, die mehr Schaden anrichtet als sie verhindert: das alles-umschliessende try/except um den kompletten Agent-Loop. Die Intention ist verständlich, denn niemand möchte, dass ein einzelner Bug die gesamte Anwendung in den Abgrund reisst. Das Resultat ist aber oft schlimmer: Silent-Failures, bei denen der Agent stumm scheitert, eine generische “Etwas ist schiefgelaufen”-Meldung ausspuckt und keine Telemetrie hinterlasst.

Der bessere Ansatz ist Fehlerbehandlung auf Tool-Ebene plus bewusstes Durchlassen kritischer Fehler. Tool-Fehler sind Geschäftsfehler (“die API ist down”, “der Datensatz existiert nicht”) und gehören als strukturierte Fehlermeldung zurück ans LLM, damit es eine alternative Strategie wählen kann. Programmierfehler sind technische Fehler (“Index out of range”, “Connection refused gegen den Memory-Store”) und gehören in den Stacktrace, in dein Sentry und in einen Restart-Mechanismus.

Wer alles fängt, signalisiert dem Modell falsche Sicherheit und nimmt sich gleichzeitig die Möglichkeit, kritische Fehler überhaupt zu sehen. In einer gesunden OpenClaw-Architektur sind die Fehlerklassen explizit getrennt: Tool-Errors haben einen klaren Typ, der ans LLM zurückgereicht wird, und alles andere fliegt nach oben in den Process-Manager.

# Schlecht: alles wird verschluckt
try:
    result = agent.run(query)
except Exception as e:
    return "Etwas ist schiefgelaufen, bitte spaeter erneut versuchen."
# Gut: Tool-Fehler explizit, Systemfehler propagieren
from openclaw.errors import ToolError

try:
    result = agent.run(query)
except ToolError as e:
    # Geschaeftsfehler ans LLM zurueckgeben, damit es retry oder
    # Fallback waehlen kann
    return agent.recover_with_fallback(query, error=e)
# Systemfehler werden bewusst NICHT gefangen, sie sollen den
# Process killen, damit systemd/PM2 neu startet und Sentry alarmiert.

4. Multi-Agent als Erstreflex

Wer zum ersten Mal von Multi-Agent-Architekturen hört, will sofort drei Agenten bauen: einen Researcher, einen Writer, einen Reviewer. Das klingt sauber und wie aus dem Lehrbuch, ist aber für 90 Prozent aller realen Anwendungsfälle Overengineering. Multi-Agent ist sinnvoll, wenn die Rollen tatsächlich unterschiedliche Personas, unterschiedliche Tool-Sets und unterschiedliche Modelle brauchen. In allen anderen Fällen ist es nur eine teure Form, einen einfachen Loop zu komplizieren.

Der Test ist einfach. Kannst du in einem Satz erklären, was Agent A tut und warum Agent B das nicht selbst tun könnte? Wenn die Antwort “weil ich das so im Buch gesehen habe” lautet, baust du das falsche System. Multi-Agent-Setups verbrennen Tokens, weil zwischen den Agenten ständig Kontext kopiert werden muss. Sie sind schwerer zu debuggen, weil jeder Hop eine eigene Iteration mit eigenem Memory ist, und sie fügen einen Synchronisationspunkt ein, an dem Fehler doppelt schwer zu lokalisieren sind.

Der pragmatische Weg ist: starte mit einem Agent, der mehrere Tools hat. Erst wenn du klar messen kannst, dass dieser eine Agent an der Aufgabe scheitert oder dass eine Aufgabe sauber in zwei voneinander unabhängige Phasen zerfällt, lohnt sich Multi-Agent. Beispiel für ein gutes Multi-Agent-Szenario: ein billiger Sonnet-Agent klassifiziert eingehende E-Mails, ein teurerer Opus-Agent beantwortet nur die als wichtig markierten. Hier verdient die Trennung sich kostentechnisch, weil 95 Prozent der Mails nie das teure Modell sehen.

5. Prompts im Python-Code statt externalisiert

Es ist verführerisch, den System-Prompt direkt als String-Konstante in das Python-Modul zu schreiben, in dem der Agent definiert wird. Bei den ersten 50 Zeilen Prompt fühlt sich das gut an, weil alles an einem Ort liegt. Bei 500 Zeilen Prompt wird es unangenehm, bei 1500 Zeilen ist die Codebasis kaputt. Diffs sind unleserlich, Reviews dauern doppelt so lange und A/B-Tests zwischen zwei Prompt-Varianten brauchen plötzlich Code-Branches statt Daten-Branches.

Die saubere Lösung ist Externalisierung in eigene Dateien, typischerweise im Markdown-Format. Lege einen prompts/-Ordner an und benenne die Dateien nach Rolle und Version: system_default.md, system_v2_strict.md, tool_invoice_extraction.md. Im Code lädst du sie über einen Loader, der den Inhalt einliest und gegebenenfalls Variablen substituiert. Dieser kleine Refactor zahlt sich nach drei Tagen aus, weil du jetzt Pull-Requests gegen Prompts machen kannst, die wirklich nur den Prompt zeigen.

Externe Prompts haben einen weiteren Vorteil: sie lassen sich mit nicht-technischen Stakeholdern teilen. Ein Produktmanager oder eine UX-Autorin kann ein Markdown-File lesen und kommentieren, ein 1500-Zeilen-Python-File nicht. Wer Prompts als Produktmaterial begreift, sollte sie auch wie Produktmaterial verwalten: getrennt vom Code, versioniert, mit klaren Verantwortlichen.

6. Tool-Output ohne Schema-Validierung

Tools liefern Strings, Dicts oder JSON zurück, und es ist erstaunlich, wie oft diese Rückgaben unvalidiert ans LLM weitergereicht werden. Das geht solange gut, wie das Tool stabile Outputs liefert. Sobald sich das Schema ändert, etwa weil eine externe API ein neues Feld einführt oder ein Feld umbenennt, fängt der Agent an, sich an Daten zu klammern, die er nicht mehr versteht. Im besten Fall halluziniert er einen Workaround. Im schlimmsten Fall reicht er Müll an den Nutzer durch.

Schema-Validierung ist deshalb keine Nice-to-have-Feature, sondern Pflicht. Definiere für jedes Tool ein Pydantic-Modell, eine Zod-Schema oder mindestens eine TypedDict-Struktur, gegen die du den Output prüfst, bevor du ihn ans LLM zurückgibst. Wenn die Validierung fehlschlägt, wirf einen klaren Tool-Error. Das Modell kann dann entscheiden, ob es einen Retry mit anderen Parametern macht, das Tool ganz weglässt oder dem Nutzer ehrlich sagt, dass es gerade nicht weiterkommt.

Ein Nebeneffekt der Schema-Validierung ist Dokumentation. Wer ein Pydantic-Modell pflegt, hat automatisch eine maschinenlesbare Spezifikation des Tool-Outputs, die in API-Docs, Tests und Mocks wiederverwendet werden kann. Wer keine Validierung pflegt, hat in drei Monaten kein Wissen mehr darüber, was ein Tool eigentlich liefern sollte. Das ist ein klassischer Wartungsschuldfall, der erst auffällt, wenn ein neuer Entwickler ans Projekt kommt und einen ganzen Tag verliert, um den Output-Vertrag zu rekonstruieren.

7. System-Prompt im selben File wie Logik

Verwandt mit dem Externalisierungs-Anti-Pattern, aber nochmal eine Stufe drastischer: der System-Prompt steht nicht nur im Python-Code, sondern im gleichen File wie die Agent-Logik selbst. Das macht das File doppelt unleserlich, weil zwei völlig verschiedene Lesegruppen es betreuen müssen: Entwickler, die die Loop-Mechanik verstehen, und Prompt-Autoren, die den Tonfall feinjustieren. Beide stehen sich im Diff-Tool im Weg.

Die Trennung ist trivial herzustellen. Eine Datei für die Agent-Konfiguration und Loop-Definition, eine zweite Datei (oder ein Verzeichnis) für die Prompts. Diese Trennung ist auch eine Vorbedingung für sauberes Caching: wer den System-Prompt cacht, will sicher sein, dass kein versehentlicher Code-Change die Cache-Invalidierung auslöst. Wer Prompt und Logik im selben File hat, riskiert, dass jeder Refactor Cache-Misses auslöst.

8. LLM-Provider-Lock-In

Wer einen Agent ausschließlich gegen die OpenAI-API entwickelt und alle Promptformulierungen, Tool-Schemas und Token-Limits auf dieses eine Modell zuschneidet, baut sich einen goldenen Käfig. Sobald Anthropic ein neues Modell veröffentlicht, das günstiger oder besser ist, ist der Wechsel kein Konfigurationsschritt mehr, sondern ein Refactoring-Projekt. Das gleiche gilt umgekehrt: wer nur gegen Anthropic baut und plötzlich aus Compliance-Gründen ein lokales Modell via Ollama nutzen muss, hat ein Problem.

Der saubere Weg ist die Abstraktion über das Provider-Interface von OpenClaw. Konfiguriere den Provider in einer ENV-Variable und teste deinen Agent regelmässig gegen mindestens zwei verschiedene Modelle, idealerweise eines mit grosszügigem Tool-Use-Support und eines mit knapperer Function-Calling-Schiene. Wer beide bedienen kann, ist gegen Marktbewegungen weitgehend immun.

Provider-Lock-In hat ausserdem eine kommerzielle Dimension. Wer ein Volumengeschäft mit einem einzigen Modell-Anbieter aufbaut, wird zum Preisnehmer. Sobald der Anbieter die Preise erhöht, hast du keinen Hebel. Wer dagegen zwischen mehreren Providern routen kann, behält Verhandlungsmacht und kann auf neue, günstigere Modelle in Stunden statt Wochen umschalten. Das ist auch der Grund, warum Open-Source-Modelle wie Hermes Agent von Nous Research zunehmend an Bedeutung gewinnen: sie geben dir eine echte Ausweichoption, falls die proprietären Anbieter ihre Konditionen verschlechtern.

9. Keine Token-Limits

Token-Limits sind für viele Teams ein abstraktes Thema, das erst wichtig wird, wenn die erste Rechnung kommt. Das ist genau der falsche Moment, denn dann ist der Schaden schon entstanden. OpenClaw bietet mehrere Stellen, an denen du Token-Verbrauch hart limitieren kannst: pro Iteration, pro Sitzung, pro Tag und pro Tool-Aufruf. Wer keines dieser Limits aktiviert, vertraut darauf, dass weder Nutzer noch das Modell selbst aus dem Ruder laufen. Diese Annahme hält selten lange.

Ein realistischer Production-Setup hat drei Limits gleichzeitig. Erstens ein Iterationslimit (max_iterations), das verhindert, dass eine einzelne Sitzung in eine Endlosschleife gerät. Zwei stelliger Wert, typisch zwischen 10 und 25. Zweitens ein Token-Budget pro Sitzung, das den maximalen Schaden eines kompromittierten oder bösartigen Inputs deckelt. Drittens ein Tagesbudget auf Provider-Ebene, das selbst bei 100 entgleisten Sitzungen die monatliche Cloud-Rechnung in beherrschbarem Rahmen hält.

Token-Limits sind kein Misstrauensvotum gegen das LLM, sondern eine elementare Verteidigung gegen Edge-Cases. Ein Nutzer, der zufällig ein Tool in einer Schleife zum Laufen bringt, ein Prompt-Injection-Versuch, der den Agent in eine ungewöhnliche Verhaltenstrajektorie zwingt, oder schlicht ein Bug, der eine Tool-Antwort immer wieder als unvollständig erkennt: in jedem dieser Fälle rettet dich ein hartes Limit vor einer vier- oder fünfstelligen Rechnung am Monatsende. Wer Limits hat, schläft nachts ruhiger.

10. Secrets im .env, das ins Repo gepusht wurde

Es passiert immer noch, und es wird so oft passieren, wie es Junior-Entwickler gibt, die zum ersten Mal mit Secrets arbeiten. Die .env-Datei wandert versehentlich in den Commit, der Push geht raus, und der Anthropic-API-Key liegt 30 Sekunden später öffentlich auf GitHub. Bots, die solche Leaks scannen, finden den Key in unter einer Minute. Bis du den Leak bemerkst, sind oft schon hunderte Euro Cloud-Kosten verursacht.

Die Verteidigung ist mehrschichtig. Erstens: .env gehört in .gitignore, ohne Ausnahme. Zweitens: installiere git-secrets oder ein vergleichbares Pre-Commit-Hook-Tool, das Commits mit Schlüsselmustern blockiert. Drittens: rotiere kompromittierte Keys sofort und nutze provider-seitige Budgets, damit ein Leak nicht in den vierstelligen Bereich eskalieren kann. Viertens: nutze für Production niemals die gleichen Keys wie für Development, damit ein Dev-Leak nicht direkt deine Production-Quoten leerräumt. Diese vier Schritte kosten zusammen weniger als eine Stunde Setup und können dir einen mittleren vierstelligen Betrag und einen unschönen Compliance-Vorfall ersparen.

11. Logs ohne Strukturierung

Wer einen Agent in Production betreibt und nicht strukturiert loggt, betreibt ihn blind. Standard-Print-Statements oder unformatierte logging.info-Aufrufe sind in einem komplexen Multi-Tool-Loop wertlos, weil du im Fehlerfall nicht herausfinden kannst, welcher Tool-Call zu welcher Iteration zu welcher Sitzung gehörte. Sobald mehr als ein Nutzer gleichzeitig den Agent benutzt, verschmelzen alle Logs zu einem unbrauchbaren Strom.

Die Lösung heißt strukturiertes Logging mit JSON-Output und konsistenten Feldern. Mindestkanon: session_id, iteration, tool_name, tokens_used, latency_ms, level, message. Mit diesem Set kannst du in Loki, Datadog oder einem anderen Logaggregator innerhalb von Sekunden filtern, welche Sitzungen welche Tools wie oft genutzt haben und wo die Latenzausreißer liegen. Wer dazu noch Tracing per OpenTelemetry einbaut, hat ein Monitoring auf dem Niveau eines Microservices.

Strukturierte Logs sind zudem die Basis für Lernschleifen. Wer Tool-Erfolgsraten, Token-Verteilungen und Iterationszahlen über Wochen aggregiert, sieht plötzlich, welche Prompt-Varianten besser performen, welche Tools überflüssig sind und welche Nutzer-Segmente überdurchschnittlich teure Sitzungen produzieren. Ohne diese Daten optimierst du nach Bauchgefühl, mit ihnen optimierst du nach Evidenz. Der Unterschied ist nach drei Monaten messbar, nach sechs Monaten dramatisch.

12. “Es geht lokal” als Akzeptanzkriterium

Das letzte und vielleicht heimtückischste Anti-Pattern ist die Aussage “es geht lokal”, verbunden mit der stillen Annahme, dass Production sich genauso verhalten wird. Lokal hast du tendenziell schnelle Netzwerkverbindungen, einen gemütlichen Single-User-Workload, frische Tokens, leeren Memory und ein Filesystem mit Schreibrechten überall. Production hat nichts davon. Was lokal in zwei Sekunden läuft, kann in Production unter Last fünf Sekunden brauchen, mit gelegentlichen Ausreißern in den zweistelligen Bereich.

Die Disziplin heißt: kein Feature gilt als fertig, bevor es in einer produktionsähnlichen Umgebung lief. Das muss nicht die echte Production sein, eine Staging-Umgebung mit echten Provider-Calls, realistischer Datenmenge und mindestens einem synthetischen Lastgenerator reicht. Wichtig ist, dass die Umgebung die gleichen Latenzen, die gleichen Rate-Limits und die gleichen Secret-Stores nutzt wie Production. Wer dies konsequent macht, fängt 80 Prozent aller Production-Bugs eine Stufe früher ab.

Die zweite Disziplin ist das bewusste Provozieren von Fehlern. Wer im Test nie einen Tool-Timeout gesehen hat, hat den Code für den Tool-Timeout-Pfad nie wirklich getestet. Schalte gezielt Mocks ein, die Latenzen, Fehler und schlechte Antworten simulieren. Das mag nach Zusatzaufwand klingen, aber es zahlt sich um Größenordnungen aus, sobald du den ersten Production-Incident vermeidest, der dich sonst nachts aus dem Bett geholt hätte. “Es geht lokal” ist kein Akzeptanzkriterium, es ist eine Hypothese, die in einer realistischen Umgebung verifiziert werden muss.

Checkliste vor dem Production-Push

  1. Jeder Tool-Docstring besteht den Drei-Sätze-Test (Was, Wann, Was-zurück).
  2. Memory-Limit ist explizit gesetzt und Token-Verbrauch wird pro Iteration geloggt.
  3. Tool-Errors und Systemfehler sind über getrennte Exception-Klassen behandelt.
  4. Kein Multi-Agent-Setup ohne klare, messbare Begründung pro Rolle.
  5. Alle Prompts liegen externalisiert in prompts/ und sind versioniert.
  6. Jeder Tool-Output durchläuft Schema-Validierung, bevor er ans LLM geht.
  7. Provider-Konfiguration kommt aus ENV-Variablen, kein Hardcoding eines Anbieters.
  8. max_iterations, Session-Token-Budget und Tagesbudget sind aktiv.
  9. .env steht in .gitignore, git-secrets blockt Commits mit Keys, Production-Keys sind separiert.
  10. Strukturiertes JSON-Logging mit session_id, iteration, tool_name, tokens_used, latency_ms.
  11. Es gibt einen Staging-Lauf mit echten Provider-Calls und synthetischer Last.
  12. Fehlerinjektion (Timeouts, schlechte Antworten, Rate-Limits) wurde aktiv getestet.

Nächster Schritt

Wenn dein Agent diese zwölf Anti-Patterns überstanden hat, ist er bereit für die Bonus-Lektionen. In Hermes Agent zeige ich dir, wie du das Open-Source-Modell von Nous Research als günstige, datenschutzfreundliche Alternative zu proprietären Providern in OpenClaw integrierst. In NanoClaw lernst du den Minimalbau eines Agents kennen, der bewusst auf jeden Schnickschnack verzichtet und damit ein perfektes Vorbild für ressourcenarme Edge-Deployments ist. Und in Iron Claw bekommst du das Härtungspaket für sicherheitskritische Setups, in denen Compliance, Audit-Trails und Rollenrechte über simplen Code-Komfort gehen. Damit schließt du den Kreis vom Prototyp über die Produktivsetzung bis zur sicheren Skalierung.

Häufige Fragen zu diesem Modul

Was ist das häufigste Anti-Pattern bei OpenClaw?

Zu generische Tools mit unklaren Docstrings - das LLM rät, was es tun soll, statt klare Schritte zu wählen.

Wie erkenne ich Token-Wastage frühzeitig?

Aktiviere den Token-Counter im Verbose-Log und setze ein Tageslimit per Provider-Konfiguration. Wenn der Counter explodiert, liegt es meist an unkontrolliertem Memory-Wachstum.

Was tun, wenn der Agent in Schleifen läuft?

Setze max_iterations strikt (zum Beispiel 10) und logge die letzten drei Tool-Calls - meist erkennst du dann ein Tool, das immer wieder den gleichen Fehler liefert.

Warum sollte ich keine try/except über den ganzen Agent packen?

Weil du dann Silent-Failures bekommst. Behandle einzelne Tool-Fehler explizit und lass kritische Fehler bewusst durchschlagen, damit Restart und Alerting greifen.

Wann ist Multi-Agent zuviel?

Wenn du nicht in einem Satz erklären kannst, was jede Agenten-Rolle tut und warum sie eine eigene Persona braucht. Im Zweifel: ein Agent mit klaren Tools.

Sollte ich Prompts in Code oder externalisieren?

Externalisiere sie in eigene Dateien (prompts/*.md) - das erleichtert Diffs, Reviews und A/B-Tests massiv.