Mein System-Prompt für die Softwareentwicklung hat acht Fassungen hinter sich. Keine einzige davon kam, weil die Formulierung falsch war. Jede kam, weil das Modell etwas getan hatte, das ich ihm hätte verbieten müssen. Nur war ich nicht darauf gekommen. Und die Korrektur hatte jedes Mal dieselbe Form. Die meisten dieser acht Runden habe ich gebraucht, um das zu sehen: Ich hatte Schilder aufgestellt, und ein Schild liest man im Vorbeigehen.

Der Prompt, mit dem ich angefangen habe

So ungefähr sah das aus, was ich am Anfang übergeben habe — mit der Art Detail, die ein echtes Ticket mitbringt.

This is a refactoring task

the context:
The performance of our endpoint has been pretty bad lately and customers
feel the website getting slower. It happens mostly on the dashboard,
where we load the user and everything attached to them. Support says it
started around the last release but nobody has confirmed that. We use
Spring Boot and JPA, the data is in Postgres, and there is a Redis cache
somewhere in the user service that may or may not still be in use.

what needs to be done:
- Check the user fetching data process
- Check what causes the performance issue
- Look at the queries and the caching
- Find a fix and optimize

what I want you to do:
- Create the fix
- Refactor the parts that are in the way
- Check if performance has been better
- Tell me what you changed

Geben Sie das einem Menschen, und es hält. Da ist eine Lage, da ist eine Diagnose zu stellen, da ist eine Liste dessen, was ich zurückhaben will. Einem Handwerker hätte ich das übergeben, ohne rot zu werden.

Was nicht drinsteht, ist ein einziges Wort darüber, was nicht passieren darf. Also änderte sich der Zuschnitt der Antwort — nirgends stand, dass andere Teams sie lesen. Der Redis-Cache wurde auseinandergenommen; ich hatte Look at the queries and the caching geschrieben, und es schaute. Eine Dependency kam dazu, für ein Problem, nach dem ich nie gefragt hatte. Jedes Einzelne davon war eine faire Lesart dessen, was da stand.

Der Prompt beschrieb das Ziel ziemlich genau. Kein Wort darüber, wo eine Schranke unten bleiben musste.

Jeder neue Abschnitt markiert eine Stelle, an der schon jemand durchgefahren ist

Die Fassungen danach hat niemand entworfen. Sie sind gewachsen, Schicht für Schicht. the current state: kam dazu, nachdem ich einen Nachmittag damit verbracht hatte, etwas zu reparieren, das längst repariert war. what needs to be done: und what I want you to do: gingen auseinander, als mir auffiel, dass ich Diagnose und Reparatur vermischt hatte — und von beidem einen Kompromiss zurückbekam. Jede Überschrift ist ein kleines Denkmal für einen bestimmten Nachmittag.

In dieselbe Zeit fällt der Plan Mode. Das Modell sagt an, was es vorhat, und ich lese das, bevor irgendetwas durchgelassen wird. Die meisten Missverständnisse kommen dort ans Licht, wo sie noch einen Absatz kosten und keinen Diff.

Und dann boundaries:. Dieser eine Abschnitt hat mehr verändert als die anderen vier zusammen.

the current state:
The dashboard endpoint loads the user plus every attached entity in one
call. Response times went from ~300ms to ~2.5s over two releases.

the context:
Spring Boot, JPA, Postgres. The Redis cache in the user service is still
wired up but nothing reads from it anymore.

what needs to be done:
- Find what causes the regression in the dashboard endpoint
- Show me the evidence before you change anything

what I want you to do:
- Propose a fix, then implement the one I approve
- Measure before and after with the same request

boundaries:
- Do not change the API contract. The response shape stays as it is.
- Do not touch the Redis cache in this task.
- Do not add a dependency.
- No new database migration.
- If the cause is outside the user service, stop and tell me.

Dass das funktioniert, ist nicht die Überraschung. Die Überraschung ist, dass dieselben Sätze an anderer Stelle wirkungslos bleiben. Ein Kollege hat es auf den Punkt gebracht: „Aber ich hab es doch in CLAUDE.md aufgeschrieben, und die KI hält sich trotzdem nicht daran.“ Hatte er auch. Es stand da, unmissverständlich, in einer Datei, die das Modell tatsächlich liest. CLAUDE.md ist der laminierte Aushang neben der Tür — korrekt, dauerhaft und ab der zweiten Woche von der Wand dahinter nicht mehr zu unterscheiden.

Ein boundaries:-Block ist nichts davon. Er ist kurz, er ist negativ, er meint diese eine Aufgabe, und er steht im selben Atemzug wie der Auftrag. Er ist nicht besser geschrieben. Er ist das Erste in meinem Prompt, das die Arbeit nicht mehr beschreibt, sondern entscheidet.

Ein Schild sagt dem Modell, was Ihnen lieber wäre. Eine Schranke nimmt ihm die Wahl. Was am Ende gehalten hat, war jedes Mal eine Schranke.

Struktur war das Zweite, was gehalten hat

Irgendwann habe ich Claude gefragt, wie ein guter System-Prompt eigentlich aufgebaut ist. Die nützlichste Frage, die ich in dem Jahr gestellt habe. Zurück kamen fünf Tags: <role>, <context>, <explanation>, <instructions>, <boundaries>.

Nicht die Tags sind der Punkt, Überschriften täten es auch. Der Punkt ist die Trennung. <role> und <boundaries> ändern sich von Aufgabe zu Aufgabe kaum: dieselbe Rolle, dieselben Dinge, die sie nie tun darf. <context>, <explanation> und <instructions> sind jedes Mal neu. Sobald die stabile Hälfte sichtbar abgetrennt war, habe ich aufgehört, sie aus Versehen umzuschreiben. Und sie hörte auf zu driften.

Es war auch das erste Mal, dass ich das alles bewusst hingeschrieben habe: eine Rolle, die benannt ist statt vorausgesetzt, und Grenzen, die von außen greifen. Die Arbeit bekommt ihre Form von dem, was zu ist, nicht von dem, was in der Mitte liegt.

Dann bekamen die Instructions Phasen, in fester Reihenfolge, jede mit einer Ansage, was sie liefern muss.

<phase-2>
  Implement the approved brief.
  → Delegate to `frontend-engineer`: "Implement this technical
    overview." Pass: the approved overview, the acceptance criteria,
    and the target surfaces.
  <expected-output>
    The diff, plus a change summary naming every file touched.
  </expected-output>
</phase-2>

<phase-3>
  Delegate a second, independent `frontend-engineer` instance a REVIEW
  task, not a build task. Hand it the diff and the house rules.
  Verdict: {clean: true|false, findings: [...]}
  Proceed only on {clean: true}; otherwise loop back to phase-2.

  🛑 HUMAN GATE — STOP. Wait for approval before anything ships.
</phase-3>

„Mach das gut“ ist ein Schild. „The diff, plus a change summary naming every file touched“ ist etwas, woran sich das Ergebnis messen lässt — von mir und von dem, was als Nächstes läuft. Die letzten beiden Zeilen von Phase 3 sind die einzigen in der ganzen Datei, die überhaupt kein Ratschlag mehr sind: ein Urteil, an dem die Pipeline mechanisch verzweigt, und eine Schranke, die unten bleibt, bis jemand sie freigibt.

Bei jedem Übergang ein frischer Kopf

Sobald die Rollen aufgeschrieben waren, wurden Agenten daraus. Eine Rolle besteht größtenteils aus einer Identität, die in diesem System verankert ist und nicht im Allgemeinen. „You are a senior engineer“ bringt allgemeine Kompetenz zurück. Steht da stattdessen, dass Seniorität hier Vertrautheit mit den Konventionen dieser Codebasis heißt, und liegen die Konventionen bei, dann kommt Code zurück, der aussieht wie der Code daneben. Der Rest ist die Zuständigkeit: was die Rolle entscheidet, was sie stattdessen weiterreichen muss, und woran ihre Arbeit gemessen wird, wenn sie zurückkommt.

Registriert und aufrufbar lesen sich die Agenten in der Summe wie ein Entwicklungsteam. Ein Orchestrator, der den Lauf verantwortet. Ein Validator, der für den Product Owner spricht. Frontend-, Backend- und Data-Engineers, dazu ein QA-Engineer. Drumherum ein Business Analyst, jemand für den Testplan, ein Software-Architekt — und ein Agent, dessen ganze Aufgabe darin besteht, den Vorgaben zu widersprechen, die man ihm gerade gegeben hat.

Ein technischer Umstand bestimmt alles Weitere. Jeder Agent startet mit einem frischen Kontextfenster, und was er ausgibt, fließt genau eine Ebene nach oben. Der Subagent hat das Gespräch nie gesehen. Nur sein Aufrufer sieht, was zurückkommt.

Damit wandert das Handwerk aus der Formulierung ab. Es besteht heute darin, zu entscheiden, was ein frischer Kopf braucht, und genau das zu übergeben. Mehr bekommt er nicht.

Und deshalb steht die Zuständigkeit zweimal da. In der Rollendatei des Validators steht im Klartext: Er prüft, er implementiert nicht. Das ist ein Schild. In seinem tools:-Feld steht kein Edit. Das ist eine Schranke ohne Knopf. Er verzichtet nicht aufs Schreiben — er kann es nicht.

Die Prompts für diese Pipelines wurden dann so lang, dass ihr Schreiben selbst zur Arbeit wurde. Also habe ich auch das delegiert. /build-prompt nimmt eine kurze Eingabe: die Form der Pipeline, den Kontext, die Erläuterung. Heraus kommt der fertige Prompt im Hausformat. Im ersten Durchgang holt es außerdem die Implementierungsdetails, die ich nicht habe, und schreibt sie gleich mit hinein. Zwei weitere stammen aus demselben Nachmittag voller Tipparbeit: /create-agents, das einen frischen Satz Rollen in der Codebasis verankert, auf die Sie es loslassen, und /walkthrough, das mich Schritt für Schritt durch eine Implementierung führt, bis ich sagen kann, was da gebaut wurde.

Der Gewinn — und ich sage gleich dazu, was er ist: meine eigene Erinnerung an meine eigene Arbeit, keine Messung. Vor den Pipelines war etwa 70 % dessen, was zurückkam, richtig. Der Rest waren falsche Annahmen, Code, der ein zweites Mal neben schon vorhandenem entstand, und Details, die schlicht erfunden waren. Mit den Pipelines würde ich es über 80 % ansetzen. Meine Erklärung ist das frische Fenster: Die QA- und Validator-Agenten haben die lange Sitzung nicht miterlebt, in der die Arbeit entstand. Sie erben deren Ermüdung also nicht — und mehrere von ihnen existieren aus keinem anderen Grund, als zu prüfen.

Der Preis ist Zeit. Eine mittelgroße Implementierung hat mich früher dreißig bis sechzig Minuten gekostet, von vorne bis hinten. Eine vollständige Pipeline mit allen Reviews und allen Freigaben kann den größten Teil eines Tages dauern, manchmal mehr. Das ist eine echte Rechnung, und für eine umbenannte Schaltfläche würde ich sie nicht bezahlen. Sie kauft Korrektheit mit Zeit, und Zeit ist nur dann die günstigere Währung, wenn Falschliegen teuer wird — wenn die Arbeit Geld berührt oder personenbezogene Daten oder eine Entscheidung, die Sie später begründen müssen.

Und das Schlichte gehört genauso dazu: Diese Skills und Werkzeuge zu bauen, hat mir echte Freude gemacht, und die Arbeit ist dadurch effizienter geworden — effizienter allerdings in dem, was nicht noch einmal zurückkommt, nicht in Stunden.

Wo Sie anfangen

Nicht die Tags, nicht die Agenten, keine Pipeline. Schreiben Sie in den nächsten Prompt einen boundaries:-Block, und hinein kommt, worüber Sie sich geärgert hätten, wenn es jemand verändert hätte: der Vertrag, den ein anderes Team liest; die Datei, die aus Gründen fragil ist, die nie jemand aufgeschrieben hat; die Liste der Dependencies; die Migration, für die Sie noch nicht bereit sind. Fünf Zeilen. Die meisten fangen mit „Nicht“ an. Das ist die billigste Änderung in diesem ganzen Text, und sie hat mehr zurückgegeben als alle anderen.

Nichts davon bleibt im Prompt, und das war der Teil, den ich nicht erwartet hatte. Eine Organisation macht dieselbe Ersetzung mit sich selbst, ein Vorfall nach dem anderen, und nennt das Ergebnis Governance. Man kann das auch vorher tun, an einem Nachmittag, an dem noch nichts passiert ist.

Ein Schild wird geschrieben. Eine Schranke wird gesetzt. Nur eines von beiden hält, wenn niemand hinsieht.