This blog post is also available in English

Moderne KI-Tools ermöglichen es Entwickler:innen, schneller mehr Code zu produzieren und Aufgaben abzuschließen. Allerdings hat die Steigerung der individuellen Entwicklerproduktivität auf Unternehmensebene nicht zu einer höheren Gesamtproduktivität geführt (siehe diesen Bericht), da sich der Engpass von der Code-Erstellung zum Code-Review verlagert hat.

Die Kernfrage lautet daher: Wie können wir Reviews besser handhabbar machen?

Dies ist kein neues Problem. Umfangreiche, schwer verständliche Merge Requests waren immer schon möglich. Da KI-Tools jedoch deutlich mehr Code mit weniger Aufwand generieren können, wird dieses Problem künftig wahrscheinlich verschärft auftreten.

Eine der wertvollsten Fähigkeiten für Softwareentwickler:innen ist das Zerlegen von Aufgaben in leicht überprüfbare und integrierbare Teile. Mit wachsender Erfahrung verbessern wir unser Gespür dafür, wie viel Code wir sinnvoll verwalten können, und lernen, Aufgaben entsprechend zu strukturieren.

Im Kontext von LLMs ist die Begrenzung des Kontexts besonders wichtig, da diese Modelle unberechenbar werden können, wenn ihr Kontext zu groß wird. Sie könnten beispielsweise vorschlagen, komplexe Umstrukturierungen manuell fertigzustellen, oder falsch behaupten, dass fehlschlagende Tests nichts mit ihren Änderungen zu tun haben.

Bei der Arbeit mit einem LLM wird jede Eingabe zum Systemkontext hinzugefügt, der die Modellausgabe bestimmt. Das LLM benötigt den passenden Kontext für sinnvolle Antworten.

Dies ist ein wesentlicher Vorteil des agentischen Programmierparadigmas – der Agent kann relevanten Kontext aus Deiner Codebasis abrufen und dem LLM zusätzlich zu Deinen Eingaben zur Verfügung stellen.

Die Schwierigkeiten beim Verwalten des Systemkontexts

Dieser detaillierte Kontext macht agentische Programmierung so effektiv und leistungsfähig.

Die Kehrseite: Während einer Programmiersitzung kann viel „Rauschen” im Kontext landen. Große eingelesene Dateien, zahlreiche Fehlermeldungen und ablenkende Fragen – all das belastet den Kontext.

LLMs haben konkrete Kontextgrößenbeschränkungen, und die Modellleistung sinkt mit wachsendem Kontext (siehe Bericht hier). Ab einem bestimmten Punkt setzt „Kontextfäule” ein, und die Ergebnisse werden unzuverlässig.

Mit diesem Wissen können wir den Systemkontext kompakt halten, indem wir beim Verweisen auf Dateien präzise sind, nur relevante Fehlermeldungen einfügen oder Sitzungen zusammenfassen und neu starten, um überflüssige Informationen zu entfernen. Eine weitere Strategie ist die Delegation spezifischer Aufgaben an Unteragenten mit eigenem Systemkontext.

In der Praxis erreiche ich selten die Grenzen des Systemkontexts. Obwohl es vereinzelt vorkommt, dass Aufgaben den Systemkontext an seine Grenzen bringen und zu schlechteren Ergebnissen führen, resultiert „Kontextfäule” meist daraus, dass ich vergessen habe, eine neue Sitzung mit frischem Kontext zu starten. Für die meisten Implementierungsaufgaben reicht der Systemkontext völlig aus.

Reparatur eines außer Kontrolle geratenen Vibe-Coding-Experiments

Die größere Herausforderung liegt häufig in der gegenteiligen Richtung: Wie kann ich die Menge des von einem Coding-Agenten generierten Codes überschaubar halten, um ihn verstehen und validieren zu können?

Bei einem Experiment mit Vibe-Coding für einen UI-Prototyp erstellte ich durch mehrere Iterationen große Mengen generierten Codes, die ich mental nicht mehr erfassen konnte, wobei manches unvollständig wirkte.

Dies zeigt, wie mein kognitives Kontextfenster durch den Arbeitsumfang überlastet wurde. Die Versuchung war groß, alles in einem riesigen Merge Request zu pushen und an problematischen Stellen zu kommentieren, dass ich die Details später ausarbeiten würde.

Aber wäre das fair? Diese kognitive Last auf Kolleg:innen zu übertragen, die alles durcharbeiten und hoffen müssen, nichts Wichtiges zu übersehen?

Definitiv nicht.

Um das Problem zu lösen, nutzte ich eine angepasste Version meines Git-Workflows, den ich in einem anderen Beitrag beschrieben habe, um den Code in überschaubare Arbeitseinheiten zu sortieren. Mein KI-Agent identifizierte zunächst drei Features. Es waren tatsächlich fünf.

Der entscheidende Punkt war, den aktuellen Arbeitsumfang zu reduzieren. Ich konzentrierte mich auf eine spezifische Umstrukturierung und verwendete git add -p, um Änderungen interaktiv zu prüfen. Die Frage „gehört dies zu Feature X?” wurde so zu einer einfachen Ja/Nein-Entscheidung statt einer umfassenden Bewertung jeder Änderung. Mit git stash -u legte ich alle anderen Änderungen beiseite, prüfte die vorbereiteten Änderungen mit git diff --staged, führte ein gründliches Review durch und ergänzte fehlende Tests. Erst als dieser Teil vollständig war, erstellte ich einen Merge Request.

Anschließend holte ich mit git stash pop die restlichen Änderungen zurück. Es war immer noch zu viel, aber weniger als zuvor – und etwas weniger ist besser als nichts.

Ich setzte diesen Prozess fort, bis ich alle Features separieren, prüfen und in ordnungsgemäßen Merge Requests bereitstellen konnte. Der scheinbare Produktivitätsgewinn durch den KI-Agenten wurde vollständig durch den mentalen Aufwand aufgehoben, den ich investieren musste, um die Komponenten in verständliche Einheiten zu zerlegen.

Aus dieser Erfahrung habe ich gelernt, genauer auf die Menge des erzeugten Codes zu achten, um nicht denselben Fehler zu wiederholen.

Halte Deinen Aufgabenbereich klein

Die beste Maßnahme gegen übermäßigen Kontext ist Prävention. Kleine Aufgabenbereiche schaffen kohärente Arbeitseinheiten sowohl für unser Gehirn als auch für das LLM. Der Begriff „Context Engineering” mag wie ein Modewort klingen (und ich bin etwas allergisch gegen Modewörter), doch letztlich geht es darum, den Umfang eines Features minimal zu halten und irrelevante Informationen aus dem Kontext fernzuhalten, damit LLMs optimal arbeiten können.

In der Praxis bedeutet dies, einen Agenten lieber kleine, aufeinander aufbauende Schritte ausführen zu lassen, statt allgemeine Anweisungen zu geben und zu hoffen. Der Plan-Modus in Agenten wie Claude Code und Codex kann dabei nützlich sein. Auch testgetriebene Entwicklung ist hier wertvoll: Tests im Voraus zu schreiben und dann den Agenten um eine Implementierung zu bitten, die diese Tests erfüllt, schafft klare Leitplanken.

Dies führt dazu, dass wir Änderungen häufiger committen und pushen, als wir es gewohnt sind. Wie ich in meinem Beitrag über meinen Git-Workflow erläutert habe, sollte jeder Commit eine überschaubare Arbeitseinheit darstellen. Während es früher vielleicht 2–3 Stunden Programmieren brauchte, um diesen Umfang zu erreichen, können wir mit KI-Agenten diesen Punkt bereits nach 15 Minuten erreichen!

In solchen Fällen ist es besser, innezuhalten, den Code zu optimieren, zu committen und zu pushen. Da die geschaffene Arbeitsmenge für Dich verständlich ist, sollte sie auch für Deine Kolleg:innen leicht überprüfbar sein.

Der resultierende Code-Durchsatz wird weiterhin höher sein als bei traditioneller Entwicklung ohne KI, aber in kleinere, leichter zu überprüfende Einheiten verpackt, die schneller in die Produktion gelangen können – ohne gefährliche „LGTM”-Reviews bei Änderungen, die das menschliche Gehirn überfordern.

Nicht korrigieren

Aufgrund der Natur des Systemkontexts ist es schwierig, einen Agenten zur Änderung seiner Vorgehensweise zu bewegen, sobald er einen unerwünschten Ansatz gewählt hat. Der Systemkontext enthält die gesamte bisherige Sitzung, einschließlich der „fehlerhaften” Implementierung, gefolgt von einer nachträglichen Korrekturanweisung.

Kein Wunder, dass der Agent sich schwertut, seine Herangehensweise zu ändern.

Bei schrittweisem Vorgehen mit ständiger Überwachung des Fortschritts ist es besser, nicht zu korrigieren, sondern die Sitzung zu beenden, wenn etwas schief läuft. Starte lieber eine neue Sitzung mit präziseren Anweisungen zur Feature-Implementierung.

Im Zweifel wegwerfen

Ich erstelle inzwischen „WIP”-Commits, nachdem mein Agent einen Teil meiner Aufgabe erfolgreich abgeschlossen hat und ich mit der Arbeit zufrieden bin. Das erleichtert es mir, unerwünschten Code einfach zu löschen.

Wenn wir eine Sitzung neu starten, ohne suboptimalen Code zu entfernen, wird dieser sofort wieder Teil des Systemkontexts und bringt den Agenten erneut auf den falschen Weg.

Die Sunk-Cost-Fallacy kann ebenfalls eintreten: Wir sind konditioniert zu glauben, dass bestehender Code wertvoll sein muss (weil wir gewohnt sind, eigene Zeit ins Schreiben zu investieren). Dies ist heute weniger zutreffend: Wenn ein Agent diesen Code in 10 Minuten erstellen konnte, kann er problemlos in gleicher Zeit ein ähnliches Codefragment neu erstellen – diesmal mit präziseren Anweisungen für bessere Ergebnisse.

In meinem früheren Beispiel hätte ich vermutlich das gleiche Ergebnis mit weniger Zeitaufwand und Kopfschmerzen erreicht, indem ich die fünf Aufgaben in fünf separaten agentischen Programmiersitzungen komplett neu implementiert hätte.

Eine neue Art der Iteration

Diese Methode kleinerer Schritte und Code-Iterationen fühlt sich vertraut an: Statt einen Test zu schreiben und Code zur Erfüllung dieses Tests zu iterieren, formulieren wir eine präzise Aufgabenbeschreibung und optimieren die Antwort oder verwerfen sie, bis wir mit unserem Code zufrieden sind.

Dieser Ansatz ermöglicht echte Produktivitätsgewinne durch KI-Einsatz, ohne diese im Review-Prozess wieder einzubüßen. Während wir weiterhin lernen, KI optimal in unseren Workflow zu integrieren, werden wir uns anpassen und schneller committen und pushen, ohne Dynamik zu verlieren. Wir schulden es uns selbst und unseren Kolleg:innen, unsere Arbeit in überschaubaren Einheiten zu halten, die mental erfassbar sind – ohne das Gefühl, dabei Kompromisse einzugehen.