Startseite / Artikel

Gebundene Anfragen: Verhinderung, dass KI-Hilfsprogramme einen parallelen Stack erfinden

Warum vage Funktionsanfragen dazu führen, dass Code-Assistenten doppelte Bibliotheken und Wrapper hinzufügen, und wie ein begrenzter Prompt mit Pfaden, Invarianten und klaren Grenzen das Problem löst.

Verlag: REACTAPP.TOP6 Min. Lesezeit1323 Wörter

Quellen: AI Doesn’t Need Better Prompts. It Needs Boundaries.

Fragen Sie einen Programmier-Assistenten, „eine Benutzer-Einstellungsseite zu erstellen“, und Sie erhalten in der Regel etwas, das kompiliert werden kann, angezeigt wird und fertig aussehen lässt. Bei genauerer Betrachtung weist das Ergebnis oft einen eigenen State-Store, eigene Fetch-Hilfsfunktionen sowie eine Validierungsbibliothek auf, die in Ihrem Repository noch nie verwendet wurde. Nichts bricht – genau deshalb entgeht das Problem der Überprüfung. Dieser Artikel erklärt, warum vage Anfragen auf diese Weise scheitern, warum das Hinzufügen von Adjektiven nicht hilft und wie man präzise Anfragen formuliert, sowie einen wiederverwendbaren Überprüfungsliste, der den generierten Code in Ihrer bestehenden Architektur hält.

Wie eine vage Anfrage sanft scheitert

Stellen Sie sich ein Team vor, das an einer Client-Admin-App arbeitet, die mit React und TypeScript entwickelt wurde. Die Codebasis enthält bereits Form-Primitiven, einen gemeinsamen API-Client sowie einen Benachrichtigungs-Hook. Jemand bittet den Assistenten in einem kurzen Satz um eine Einstellungsseite. Das Ergebnis umfasst Tabellen, Formulare, Toast-Nachrichten, Lade-Skelette sowie einen kleinen State-Store. Im Hintergrund widerspricht diese Änderung leise der bestehenden Codebasis:

  • Der Formzustand wird von einer Bibliothek verwaltet, die das Projekt nicht verwendet.
  • Neben dem gemeinsamen API-Client befinden sich neue fetch-Wrappers.
  • Toasts werden direkt implementiert, anstatt über den Benachrichtigungs-Hook des Projekts zu laufen.
  • Die Validierungs-Schemata ignorieren die bereits in types/ definierten Strukturen.
  • Ein clientseitiger „Settings-Store“ enthält drei Felder, die eigentlich auf dem Server liegen sollten.
  • Die Lade-Skelette passen nicht zum Rest des Dashboards.

Nichts davon führt zu einem Fehler, und es könnte einer schnellen Überprüfung standhalten – es sei denn, jemand öffnet package.json. Das ist die Gefahr: Vage Anfragen verlaufen sanft. Sie führen zu einer zweiten Methode, etwas zu erledigen, was das Team bereits gelöst hat, und jeder zukünftige Wartungstechniker erbt beides. Der Assistent ist gut im Umgang mit dem Code, den er sehen kann; die Dateien, die er nie geöffnet hat, entscheiden darüber, ob eine Funktion tatsächlich in Ihrer Anwendung enthalten sein sollte.

Warum eine längere Anfrage keine Lösung ist

Der übliche Rat lautet, präziser zu sein. Ein natürlicher zweiter Versuch besteht darin, nach einer „verfeinerten, für die Produktion bereiten“ Einstellungsseite zu fragen, die über „eine klare Benutzeroberfläche, guten TypeScript-Code sowie solide Fehlerbehandlung“ verfügt.

Das erzeugt dieselbe parallele Architektur, nur mit größerer Sicherheit. Die Worte beschreiben den Geschmack, und der Geschmack lässt das Modell völlig frei, Strukturen zu erfinden. Was gefehlt hat, war nie Eloquenz – es fehlten Grenzen: klare Angaben darüber, was das Modell verwenden darf, was es nicht hinzufügen darf und was als erledigt gilt.

Die begrenzte Version schreiben

Der unten stehende begrenzte Prompt fordert dieselben Funktionen an, liest sich aber wie eine Stellenbeschreibung. Er nennt die genauen Komponenten, den Hook, den API-Client sowie die zu wiederverwendenden Schema-Dateien, listet das Verhalten bei Tabulation und Einreichung auf, definiert die Tests und endet mit klaren Verbotsregeln.

Build a user settings page in React and TypeScript.
Use ONLY these existing pieces:
- `src/components/FormField.tsx`
- `src/components/Button.tsx`
- `src/hooks/useNotify.ts`
- `src/api/client.ts` (no new fetch wrappers)
- validation schemas from `src/types/userSettings.ts`
Behavior:
- Tabs: Profile, Notifications, Security
- Preserve unsaved edits when switching tabs
- Show server field errors beside the matching inputs
- Disable submit while in flight
- Ignore duplicate submits
Tests:
- loading, success, server error, duplicate click
- empty required fields
Do NOT:
- add a state-management library
- add a toast library
- create a new API client
- invent types that duplicate `src/types/userSettings.ts`

Das ist weniger ein ansprechender Prompt als vielmehr eine Architekturanweisung, der das Modell folgen muss. Im Vergleich zur einzeiligen Formulierung kommuniziert es sieben Aspekte, die zuvor dem Zufall überlassen wurden:

  1. Welche bestehenden Komponenten wiederverwendet werden sollen.
  • Wo sich die Quelle der Wahrheit für die Validierung befindet.
  • Wechselwirkungsregeln, wie beispielsweise das Beibehalten ungespeicherter Änderungen über verschiedene Tabellen hinweg.
  • Wo Fehler angezeigt werden sollten.
  • Konkurrenzverhalten: Der laufende Zustand sowie doppelte Einreichungen.
  • Tests, die definieren, was „erledigt“ bedeutet.
  • Harte Beschränkungen bezüglich neuer Abhängigkeiten.
  • Mit diesen Einschränkungen wird der resultierende Unterschiedsbericht angenehm langweilig. Er verwendet denselben FormField, denselben useNotify sowie denselben api/client. Die Tabellen behalten ihren ungespeicherten Zustand bei, ohne dass ein neuer Speicher benötigt wird, und doppelte Einreichungen werden durch einen deaktivierten Button sowie einen Test geregelt, anstatt mit einem Kommentar wie „das später erledigen“. In etablierten Codebasen finden sich bereits Muster; die Aufgabe der Anleitung besteht darin, diese so deutlich hervorzuheben, dass das Modell sie nicht übersehen kann.

    Dies erklärt auch, warum erfahrene Entwickler in der Regel bessere Ergebnisse mit Assistenten erzielen. Ihr Vorteil liegt nicht im Formulieren, sondern darin, im Voraus zu wissen, welche Details von Bedeutung sind. Entscheidend ist es, die Architektur zu kommunizieren, nicht einen Prompt zu verziern.

    Ein schneller Test auf Begrenztheit

    Falls Ihr Prompt auch in jedem Repository der Welt sinnvoll wäre, ist er noch nicht begrenzt. Ein guter Prompt sollte außerhalb Ihres eigenen Quellbaums etwas nutzlos sein, da er auf Ihre Pfade, Typen und Konventionen verweist.

    Eine wiederverwendbare Vorab-Überprülliste

    Das Halten eines Templates über jeder Funktionsanfrage macht den konsequenten Anwendung dieses Stils zur Gewohnheit. Das untenstehende Template gruppiert die Fragen nach Kontext, Invarianten, Verhalten, Einschränkungen sowie einer Definition des Abschlusszustands. Der Abschnitt zu den Invarianten wird am häufigsten übersprungen: Die Entscheidung darüber, ob Daten auf dem Server, in der URL oder im lokalen UI-Zustand gespeichert werden sollen, verhindert das Problem „Daten für drei Felder speichern“ bereits im Vorfeld.

    CONTEXT
    - Stack: React + TypeScript
    - Relevant paths: ...
    - Patterns to copy: ...
    
    INVARIANTS
    - Where does data live (server / URL / local UI state)?
    - What must survive refresh?
    - What is the source of truth for types/validation?
    
    BEHAVIOR
    - Happy path
    - Empty / invalid input
    - Server errors (field-level + form-level)
    - Slow network / double submit
    - Permission failure
    
    CONSTRAINTS
    - Do not add: ...
    - Do not invent parallel: API client / store / toast / form lib
    - Prefer editing: [files]
    
    DONE
    - Tests for: ...
    - Manual checks: ...
    

    Verwenden Sie das Template als Bereitschaftsprüfung. Wenn Sie die Einschränkungen sowie die relevanten Pfade nicht ausfüllen können, sind Sie noch nicht bereit, Code zu generieren – Sie befinden sich weiterhin in der Entwurfsphase. Das Erstellen von Code, solange der Entwurf noch offen ist, führt genau dazu, dass eine zweite Architektur allmählich entsteht. Stabile Teile dieser Checkliste können in einer Projektanleitungsdatei gespeichert werden; siehe unseren Leitfaden zur Erstellung einer effektiven CLAUDE.md-Datei.

    Was noch einer menschlichen Überprüfung bedarf

    Begrenzte Anweisungen beseitigen den größten Teil des „Rauschens“, ersetzen aber das Urteilsvermögen nicht. Bei der Überprüfung des Unterschieds sollten Sie weiterhin auf Folgendes achten:

    • Ein neues Paket, das noch von niemandem genehmigt wurde.
    • Eine weitere Möglichkeit, die API aufzurufen.
    • Typen, die sich vom Serververtrag entfernen.
    • Klientenseitiger Zustand für Daten, die eigentlich beim Server liegen sollten.
    • Tests, die nichts außerhalb des von dem Modell angenommenen „glücklichen Pfades“ prüfen.

    Die Erstellung der Anweisung ist der einfache Teil; zu wissen, welche Grenzen in dieser Codebasis wichtig sind, ist der schwierige Teil – und dieses Wissen liegt beim Team.

    Die kleinste Änderung, die heute vorgenommen werden kann

    Falls eine vollständige Checkliste zu umfangreich erscheint, fügen Sie einfach drei Zeilen zu Ihrer nächsten Funktionsanfrage hinzu: welche Pfade verwendet werden sollen, welche Bibliotheken nicht hinzugefügt werden dürfen und wie „erledigt“ aussehen soll, einschließlich mindestens eines Fehlerfalls.

    Use only: [paths]
    Do not add: [libs]
    Done when: [2–3 behaviors + one failure path]
    

    Zusammenfassung

    • Vage Anweisungen führen selten zu Fehlern; sie erzeugen doppelte Infrastrukturen, die wie abgeschlossen aussehen, Ihnen aber später Kosten verursachen.
    • Mehr Adjektive ändern den Ton der Ausgabe, nicht ihre Struktur. Einschränkungen hingegen verändern die Struktur.
    • Eine gut definierte Anweisung gibt Namen für wiederverwendete Dateien vor, legt die Quelle der Wahrheit für Daten und Typen fest, beschreibt das Verhalten bei Randfällen, die Tests sowie die nicht verwendbaren Abhängigkeiten.
    • Falls das Modell etwas außerhalb der vorgegebenen Grenzen erfindet, betrachten Sie dies als fehlende Grenze: Korrigieren Sie die Anweisung und erzeugen Sie neu, anstatt nur den Wortlaut zu überarbeiten.