12k
All articles

Die Grundlagen, die Sie beim Programmieren mit Agenten weiterhin brauchen

Prüfen Sie KI-generierten Code sicher. Verstehen Sie die Web-Grundlagen zu HTTP, Browserverhalten, Zustand, Sicherheit, Debugging, Git und Architektur.

OpenReplay Team
OpenReplay Team
Die Grundlagen, die Sie beim Programmieren mit Agenten weiterhin brauchen

Sie brauchen genug Programmiergrundlagen, um von Agenten geschriebenen Code beurteilen zu können, nicht um ihn selbst zu tippen. Denn Code, der läuft, kann trotzdem schlecht entworfen, unsicher oder langsam sein.

Die typische Situation: Der Agent meldet, dass er fertig ist, die Seite lädt, die Tests laufen durch, und trotzdem könnten Sie den Diff nicht erklären, wenn ein Reviewer danach fragt. Dieser Zweifel ist berechtigt. Meist deutet er auf eine konkrete Wissenslücke hin.

Dieser Artikel behandelt weder Prompting noch die Einrichtung von Tools. Dazu finden Sie mehr in how to get the best results from AI coding tools und tips and tricks for AI coding. Stattdessen stellt er sieben Grundlagen der Webentwicklung vor und kombiniert jede davon mit einem realistischen Agentenfehler und dem Wissen, das Sie brauchen, um ihn zu erkennen.

Die wichtigsten Erkenntnisse

  • Das fetch() des Browsers schlägt nur fehl (rejected), wenn die Anfrage selbst scheitert, etwa bei einem Netzwerkfehler. Code, der response.ok nie prüft, behandelt daher einen 404 oder 500 als Erfolg.
  • Jeder Wert, der in Frontend-JavaScript gebündelt wird, ist öffentlich, einschließlich Umgebungsvariablen, die das Framework dem Client zugänglich macht.
  • Einen Button auszublenden ist keine Autorisierung: Der Server muss die Berechtigungen bei jeder Anfrage prüfen.
  • Mit git add -p übernehmen Sie die Änderungen eines Agenten Hunk für Hunk, und git revert macht einen Commit rückgängig, ohne die Historie umzuschreiben.
GrundlageTypischer AgentenfehlerWoran man ihn erkennt
HTTP200 mit Fehlermeldung im BodySemantik der Statuscodes
BrowserListener ohne CleanupLebenszyklus von Effects
StateServerdaten in einen Store kopiertSingle Source of Truth
SicherheitSecret im Client-BundleWissen, was an den Browser ausgeliefert wird
DebuggingVerschluckter FehlerStack Traces, DevTools
GitAlles auf einmal übernehmenHunk-weises Staging, Revert
ArchitekturNeue Abhängigkeit für einen EinzeilerPlattform-APIs

Warum spielen HTTP-Statuscodes und Caching weiterhin eine Rolle?

Über Statuscodes und Caching-Header erfahren Clients, Proxys und Monitoring-Tools, was mit einer Anfrage passiert ist. Ein Endpunkt, der 200 OK mit einer Fehlermeldung im Body zurückgibt, teilt jedem Client, jedem Cache und jedem Monitoring-Tool mit, dass die Anfrage erfolgreich war. RFC 9110 definiert 2xx als Erfolg, sodass Error-Tracking und Retries nicht ausgelöst werden. Halten Sie beim Review von Handlern die HTTP-Statuscode-Referenz griffbereit.

Auf der Client-Seite lauert die passende Falle. fetch() schlägt bei HTTP-Fehlerstatus nicht fehl, sondern nur, wenn die Anfrage selbst scheitert. Sie müssen Response.ok also selbst prüfen:

const res = await fetch('/api/save', { method: 'POST', body });
if (!res.ok) throw new Error(`Save failed: ${res.status}`);

Agenten neigen außerdem dazu, Daten zu pollen, die sich selten ändern. Für Konfigurationen oder Referenzlisten beseitigen Cache-Control (definiert in RFC 9111) und Revalidierung per ETag (mit der Antwort 304 Not Modified, definiert in RFC 9110) die überflüssigen Anfragen. Daten, die sich tatsächlich in Echtzeit ändern, sind ein eigenes Problem.

Wie rendert der Browser und wie verarbeitet er Events?

Event-Listener und DOM-Schreibzugriffe haben Lebenszyklen, und der Browser bestraft Sie, wenn Sie diese ignorieren. Ein häufiger Agentenfehler ist ein Listener, der in einem Effect ohne Cleanup und ohne Dependency-Array registriert wird. React führt diesen Effect nach jedem Render aus, sodass jeder Render einen weiteren resize-Listener hinzufügt. Die Korrektur gibt eine Cleanup-Funktion zurück und deklariert die Abhängigkeiten:

useEffect(() => {
  window.addEventListener('resize', onResize);
  return () => window.removeEventListener('resize', onResize);
}, [onResize]);

Die zurückgegebene Cleanup-Funktion läuft vor dem nächsten Durchlauf des Effects und beim Unmount. Das zweite Browser-Muster, auf das Sie achten sollten, ist Layout Thrashing: eine Schleife, die immer wieder einen Style schreibt und anschließend offsetHeight liest. Jeder Lesezugriff nach einem Schreibzugriff kann ein synchrones Layout erzwingen. Die Lösung: zuerst alle Lesezugriffe, danach alle Schreibzugriffe.

Wo sollte State liegen und wie sollten Daten fließen?

Jedes Datum sollte genau einen Eigentümer haben. Wer Serverdaten in einen clientseitigen Store kopiert, schafft eine zweite Source of Truth, und die beiden Kopien laufen auseinander, sobald sich eine ändert, ohne dass die andere mitzieht. Eine typische Agentenvariante lädt eine Liste, legt sie in useState oder einem Zustand-Store ab und bearbeitet sie lokal, während ein Refetch eine andere Kopie aktualisiert.

Reacts Leitfaden zur Strukturierung von State rät davon ab, State zu duplizieren. Bei Serverdaten übernimmt eine Cache-Schicht wie TanStack Query oder SWR die Eigentümerschaft und kümmert sich um die Invalidierung. Alles, was sich aus vorhandenem State berechnen lässt, sollten Sie während des Renderns ableiten.

Sicherheitsgrundlagen: Auth, XSS, Secrets und nicht vertrauenswürdige Eingaben

Frontend-Sicherheit setzt voraus, dass Sie wissen, welcher Code im Browser und welcher auf dem Server läuft. Jeder Wert, der in Frontend-JavaScript gebündelt wird, ist öffentlich. In Next.js sind Umgebungsvariablen standardmäßig nur serverseitig verfügbar. Das Präfix NEXT_PUBLIC_ fügt den Wert einer Variable zur Build-Zeit direkt in das Client-Bundle ein. Ein Agent, der einem API-Key dieses Präfix voranstellt, hat den Key also veröffentlicht.

Einen Button in der UI auszublenden ist keine Autorisierung. Jeder kann die API direkt aufrufen, daher muss der Server die Berechtigungen bei jeder Anfrage prüfen. Dieser Fehler fällt unter OWASP Top 10:2025, A01 Broken Access Control.

Wird Benutzereingabe innerHTML zugewiesen, parst der Browser sie als Markup, einschließlich Attributen wie onerror, die JavaScript ausführen. textContent fügt dieselbe Eingabe als reinen Text ein. JSX escapet interpolierte Strings standardmäßig, und dangerouslySetInnerHTML schaltet diesen Schutz ab. Alles Weitere finden Sie im OWASP XSS Prevention Cheat Sheet.

Wie debuggt man Code, den man nicht selbst geschrieben hat?

Debugging heißt, die Ursache eines Bugs zu finden, nicht das Symptom verschwinden zu lassen. Agenten „beheben“ einen Fehler oft, indem sie ihn in ein try/catch packen, das ihn verschluckt, oder indem sie Optional Chaining einfügen, das einen undefined-Wert verdeckt, statt zu verfolgen, woher er stammt. Der Fehler verschwindet aus der Konsole, aber der Bug bleibt.

Bevor Sie einen Fix übernehmen, lesen Sie den Stack Trace, reproduzieren Sie den Bug und prüfen Sie im Network-Panel der Chrome DevTools, was Anfrage und Antwort tatsächlich enthielten. Manche Bugs treten nur bei echten Nutzern auf. Session Replay zeigt, was von Agenten geschriebener Code in Produktion bei diesen Nutzern tatsächlich tut, etwa eine Retry-Schleife, die einen Endpunkt mit Anfragen bombardiert, oder ein Formular, das stillschweigend fehlschlägt. Genau dort werden Lücken in diesen Grundlagen oft sichtbar.

Git gut genug beherrschen, um die Änderungen eines Agenten zu prüfen und rückgängig zu machen

Mit Git übernehmen Sie einen Teil der Arbeit eines Agenten und verwerfen den Rest. Agenten neigen zu weitreichenden Änderungen, und wer diese in einem Rutsch übernimmt, übersieht Änderungen, die nichts mit der Aufgabe zu tun haben. Vier Befehle decken das Meiste ab:

git diff                 # read every change
git add -p               # stage hunk by hunk
git restore -p src/x.ts  # discard unwanted hunks
git revert <commit>      # undo a committed change

git add -p fragt Sie vor dem Staging zu jedem Hunk, und git restore -p verwirft Hunks im Working Tree einzeln. git revert erstellt einen neuen Commit, der einen früheren rückgängig macht. Das ist auf gemeinsam genutzten Branches sicher, während reset die Historie umschreibt.

Genug Architekturwissen, um eine überdimensionierte Lösung zu erkennen

Gute Architektur löst das heutige Problem mit dem, was das Projekt bereits mitbringt. Agenten greifen für einmalige Aufgaben oft zu einer neuen Abhängigkeit oder zu einer Factory- bzw. Strategy-Schicht. Eine Datumsbibliothek zu installieren, um ein einziges Datum zu formatieren, ist ein typisches Beispiel, denn Intl.DateTimeFormat erledigt das nativ. Wenn ein Diff Dateien, Pakete oder Abstraktionen hinzufügt, fragen Sie sich, ob der vorhandene Code die Aufgabe mit weniger Dateien lösen könnte. Falls ja, lehnen Sie die Änderung ab oder fordern Sie eine kleinere an.

Gewohnheiten, mit denen Sie die Kontrolle behalten

  • Lassen Sie sich die Entscheidungen des Agenten erklären. Wenn Sie die Erklärung nicht beurteilen können, haben Sie die Grundlage gefunden, die Sie als Nächstes lernen sollten.
  • Lesen Sie den Diff, bevor Sie ihn übernehmen. Prüfen Sie jeden Hunk, jedes Mal.
  • Nehmen Sie kleine Änderungen von Hand vor. Einen Fix selbst zu tippen hält Ihr Verständnis aktuell.

Tests verwandeln Ihr Urteilsvermögen in Prüfungen, die bei jeder Änderung laufen.

Fazit

Agenten können den Code schreiben, aber Sie sind dafür verantwortlich, was er tut. Lernen Sie HTTP-Semantik, das Rendering-Modell des Browsers, die Eigentümerschaft von State, Sicherheitsgrenzen, Debugging, Git und die Disziplin, Dinge klein zu halten. Dann können Sie einen schlechten Diff ablehnen und begründen, warum. Wenn Ihnen ein Agent das nächste Mal eine Änderung übergibt, lesen Sie zuerst git diff und suchen Sie sich eine Entscheidung heraus, die Sie noch nicht erklären können.

FAQs

Hat axios dasselbe Problem mit HTTP-Fehlern wie fetch?

Nein. Standardmäßig rejected axios das Promise bei jedem Antwortstatus außerhalb des Bereichs 200 bis 299, sodass ein 404 oder 500 im catch-Block landet. Gesteuert wird das über die Option validateStatus, die sich überschreiben lässt. Eine API, die 200 mit einer Fehlermeldung im Body zurückgibt, wird jedoch sowohl in axios als auch in fetch erfolgreich aufgelöst. Der Server muss also korrekte Statuscodes senden.

Ist es sicher, API-Keys in Vite-Umgebungsvariablen abzulegen?

Nur wenn die Variable kein VITE_-Präfix hat. Vite stellt Variablen mit dem Präfix VITE_ dem Client-Code über import.meta.env zur Verfügung und ersetzt sie zur Build-Zeit statisch, sodass ihre Werte im Client-Bundle landen. Variablen ohne Präfix sind für Client-Code nicht zugänglich. Wie NEXT_PUBLIC_ in Next.js markiert das Präfix einen Wert zur Veröffentlichung und schützt ihn nicht. Secrets müssen daher auf einem Server bleiben.

Wie rendere ich von Nutzern bereitgestelltes HTML sicher, wenn textContent nicht ausreicht?

Bereinigen Sie das HTML, bevor Sie es einfügen. OWASP empfiehlt DOMPurify: Übergeben Sie den String an DOMPurify.sanitize und verwenden Sie das Ergebnis mit innerHTML oder dangerouslySetInnerHTML. Verändern Sie die bereinigte Ausgabe danach nicht mehr, da Änderungen gefährliches Markup wieder einschleusen können. Halten Sie die Sanitizer-Bibliothek aktuell, da regelmäßig neue Umgehungen entdeckt werden. Typische Anwendungsfälle sind Rich-Text-Editoren und von Nutzern verfasstes Markdown.

Warum läuft mein React-Effect in der Entwicklung zweimal?

In der Entwicklung mountet der React Strict Mode Komponenten ein zusätzliches Mal, um Effects ohne Cleanup aufzudecken. In Produktion passiert das nicht. Wenn der zweite Durchlauf doppelte Listener, Anfragen oder Subscriptions erzeugt, braucht der Effect eine Cleanup-Funktion, die sein Setup rückgängig macht. Den Strict Mode zu entfernen oder den zweiten Durchlauf mit einem Ref-Guard zu überspringen, verdeckt den Bug nur.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.