Dieser Artikel basiert auf einem Vortrag, den ich am 17. September 2026 auf dem Entwickler Summit in Berlin zum ersten Mal gehalten habe.
Wenn ein Agent die Tests und die Implementierung schreibt, prüft er seine eigene Interpretation gegen seine eigene Interpretation. Deshalb halte ich die rote Phase für die einzige Arbeit im Entwicklungsprozess, die ich einem Agenten nicht überlassen darf. Wer den fehlschlagenden Test schreibt, legt fest, was richtig ist. Wer nur noch Reviews durchführt, verliert die Kontrolle über genau diese Festlegung.
Ich schreibe seit 1998 PHP und arbeite seit 2000 an PHPUnit. In dieser Zeit habe ich viele Werkzeuge kommen sehen, die die Softwareentwicklung grundlegend verändern sollten, und die meisten haben es nicht getan. Agenten auf Basis großer Sprachmodelle halte ich für die Ausnahme. Sie verändern unsere Arbeit tiefer als jedes Werkzeug vor ihnen.
Das Wort „Künstliche Intelligenz“ vermeide ich dabei. Es unterstellt Verstehen, und Verstehen ist genau das, was in diesem Prozess knapp wird. Was den Code schreibt, ist ein Sprachmodell: ein außerordentlich fähiges Werkzeug, das Muster fortsetzt.
In der Schleife des Agenten kommst du nicht mehr vor
Am Anfang steht eine Spezifikation oder ein Bug-Report, am Ende ein Commit. Dazwischen arbeitet der Agent selbstständig. Er liest sich in die Codebasis ein, schreibt Tests, führt sie aus, implementiert und behebt, was fehlschlägt. Das wiederholt er, bis alles grün ist.
Code Completion schlägt vor, ein Chatfenster antwortet. Ein Agent fragt nicht nach und legt dir nichts zur Auswahl vor. Er verfolgt ein Ziel. Du kommst in diesem Ablauf zweimal vor, am Anfang und am Ende. Die Schleife in der Mitte läuft ohne dich.
Bei der unterstützten Entwicklung schreibst du den Code, das Werkzeug schlägt vor, und du entscheidest in jedem einzelnen Schritt. Bei der agentenbasierten Entwicklung verfolgt der Agent das Ziel, und du setzt es und prüfst das Ergebnis. Die Rollen sind vertauscht. Fast alles, was wir über Jahrzehnte an Qualitätssicherung aufgebaut haben, setzt aber die alte Verteilung voraus.
IDEs, Versionskontrolle und Continuous Integration waren Antworten auf die Frage, wie wir die Arbeit organisieren. Wer sie macht, stand nie zur Debatte. Jetzt steht es zur Debatte: Pull Requests entstehen automatisiert, und der Mensch übernimmt das Review. Das klingt nach einer Rollenverteilung, mit der wir leben können, weil der Mensch das letzte Wort behält. Ich bezweifle, dass er es wirklich noch hat.
Wer nur noch Reviews durchführt, verliert die Kontrolle. Wer spezifiziert, behält die Verantwortung.
Kontrolle kannst du verlieren, die Verantwortung behältst du trotzdem. Wenn generierter Code in Produktion Schaden anrichtet, fragt niemand, welches Modell ihn geschrieben hat.
Grüne Tests haben mir nicht gesagt, ob der Code korrekt ist
In einem meiner kleineren Pakete stand jahrelang ein TODO. Es ging um ACPATH, die Anzahl der azyklischen Ausführungspfade durch eine Methode. Das Paper dazu hatte ich, die Stelle im Code auch. Fast fünf Jahre lang fehlte mir die Ruhe, es zu implementieren.
Vor ein paar Monaten habe ich einen Agenten damit beauftragt, weil ich beobachten wollte, was passiert. Deshalb habe ich bewusst etwas gewählt, bei dem ich kein Experte bin: Codeanalyse kenne ich, Graphentheorie ist nicht mein Feld. Damit war ich in der Lage, in der die meisten von uns sind, wenn sie einen Agenten auf etwas ansetzen. Ich konnte das Ergebnis lesen, aber nicht aus eigener Kraft herleiten.
Die Metrik selbst ist schnell erklärt. Eine Methode mit drei aufeinanderfolgenden if-Anweisungen hat 2 × 2 × 2 = 8 azyklische Pfade. Solche Fälle kann ich von Hand nachzählen.
Nach etwa fünfzehn Minuten lag das Ergebnis vor:
- Die Tests waren grün.
- Der Code war so lesbar und strukturiert, wie ich ihn selbst geschrieben hätte.
- Die erzeugten Visualisierungen der Pfadberechnung sahen plausibel aus.
- Die Fälle, die ich nachrechnen konnte, stimmten.
Ob die Implementierung korrekt ist, weiß ich bis heute nicht. Für echte Methoden mit Schleifen, verschachtelten Bedingungen und frühen Returns kann ich nicht feststellen, ob der Algorithmus aus dem Paper richtig umgesetzt wurde. Gerade für diese Fälle will ich die Metrik überhaupt haben. Drei if-Anweisungen zähle ich ohne Werkzeug.
Der Agent generiert Code schneller, als ich die Domäne verstehen kann. Er brauchte fünfzehn Minuten. Ich bräuchte Tage oder Wochen, um mich in Graphentheorie einzuarbeiten, das Paper zu durchdringen und eine unabhängige Referenzimplementierung zu bauen. Damit wäre die Zeitersparnis weit überzogen, und deshalb macht das niemand.
Schlechter Code fällt im Review auf. Gefährlich wird Code, der gut genug aussieht, dass wir aufhören, ihn zu hinterfragen. Richtig aussehen und richtig sein fühlen sich im Review identisch an.
Tony Hoare hat 1980 in seiner Turing Award Lecture „The Emperor's Old Clothes“ zwei Wege beschrieben, ein Software-Design zu konstruieren: so einfach, dass offensichtlich keine Mängel vorhanden sind, oder so kompliziert, dass keine Mängel offensichtlich sind. Die ACPATH-Implementierung gehörte zur zweiten Art, obwohl an ihr nichts erkennbar schlecht war. Sie lag in einer Domäne, in der ich Mängel nicht hätte sehen können. Früher führte schlechtes Design dorthin. Heute reicht Geschwindigkeit: Wenn Code schneller entsteht, als Verständnis wachsen kann, landest du automatisch bei der zweiten Art.
Sprachmodelle senken die Schuld, die wir messen können
Margaret-Anne Storey hat in „From Technical Debt to Cognitive and Intent Debt“ einen Rahmen vorgeschlagen, mit dem ich mein Erlebnis einordnen kann. Sie unterscheidet drei Arten von Schulden:
- Technical Debt lebt im Code und macht Systeme schwerer änderbar. Wir sehen sie und haben Werkzeuge und Metriken dafür.
- Cognitive Debt lebt in den Menschen. Das geteilte Verständnis im Team erodiert.
- Intent Debt lebt in den Artefakten. Es ist nicht mehr festgehalten, wofür das System da ist, welche Ziele es erfüllen soll und welche Constraints warum galten.
Für die beiden letzten gibt es keinen Linter. Sprachmodelle senken die technische Schuld mit saubererem Code, weniger Duplikation und mehr Tests. Die beiden unsichtbaren Schulden beschleunigen sie gleichzeitig. Bei ACPATH hatte ich kaum technische Schuld und maximale kognitive.
Storey greift dafür einen Begriff von Shaw und Nave auf. Cognitive Offloading ist rational: Typprüfung überlasse ich dem Type Checker, Coding Standards dem Linter. Ich weiß, was ich delegiere, und woran ich merke, wenn etwas schiefgeht. Cognitive Surrender sieht von außen genauso aus, nur prüfst du nicht mehr, was das Werkzeug liefert, weder mit dem Bauchgefühl noch mit bewusstem Nachdenken. Das beginnt schleichend, etwa beim dritten Pull Request, der genauso aussieht wie die beiden davor, die in Ordnung waren.
Beunruhigt hat mich ein Befund besonders: Cognitive Surrender lässt das Vertrauen steigen. Das Team fühlt sich kompetenter, als es ist, und zwar am stärksten dort, wo das Modell danebenliegt. Dort sieht der Code nämlich am glattesten aus.
Ein Test legt fest, was „richtig“ heißt
Wenn Verständnis und Absicht die Engpässe sind, brauchen wir eine Sprache, in der wir sie festhalten. Ich halte Tests für diese Sprache. Mit ihnen sagen wir der Maschine seit Jahrzehnten, was richtig ist, und das funktioniert auch mit Agenten.
Ein Test prüft, ob sich der Code richtig verhält. Diese Funktion kennen wir so gut, dass sie eine zweite verdeckt: Er definiert, was „richtig“ überhaupt heißt. Das Ticket ist mehrdeutig, und wer den Code geschrieben hat, arbeitet nächstes Jahr vielleicht woanders. Der Test ist der einzige Ort, an dem diese Festlegung ausführbar steht. Storey nennt so etwas ein intent artifact.
Nimm die Anforderung „Berechne den Rabatt für Bestandskunden.“ Ab wann ist jemand Bestandskunde? Wie wird gerundet? Was passiert bei negativen Beträgen?
$kunde = new Kunde(bestellungen: 3);
$this->assertSame(333, $rabatt->fuer($kunde, 3333)); // Beträge in Cent
Dieser Test legt fest, dass drei Bestellungen einen Bestandskunden ausmachen. Zehn Prozent von 3333 Cent sind 333,3 Cent. Weil der Test 333 erwartet, ist nebenbei die Rundung entschieden. Zu negativen Beträgen sagt er nichts. Den fehlenden Fall kann ich hinschreiben, und dann ist auch er entschieden. Ein Test kann unvollständig sein. Was er sagt, sagt er eindeutig.
Grün und Refactor kann ich abgeben, Rot nicht
Den TDD-Zyklus teile ich mit dem Agenten so auf:
- Red: Ich schreibe den fehlschlagenden Test und lege fest, was gelten soll, bevor es existiert.
- Green: Der Agent implementiert, bis der Test grün ist. Darin ist er außerordentlich gut, weil er ein klar definiertes Ziel und ein maschinell prüfbares Abbruchkriterium hat.
- Refactor: Der Agent räumt auf, und ich prüfe das Ergebnis. Ob eine Struktur gut ist, entscheidet sich daran, ob Menschen sie in zwei Jahren noch verstehen, und das kann nur ein Mensch beurteilen.
Der Agent arbeitet in derselben Schleife wie vorhin, aber jetzt komme ich in ihr vor: Jeder Durchlauf beginnt mit meinem Test.
Die rote Phase ist die einzige, die nicht delegiert werden darf.
Die Festlegung, was richtig ist, lagere ich auch dann nicht aus, wenn die Zeit knapp wird, denn an ihr hängt die Verantwortung. Ein Review reagiert auf etwas, das schon da ist. Der Test kommt vorher, und an keiner anderen Stelle im Prozess lege ich fest, statt zu beurteilen. Wer den Agenten auch die Tests schreiben lässt, hat ihm die Definition von „richtig“ übergeben.
Je schneller Code entsteht, desto mehr Prüfschichten braucht er
Tests lösen das Problem trotzdem nicht allein. Hillel Wayne hat aufgezählt, was jeweils nicht genügt: Unit Tests, Typsysteme, Contracts, formale Spezifikationen, Code Review. Ein Programm kann auf genau eine Weise richtig sein und auf unendlich viele Weisen falsch.
Ich arbeite deshalb mit mehreren Schichten:
- Statische Analyse findet Fehler ohne Ausführung und gibt sofortiges, objektives Feedback auf generierten Code.
- Example Tests prüfen konkretes Verhalten bei konkreten Eingaben.
- Property-Based Testing verallgemeinert über ganze Eingabebereiche.
- Mutation Testing prüft die Tests.
- Fuzzing sucht das, was niemand benannt hat.
Die Schichten greifen ineinander. Was Mutation Testing findet, ändert meine Tests. Was Fuzzing findet, wird zum eigenschaftsbasierten Test. Jede Schicht schärft die anderen.
Bei generiertem Code leistet Mutation Testing am meisten. Ein Agent kann Code produzieren, der alle Tests besteht und trotzdem subtil falsch ist. Das Modell hat dann eine Lücke in den Tests gefüllt, ohne zu fragen, und es hatte keinen Grund, dieselbe Entscheidung zu treffen wie du. Macht Mutation Testing aus $bestellungen >= 3 die Bedingung $bestellungen > 3 und schlägt ein Test fehl, war die Grenze festgelegt. Bleibt alles grün, hast du sie nur zufällig getroffen. Ein Agent, der später an diesem Code arbeitet, kann sie dann verschieben, ohne dass etwas Alarm schlägt.
Wenn der Test die Sprache ist, ist Mutation Testing ihre Grammatikprüfung.
Im Review geht es jetzt um Absicht und Architektur
Die Frage „Ist dieser Code korrekt?“ beantworten statische Analyse und Testsuite inzwischen zuverlässiger als ein Mensch, der den Code überfliegt. Im Review rücken deshalb andere Fragen nach vorn. Passt die Änderung zu unseren Architekturentscheidungen? Legen die Tests wirklich fest, was gelten soll, oder haben sie nur zufällig recht? Entstehen hier Schulden?
Storey weist auf einen zweiten Effekt hin: Review verteilt Verständnis im Team. Damit ist es das direkteste Gegenmittel gegen kognitive Schuld, und ich würde es als Letztes wegoptimieren, wenn Agenten Pull Requests schneller liefern, als ein Team sie besprechen kann.
Ähnliches gilt für Architecture Decision Records, Technical Debt Records, Qualitätsziele und Coding Guidelines. Ein ADR, der Event Sourcing für Bestellungen festlegt, schließt CRUD für diesen Bereich aus, ohne dass irgendwo ein Verbot steht. Ein Agent, der dieses Dokument im Kontext hat, hält sich daran. Dokumentation schränkt damit auch den Lösungsraum ein, in dem der Agent arbeitet.
Storey warnt allerdings davor, das Verstehen zu automatisieren. Wenn du dir die Architekturdokumentation generieren lässt, hast du ein Dokument und keine Auseinandersetzung, aus der es hätte entstehen sollen. Die Artefakte kann ein Modell schreiben, das Verständnis dahinter nicht.
Wer die rote Phase abgibt, gibt das Lernen ab
Dirk Riehle hat formuliert, dass Code generierende Werkzeuge vor allem denen nützen, die ohne sie aufgewachsen sind. Eine großangelegte Commit-Analyse von Daniotti, Wachs, Feng und Neffke stützt das. Jüngere Entwicklerinnen und Entwickler nutzen diese Werkzeuge deutlich stärker und profitieren deutlich weniger davon. Die Produktivitätsgewinne fließen fast nur den Erfahrenen zu.
Das ACPATH-Beispiel erklärt, warum. Um zu erkennen, dass generierter Code nur richtig aussieht, brauchst du genau die Erfahrung, die wir uns früher beim Schreiben solchen Codes erarbeitet haben.
Jason Gorman sagt in seinem Vortrag „The Team Is The Real Product“: Das Team ist das Produkt, und Software ist das Nebenprodukt seines Lernens. Wenn das stimmt, optimieren wir gerade das Nebenprodukt und lassen das Produkt verkümmern.
Teuer war immer das Einarbeiten
Wem gehört der Entwicklungsprozess? Nach außen ist das eine vertraute Frage. Die Infrastruktur konzentriert sich auf wenige Anbieter. Für die Open-Source-Welt kommt eine neue Frage hinzu: Warum sollte jemand eine Bibliothek pflegen, wenn sich für jeden Kontext Spezialcode generieren lässt? Digitale Souveränität ist dabei eine Frage der Kontrolle.
Schwerer wiegt für mich die Frage nach innen, weil sie sich auch ohne jede Plattformabhängigkeit stellt. Eine Organisation kann die Fähigkeit verlieren, ihr eigenes System zu ändern, während Rechte und Zugriff unverändert bei ihr liegen. Wer diese Fähigkeit jedes Mal neu beschafft, baut für jede Fahrt ein neues Auto. Das Argument ist älter als agentische Entwicklung, und agentische Entwicklung beschleunigt es.
Es ist auch die Gegenrechnung zum Versprechen, ein stehendes Team sei überflüssig, weil der Agent die Codebasis in Minuten liest. Das Lesen des Codes war nie der teure Teil. Teuer war das Einarbeiten ins Geschäft, in die bestehende Software und ineinander. Der Agent liest den Code, und die Absicht steht dort nicht. Was er nicht rekonstruieren kann, muss festgehalten sein: im Test und im ADR, von jemandem, der es verstanden hat.
Ohne diese Praktiken bleibt nur Zustimmung
Klare Spezifikationen, strenge Tests, transparente Reviews und verständliche Dokumentation habe ich lange als Schutz vor den Fehlern der Werkzeuge gesehen. Heute halte ich sie für die Voraussetzung dafür, dass Menschen in diesem Prozess überhaupt handeln können. Ohne Spezifikation kannst du nichts festlegen, ohne Review teilst du kein Verständnis, und ohne Dokumentation gibt es keine Absicht, auf die sich später jemand berufen kann. Wer das alles weglässt, entscheidet nichts mehr und stimmt nur noch zu.
Storey vermutet, dass die zentrale Fähigkeit von Entwicklerinnen und Entwicklern künftig darin besteht, ein zutreffendes Verständnis davon aufrechtzuerhalten, was das System tut, warum es das tut und wie es sich entwickeln kann.
Den Satz vom Anfang, wer den fehlschlagenden Test schreibt, lege fest, was richtig ist, muss ich an dieser Stelle einschränken. Den Test muss ich nicht selbst tippen. Ein Sprachmodell kann ihn aus einer Spezifikation erzeugen, die ich geschrieben habe. Entscheidend ist, was danach mit ihm passiert. Ohne mein Review hält der generierte Test fest, was das Modell aus meiner Spezifikation herausgelesen hat. Damit ist er ein Characterization Test: Er beschreibt ein Verhalten, ohne dass jemand entschieden hat, dass es das richtige ist. Erst wenn ich ihn lese, mit meiner Absicht abgleiche und akzeptiere, wird er zum Akzeptanztest. Was richtig ist, legt dann fest, wer den Test akzeptiert hat.
Wie Berufseinsteigerinnen und -einsteiger die Erfahrung erwerben sollen, die sie brauchen, um generierten Code zu beurteilen, weiß ich nicht. Ich weiß auch nicht, was einem Team bleibt, das nur noch abnimmt. Den ACPATH-Code habe ich seit Monaten. Ob er korrekt ist, weiß ich immer noch nicht.