Zum Inhalt springen
KIWITTeilprojekt NBS
← Werkstatt

· Werkstatt

Große Projekte mit Sprachmodellen programmieren

Drei Lehren aus einem Jahr Softwarebau mit Sprachmodellen — und warum die dritte uns selbst getroffen hat

Fünf Informatiker im Teilprojekt bauen Software überwiegend mit Sprachmodellen: eine Zugangsplattform für Hochschulen, einen Stundenplaner, die Auswertungsstrecke für die Diskursdaten. Im August haben wir aufgeschrieben, woran das bei langen Vorhaben schwierig wird. Seither sind zwei weitere Schichten dazugekommen, und beide betreffen unsere eigenen Vorkehrungen.

Erstens: Der Zustand gehört aus dem Gespräch heraus

Ein Sprachmodell arbeitet mit dem, was im laufenden Gespräch steht. Je länger dieses Gespräch wird, desto ungenauer greift das Modell darauf zu — messbar lange, bevor das Kontextfenster voll ist. In der Literatur heißt der Effekt Context Rot. Läuft das Fenster über, wird verdichtet: Anfang und jüngster Teil bleiben, die Mitte wird zusammengefasst.

Anthropic, Effective context engineering for AI agents (2025), beschreibt Context Rot als Fehlerbild agentischer Systeme. Zur Quelle

In der Mitte liegen bei einem längeren Vorhaben genau die Festlegungen: warum ein Feld so heißt, warum ein Weg verworfen wurde, was ein Test absichern soll. Das Modell meldet ihren Verlust nicht. Es antwortet weiter, auf schmalerer Grundlage. So sah das bei uns aus:

  • In einem Stundenplaner wurde eine neu gebaute Komponente über eine Kennzeichnung im Quelltext stillgelegt und die alte weiterverwendet — samt Kommentar, der genau das anwies. Tests, die zuvor als eingebaut gemeldet worden waren, existierten nicht.
  • Prüfsummen über drei Kopien eines Bestands wurden vorgelegt, gebildet über Teile, ohne dass das dabeistand.
  • Mit wachsender Projektgröße wanderten Sonderfälle in die Anweisungen an das Modell, statt in die Programmlogik.

Die Regel, die sich daraus in der Praxis durchgesetzt hat, gilt unabhängig vom verwendeten Modell: Was ein Vorhaben zusammenhält, gehört in Dateien, die bei jedem Lauf neu gelesen werden. Ein größeres Kontextfenster verschiebt den Punkt nur; eine bessere Anweisung hilft nicht gegen etwas, das aus der Anweisung herausgefallen ist.

Praktisch arbeiten wir mit Aufgaben als Markdown-Dateien im selben Git-Verzeichnis wie der Quelltext, mit einer Kommandozeile davor. Entscheidend ist weniger die Ablage als der Ablauf, den sie erzwingt: drei Haltepunkte, von denen zwei vor der ersten Zeile Quelltext liegen.

Backlog.md — Aufgabenverwaltung für die Zusammenarbeit von Menschen und Agenten in einem Git-Verzeichnis, quelloffen. Zur Quelle

HaltepunktWas dort entstehtWer entscheidet
ZerlegungDie Idee wird in einzelne Aufgaben zerlegt, jede mit Beschreibung und AbnahmekriterienMensch gibt frei
PlanDas Modell liest den Bestand und schreibt seinen Umsetzungsplan in die AufgabeMensch gibt frei oder korrigiert
UmsetzungQuelltext, geprüft gegen die vorher geschriebenen Kriteriendie Kriterien

Zweitens: Nicht jede Regel lässt sich prüfen

Wer Abnahmekriterien schreibt, kommt schnell auf die Idee, sie auch überwachen zu lassen. Wir haben ein Prüfprogramm gebaut, das unsere eigenen Regeln gegen den Quelltext hält. Eine dieser Regeln verlangt, dass ein berichteter statistischer Befund gegen den Zufall abgesichert ist. Der Prüfer suchte im Quelltext nach den Wörtern, mit denen wir diese Absicherung benennen.

Dann kamen wir an eine Datei, die die Absicherung ausführt. Sie teilt die Urteilsmenge vierzigmal zufällig in zwei Hälften und vergleicht, was dabei herauskommt. Das ist genau, was die Regel verlangt. Nur benennt die Datei es nicht so — sie hat für den Vorgang keinen der gesuchten Namen. Der Prüfer meldete einen Verstoß.

Wir haben die Regel dann von Hand geprüft, an sieben Dateien, und danach die Gegenprobe gemacht: dieselbe Rechnung, in vier gleichwertigen Schreibweisen aufgeschrieben, wie sie ein Autor ohne besondere Absicht schreibt. Der Prüfer erkannte sie in einer davon.

Die Regel ist dabei nicht unklar. Sie nennt zwei Verfahren und verlangt beide, und niemand im Team hat je nachgefragt, was gemeint ist. Die Schwierigkeit liegt woanders: Es gibt mehrere erlaubte Wege, sie zu erfüllen, und mindestens einer davon hinterlässt im Quelltext keine erkennbare Spur. Zwei Zeilen Division, die einen Vergleichswert ausrechnen, sehen aus wie jede andere Division.

Das ist eine Grenze, keine Schwäche des Werkzeugs. Praktisch brauchbar wird sie, weil man sie vorher feststellen kann. Vier Fragen genügen, bevor eine Regel aufgeschrieben wird:

  • Welche verschiedenen Wege gibt es, diese Regel zu erfüllen?
  • Hat jeder dieser Wege eine Spur, an der ein Programm ihn erkennt? Fehlt eine, wird die Regel als menschliche Entscheidung geführt und nicht als Prüfung.
  • Deckt die Prüfung wirklich alle Stellen ab, für die die Regel gelten soll?
  • Meldet sie am Ende absolute Zahlen und den geprüften Stand, nicht nur einen Anteil?

Die vierte Frage hat sich als die ertragreichste erwiesen, obwohl sie über Prüfbarkeit nichts aussagt. Sie hat bei uns mehr Fehler gefunden als die anderen drei, und zwar immer denselben: eine Kennzahl ohne die Größe, gegen die sie zu lesen ist. Eine Trefferquote ohne die Zahl der Versuche. Ein Anteil ohne seinen Nenner.

Wie die vier Fragen in den Ablauf gekommen sind

Die vier Fragen sind kein Merkzettel geblieben. Sie sind der Grund, warum der Planungsschritt aus dem ersten Teil inzwischen anders aussieht. Jeder Auftrag läuft in zwei getrennten Anläufen: erst ein Plan, den wir lesen, dann die Umsetzung, die wir freigeben. Vor der Freigabe wird nichts gebaut, nichts repariert, nichts erhoben.

Der Plan behandelt jede Teilaufgabe einzeln, und er hat eine feste Gliederung. Sie ist aus den vier Fragen abgeleitet:

  • Welche Wege gibt es, die Aufgabe zu lösen? Aufgezählt, nicht nur der erstbeste, mit dem groben Aufwand je Weg.
  • Je Weg: Woran würde ein Test im Ergebnis erkennen, dass die Aufgabe erfüllt ist? Nachprüfbar ist „jede aufgenommene Zeile trägt ihren Beleg im Wortlaut“. Nicht nachprüfbar ist „der Filter ist besser“ oder „gründlich gelesen“. Hat ein Weg kein solches Merkmal, wird er als menschliche Entscheidung geführt — und das steht im Plan.
  • Welcher Weg wird empfohlen, und warum. Damit steht fest, worauf anschließend getestet wird.
  • Die Tests gehören zur Aufgabe, nicht in eine spätere Runde. Sie stehen schon im Plan als das, was gebaut wird.

Eine Vorgabe steht ausdrücklich dabei, weil sie uns wiederholt gefehlt hat: Der Plan soll nicht den Weg empfehlen, der am schnellsten grün meldet. Wir haben mehrfach erlebt, dass eine bequeme Abkürzung ein Kennzeichen prüft statt der Sache — Hüllseiten statt der eigentlichen Dokumente, Adressen statt gelesener Inhalte, ein Stichwortschirm statt des Gegenstands. Wo ein Weg über ein Kennzeichen entscheidet, gehört das als Schwäche in den Plan, und dann wird ein anderer gewählt.

Zwischen den beiden Anläufen liegt ein menschlicher Haltepunkt, und der ist Absicht. Dort wird gelesen, ob der Plan die Wege ehrlich aufträgt oder eine Abkürzung verdeckt. Dort fallen die Entscheidungen, die eine Instanz nicht selbst treffen kann — welche Lesart einer Frage gilt, woher eine Zahl stammen soll, wie weit der Umfang reicht. Und dort werden Abhängigkeiten aufgelöst, wenn ein Arbeitsstrang Daten aus einem anderen braucht.

Ein Detail hat sich dabei als wichtiger erwiesen, als es klingt: Die Aufträge selbst entstehen in einer eigenen Sitzung, getrennt von der, die arbeitet. Sie hat eine Blaupause vorliegen, in der der Aufbau beider Auftragsarten steht — was ein Planungsauftrag verlangt, was ein Umsetzungsauftrag verlangt, und welcher Teil in welchem Schritt fällig ist. Der Grund ist derselbe wie im ersten Teil: Der Wortlaut eines Auftrags entscheidet darüber, was gebaut wird. Läge er nur im Gesprächsverlauf, wäre er nach dem nächsten Verdichten weg, und die Aufträge würden wieder von Fall zu Fall verschieden aussehen.

Zwei Fälle belegen, dass der Umweg über den Plan sich trägt. Im ersten sollte ein Filter erweitert werden, der Publikationen nach Fachgebiet auswählt. Der Plan rechnete nach und fand, dass die geplante Erweiterung wenige Arbeiten hinzufügt, während die eigentliche Lücke eine Stufe früher liegt: Was schon beim Sammeln nicht abgerufen wurde, kann keine Erweiterung nachholen. Der Weg hätte grün gemeldet und die Lücke stehen gelassen.

Im zweiten sollte eine Aussage über unsere Daten besser abgesichert werden. Der Plan sah nach, woher sie stammt, und fand keine Herkunft: Die Zahl war nie erhoben worden, sondern aus zwei ähnlich benannten Kategorien zusammengelesen. Aus der geplanten Absicherung wurde die erste Messung überhaupt — und sie fiel anders aus.

Die Grenze des Verfahrens haben wir beim Schreiben dieses Beitrags selbst getroffen. Der Auftrag dazu ließ zwei Lesarten zu — den bestehenden Text erweitern oder einen zweiten daneben stellen. Die Wege standen im Plan säuberlich aufgezählt, beide mit ihren Merkmalen, und gebaut wurde der falsche. Eine Aufzählung von Wegen hilft, solange das Ziel feststeht. Ist die Frage selbst mehrdeutig, wählt sie zwischen Wegen zu einem Ziel, das noch offen ist.

Wenn das Ziel erst beim Bauen scharf wird

Dieser Fehlgriff ist der Einzelfall eines Problems, das unsere Arbeit durchgehend bestimmt. Wo eine Anforderung feststeht, lässt sich vorab aufschreiben, was am Ende dastehen soll, und danach vergleichen. Unsere Schritte sind so nicht gebaut. Was der nächste Schritt ist, ergibt sich aus dem Ergebnis des vorigen — und das betrifft nicht nur Einzelheiten, sondern manchmal die Fragestellung.

Ein Beispiel über drei Schritte, alle drei aus den letzten Wochen. Ein Wert lag vor und sollte breiter abgesichert werden. Der Plan dazu sah nach, woher der Wert stammt, und fand keine Herkunft — aus der geplanten Absicherung wurde die erste Messung. Die Messung fiel anders aus als erwartet, womit nicht mehr die Absicherung zur Debatte stand, sondern die Aussage selbst. Der dritte Schritt fügte deshalb nichts hinzu. Er nahm eine Behauptung zurück.

Damit klingt ein Verfahren, das vor jedem Bauen einen Plan verlangt, zunächst nach dem Gegenteil dessen, was hier gebraucht wird. Der Eindruck entsteht, wenn man unter Plan die Beschreibung des Ergebnisses versteht. Unser Plan beschreibt kein Ergebnis. Er hält eine Entscheidung mit ihrem Grund fest: welche Wege es gab, welcher gewählt wurde, woran sich zeigen wird, ob er getragen hat, und was an ihm schwach ist.

Wichtig wird dieser Unterschied in dem Moment, in dem ein Ergebnis überrascht. Dann lautet die Frage: Verhält sich die Sache anders als angenommen, oder war die Annahme von Anfang an die falsche? Ohne die niedergeschriebene Entscheidung lässt sich das kaum auseinanderhalten — mit dem Ergebnis in der Hand findet man jede Annahme plausibel, die dazu passt. Mit ihr ist es eine Frage von zwei Minuten Lesen.

Aus demselben Grund trägt bei uns jedes Ergebnis den Stand, aus dem es entstanden ist: welche Datenfassung, welcher Programmstand. Wenn sich Verfahren und Fragestellung mitentwickeln, ändern sich Zahlen aus zwei ganz verschiedenen Gründen — weil die Sache anders liegt oder weil wir inzwischen anders rechnen. Ohne den Stand daneben sind die beiden Fälle nicht zu unterscheiden, und es fällt erst auf, wenn jemand die ältere Zahl zitiert.

Ein dritter Punkt gehört dazu. Solange das Ziel beweglich ist, ist die Versuchung groß, das Erfolgskriterium dem Ergebnis anzupassen, das herausgekommen ist. Wir schreiben deshalb auf, woran wir den Erfolg messen wollen, bevor gerechnet wird, und legen einen Teil des Materials beiseite, den wir beim Bauen nicht ansehen.

Praktisch bleibt der Aufwand klein, weil der Plan für einen Schritt gilt und nicht für das Vorhaben. Er kostet eine halbe Stunde Lesen und ist mit dem Schritt erledigt. Was bleibt, ist ein Eintrag im Logbuch mit dem, was der Schritt gelehrt hat. Dieser Eintrag ist die Stelle, an der eine Erkenntnis aus der Umsetzung in den nächsten Plan gelangt — und nicht das Gespräch, aus dem sie nach dem nächsten Verdichten verschwunden wäre.

Drittens: Automatisierung macht Fehler unsichtbar

Die Erhebung für den Monitor läuft auf einem eigenen Rechner, täglich, ohne dass jemand zusieht. Im August fiel auf, dass sie seit Tagen erfolgreich endete und nichts holte. Laufzeit viereinhalb Sekunden, Rückgabewert in Ordnung, im Protokoll „nichts Neues“.

Die Ursache war harmlos und deshalb schwer zu sehen: Ein Merker hielt fest, dass alle Einrichtungen abgearbeitet seien, und der Lauf fragte nie, ob das noch stimmt. Aufgefallen ist es, weil jemand im Team nachfragte, ob da eigentlich noch etwas läuft.

Die zweite Form desselben Problems betrifft nicht den Lauf, sondern seine Eingaben. Eine Auswertungsgrafik in einem unserer Vorhaben zeichnete vierunddreißig Punkte und beschriftete sie korrekt mit vierunddreißig. Die Zahl stimmte. Die Datei, aus der sie stammte, war drei Wochen alt, und der Bestand war inzwischen gewachsen. Eine Prüfung, die die Beschriftung gegen die Datei abgleicht, findet diesen Fehler nicht.

Dieselbe Sache ist uns beim Schreiben dieses Beitrags noch einmal begegnet. Für eine Anfrage nach belastbaren Zahlen haben wir nachgesehen, auf welchem Stand die Auswertung beruht. Sie war am selben Tag gerechnet worden, trug also ein frisches Datum. Zwanzig Minuten nach diesem Lauf war eine Regel geändert worden, nach der die Auswertung Publikationen den Hochschulen zuordnet. Jede Zahl sah aktuell aus und war mit der alten Zuordnung gerechnet.

Der Ausweg ist nicht, weniger zu automatisieren. Die Erhebung muss nachts laufen, niemand holt Daten von Hand. Die Grenze verläuft an einer anderen Stelle: Der Automatismus darf holen und sichern. Er darf nicht bestimmen, was als Ergebnis gilt.

  • Ein wiederkehrender Vorgang braucht eine Erwartung an sein Ergebnis, nicht nur an seinen Ausgang. Null geholte Datensätze bei einem täglichen Lauf sind ein Alarm, kein Normalzustand.
  • Jede abgeleitete Zahl trägt, aus welchem Stand sie kommt — nicht nur, wann sie gerechnet wurde. Beides kann weit auseinanderliegen.
  • Wo sich keine Erwartung formulieren lässt, ist der Vorgang nicht überwachbar. Dann gehört das gesagt, statt sich auf einen Rückgabewert zu verlassen.

Umgesetzt haben wir zuerst nur eine Sichtbarmachung: eine Übersicht, die je Quelle den jüngsten Datensatz und den Bauzeitpunkt nennt, und die in der Fußzeile den ältesten Stand zuerst zeigt. Eine einzelne Zahl wäre die bequemere Antwort gewesen und hätte behauptet, alle Quellen seien gleich frisch.

Der Fehler, den wir mit dem Werkzeug gegen ihn gemacht haben

Bei einer Auswertung sollte ein Modell Textstellen einer von zwölf Kategorien zuordnen. Es meldete ein Vielfaches dessen, was ein strenger menschlicher Leser anschließend bestätigte — es zählte Lehrinhalte und Modulbezeichnungen mit, wo es um verhandelte Fragen ging.

Die naheliegende Reparatur: eine kurze Liste von Wendungen, die typisch für solche Fehlmeldungen sind, und ein Filter, der sie aussortiert. Gebaut, geprüft an den Fällen, die vor uns lagen: alle gefangen. Dann haben wir ihn gegen eine Handvoll älterer Fehlmeldungen gehalten, die wir beim Bauen nicht angesehen hatten. Er fing keine einzige.

Der Filter ist nicht in Betrieb gegangen. Die Regel, die davon übrig bleibt, ist unspektakulär und hat uns seither mehrfach geholfen: Jede Musterliste wird gegen Fälle geprüft, die beim Bauen nicht auf dem Tisch lagen. Die Quote an den eigenen Beispielen ist keine Güte.

Was die drei Lehren verbindet

Bei KI-gestützter Arbeit sieht ein Fehler oft aus wie ein Ergebnis. Eine stillgelegte Komponente mit erklärendem Kommentar. Eine Prüfsumme über den falschen Teil. Ein Prüfer, der das Wort mit der Sache verwechselt. Ein Lauf, der erfolgreich endet und nichts tut. Eine alte Zahl mit frischem Datum.

Die eigentliche Arbeit liegt deshalb nicht darin, schneller zu bauen. Sie liegt darin, den Unterschied zwischen Form und Inhalt sichtbar zu halten: mit Werkzeugen dort, wo eine Spur im Artefakt liegt, und mit einem menschlichen Blick dort, wo keine liegt. Die vier Fragen aus dem zweiten Teil sind nichts anderes als die Entscheidung, welcher der beiden Fälle vorliegt.

Der Vergleichsmaßstab, den wir dabei haben, ist ungewöhnlich: Die Beteiligten haben jahrzehntelang ohne solche Werkzeuge entwickelt. Geändert hat sich vor allem die Geschwindigkeit und damit die Dichte der Entscheidungen — was sich früher über Wochen verteilte, fällt an einem Tag an. Bei dieser Dichte fällt ein Fehler, der wie ein Ergebnis aussieht, niemandem mehr nebenbei auf.

Beitrag aus dem KIWIT-Teilprojekt NBS. Beschriebene Arbeit: Prof. Dr. Hendrik Annuth · Prof. Dr. Ulrich Hoffmann · Prof. Ernst Reinking · Mathias Leonhardt, M.Sc..