Code-Agenten sind selbstbewusst, schnell und architektonisch ahnungslos bezüglich Ihrer Codebasis, bis Sie ihnen etwas anderes sagen. Geben Sie Claude Code oder Codex ein vages Ticket, und es wird fröhlich Code schreiben, der kompiliert, einen schnellen Test besteht und stillschweigend die Grenze zwischen Ihrer Domänenschicht und Ihrer HTTP-Schicht verletzt. Der Agent hat Ihre Designdokumente nicht gelesen. Er las die Dateien, die er sehen konnte, führte einen Mustervergleich durch und riet. Eine `DESIGN.md`-Datei behebt das Ratenproblem, indem sie Ihre architektonische Absicht an dem einzigen Ort festhält, den ein Agent immer ansieht: im Repository selbst.
TL;DR
`DESIGN.md` ist eine Repository-Datei, die einer Community-Konvention folgt und die architektonische Absicht, Einschränkungen und Designentscheidungen einer Codebasis in einfachem Markdown aufzeichnet, damit Code-Agenten (Claude Code, Codex, Cursor) Code generieren, der zum System passt, anstatt dagegen anzukämpfen. Sie beantwortet „warum ist der Code so aufgebaut“, während `AGENTS.md` beantwortet „wie baue und teste ich.“
Einleitung
Hier ist der Fehlermodus, auf den jedes Team, das Code-Agenten einsetzt, innerhalb einer Woche stößt. Sie bitten einen Agenten, einen Rückerstattungs-Endpunkt zu einem Zahlungsdienst hinzuzufügen. Er gibt einen funktionierenden Handler zurück, der die Datenbank direkt vom Controller aus aufruft, den Gateway-Fehler schluckt und einen neuen Geldtyp erfindet, weil er nicht bemerkt hat, dass Sie bereits einen hatten. Der Diff ist sauber. Die Tests bestehen. Es ist jedoch auch auf drei Arten falsch, die nur ein Rezensent, der die Architektur kennt, erkennen kann. Der Agent ist nicht schlecht im Programmieren; er ist blind für Entscheidungen, die in Ihrem Kopf, auf einer Notion-Seite oder in einem Slack-Thread von vor acht Monaten existieren.
`DESIGN.md` ist die Antwort, auf die sich eine wachsende Zahl von Teams geeinigt hat. Es ist eine einzelne Markdown-Datei, die im Repository-Stammverzeichnis gespeichert ist und jedem Agenten die tragenden Fakten über Ihr System mitteilt: die Schichtregeln, die Invarianten, die niemals verletzt werden dürfen, die Muster, die Sie absichtlich gewählt haben, und die, die Sie abgelehnt haben. Es ist keine Herstellerspezifikation und es gibt kein Komitee, das es besitzt; es ist eine Konvention, so wie `ARCHITECTURE.md` und `CONTRIBUTING.md` Konventionen sind. Aber es passt natürlich zu den werkzeugspezifischen Anweisungsdateien, die Agenten bereits lesen, und für API- und Backend-Arbeiten ist es eines der wirksamsten Dokumente, die Sie schreiben können.
Was DESIGN.md tatsächlich ist
`DESIGN.md` ist eine Klartextaufzeichnung von *warum Ihr Code so aussieht, wie er aussieht*. Nicht was er tut (das ist die README), nicht wie man ihn ausführt (das ist `AGENTS.md`), sondern die Begründung, die ein erfahrener Ingenieur einem neuen Mitarbeiter am ersten Tag erklären würde, bevor er ihn an wichtige Dinge heranlässt.
Denken Sie an die Gespräche, die in keiner Datei stehen. „Wir rufen das Zahlungs-Gateway nicht aus dem Request-Thread auf; alles läuft über die Outbox-Tabelle, weil das Gateway unter Last eine Zeitüberschreitung hat.“ „Geld ist immer eine ganzzahlige Anzahl von Untereinheiten; wir haben Gleitkommazahlen nach dem Rundungsvorfall verboten.“ „Das `Account`-Aggregat ist für Saldenmutationen zuständig; nichts anderes schreibt in das Ledger.“ Das sind Designentscheidungen. Sie sind für einen Agenten, der Quellcode liest, unsichtbar, weil die Quelle das *Ergebnis* der Entscheidung zeigt, nicht die Entscheidung oder ihre Begründung. Ein Agent kann sehen, dass `Account.debit()` existiert. Er kann nicht sehen, dass Sie es absichtlich zum einzigen Schreibpfad gemacht haben, also wird er fröhlich einen zweiten hinzufügen.
Die Konvention hat Wurzeln in älteren, gut etablierten Praktiken. Das `ARCHITECTURE.md`-Muster (populär gemacht durch Alex Kladovs vielzitierten Artikel) besagt, dass ein Repository eine High-Level-Übersicht der Codebasis enthalten sollte, die Struktur und Invarianten erklärt, ohne zu versuchen, zeilenweise mit dem Code synchronisiert zu bleiben. Architecture Decision Records (ADRs) erfassen individuelle Entscheidungen und deren Begründung im Laufe der Zeit. `DESIGN.md` ist das Ergebnis, wenn Sie diese Art von Dokument *für ein Publikum schreiben, das einen Code-Agenten einschließt*: prägnant, deklarativ, entscheidungsorientiert und dort platziert, wo der Agent es tatsächlich laden wird.
Zwei Eigenschaften machen es funktionsfähig. Es befindet sich im Repository, sodass der Agent es mit denselben Tools liest wie Code; Sie benötigen kein Plugin oder einen API-Aufruf. Und es geht um die Absicht, sodass es auch dann nützlich bleibt, wenn Dateien verschoben werden. Benennen Sie ein Paket um, und Ihre README-Screenshots verrotten; die Regel „Domänenlogik importiert niemals das Web-Framework“ bleibt wahr.
DESIGN.md vs AGENTS.md vs CLAUDE.md vs README
Diese Dateien überschneiden sich genug, um Verwirrung zu stiften, und unterscheiden sich genug, dass es ein Fehler wäre, sie zu einer zusammenzufassen. Kurz gesagt: `README` ist für das Onboarding von Menschen, `AGENTS.md` ist der operative Vertrag für Agenten, `CLAUDE.md` ist die Claude-spezifische Anweisungsdatei, und `DESIGN.md` ist die architektonische Begründung, von der alle profitieren.
`AGENTS.md` ist jetzt ein echtes, weit verbreitetes Format; das agents.md-Projekt beschreibt es als „ein einfaches, offenes Format zur Führung von Code-Agenten“, das in Zehntausenden von Projekten verwendet und unter der Agentic AI Foundation der Linux Foundation verwaltet wird. Seine Aufgabe ist operativ: Build-Schritte, Testbefehle, Codestil, Commit-Konventionen, all das, was Sie einem neuen Teammitglied sagen würden, um es nicht zu blockieren. Gemäß Anthropic's Claude Code Memory-Dokumentation spielt `CLAUDE.md` dieselbe Anweisungsrolle speziell für Claude; die Dokumentation empfiehlt sogar, wenn Sie bereits eine `AGENTS.md` haben, eine `CLAUDE.md` zu erstellen, die diese mit `@AGENTS.md` importiert, damit beide Tools eine einzige Quelle der Wahrheit lesen.
Beachten Sie, was in diesen Beschreibungen fehlt: tiefe architektonische Begründung. `AGENTS.md` und `CLAUDE.md` sind darauf ausgelegt, kurz zu sein. Die Claude Code-Dokumentation empfiehlt ausdrücklich, `CLAUDE.md` unter 200 Zeilen zu halten, da längere Dateien Kontext verbrauchen und die Zuverlässigkeit, mit der das Modell ihnen folgt, verringern. Eine echte Architekturerklärung, die Grenzen, die Invarianten, die abgelehnten Alternativen, die Datenmodellregeln passen dort nicht hinein, ohne es aufzublähen. Stattdessen verweisen Sie darauf. `DESIGN.md` wird zum ausführlichen Dokument; `AGENTS.md` / `CLAUDE.md` verweisen mit einer einzigen Zeile darauf.
| Datei | Zielgruppe | Beantwortet | Lebensdauer / Änderungsrate | Länge |
|---|---|---|---|---|
README.md |
Menschen (Benutzer, neue Mitwirkende) | Was ist das, wie starte ich es | Ändert sich mit Funktionen | Mittel |
AGENTS.md |
Jeder Code-Agent | Wie baue, teste, lintere, committe ich hier | Ändert sich mit den Tools | Kurz (operativ) |
CLAUDE.md |
Speziell Claude Code | Wie AGENTS.md, plus Claude-spezifische Regeln | Ändert sich mit den Tools | Kurz (unter ~200 Zeilen) |
DESIGN.md |
Agenten + Ingenieure + Rezensenten | Warum ist das System so aufgebaut; was darf niemals kaputtgehen | Ändert sich mit der Architektur (selten) | Mittel, entscheidungsdicht |
Die Beziehung ist komplementär, nicht kompetitiv. Ein sauberes Setup für einen Claude + Codex-Shop sieht so aus: `README.md` für Menschen; eine `AGENTS.md` mit Build/Test/Stil; eine `CLAUDE.md`, die nur `@AGENTS.md` plus zwei Claude-spezifische Zeilen enthält; und `DESIGN.md`, das die Architektur enthält und von `AGENTS.md` verlinkt ist, damit jeder Agent es bei Bedarf lädt. Keine Duplizierung, jede Datei hat eine Aufgabe. Wenn Sie eine tiefere Einführung in die Strukturierung von Claudes Kontext über diese Dateien hinweg wünschen, erläutert Claude Code-Workflows das Speichermodell in der Praxis.
Was in DESIGN.md gehört (mit Vorlage)
`DESIGN.md` sollte die Fragen beantworten, die ein Agent nicht aus dem Code ableiten kann: die Struktur des Systems, die Regeln, die in keiner einzelnen Datei auftauchen, und die Entscheidungen, die Sie absichtlich getroffen haben. Halten Sie es deklarativ. Jeder Abschnitt sollte sich wie eine Regel lesen, die ein Rezensent durchsetzen würde, nicht wie ein Aufsatz.
Behandeln Sie Folgendes:
- Systemstruktur: die Schichten oder Module und in welche Richtung Abhängigkeiten fließen. Ein Satz pro Grenze.
- Invarianten: Dinge, die immer wahr sein müssen. Formulieren Sie sie als Absolute. „Guthaben wird außerhalb eines autorisierten Überziehungskredits niemals negativ.“ „Jeder externe Aufruf ist idempotent mittels Anforderungsschlüssel.“
- Wichtige Entscheidungen und ihre Begründung: die Entscheidungen, die willkürlich erscheinen, bis Sie wissen, warum. Fügen Sie das *Warum* hinzu; die Begründung ist das, was einen Agenten davon abhält, es zu „reparieren“.
- Abgelehnte Alternativen: was Sie absichtlich *nicht* getan haben, damit ein Agent es nicht als frische Idee vorschlägt. Dieser eine Abschnitt verhindert eine große Klasse schlechter Vorschläge.
- Daten- und Domänenregeln: Gelddarstellung, Zeit-/Zeitzonenbehandlung, Bezeichner, Soft-Delete, Mandantenfähigkeit.
- Die maßgebliche Quelle des API-Vertrags: wo sich die OpenAPI-Spezifikation befindet und die Regel, dass sie gegenüber handgeschriebenen Typen maßgeblich ist.
- Wohin neuer Code gehört: eine kurze „wenn Sie X hinzufügen, gehört es nach Y“-Karte, damit Agenten die Logik nicht verstreuen.
- Nicht im Geltungsbereich / Nicht anfassen: generierte Dateien, Legacy-Module unter Migration, alles, was ein Agent in Ruhe lassen sollte.
Hier ist eine vollständige Vorlage, geschrieben für einen realistischen Zahlungs-API-Dienst. Kopieren Sie sie, löschen Sie, was nicht zutrifft, und füllen Sie den Rest aus.
# DESIGN.md: Zahlungs-API-Dienst
Diese Datei dokumentiert die architektonische Absicht und die dahinter stehenden Entscheidungen.
Lesen Sie dies, bevor Sie Code generieren oder ändern. Wenn eine Änderung mit einer hier festgelegten Regel in Konflikt steht, halten Sie inne und markieren Sie sie, anstatt sie zu umgehen.
## Systemstruktur
Geschichtet, Abhängigkeiten zeigen nur nach innen:
http (Handler, DTOs) -> app (Anwendungsfälle) -> domain (Entitäten,
Invarianten) <- infra (DB, Gateway-Clients)
- `domain/` hat keine Importe aus `http/`, `app/` oder einem Framework.
- `infra/` implementiert Schnittstellen, die in `domain/` oder `app/` deklariert sind.
- `http/` berührt niemals direkt die Datenbank oder das Zahlungs-Gateway.
Es ruft einen Anwendungsfall in `app/` auf.
## Invarianten (müssen immer gelten)
- Ein Ledger-Eintrag ist nach dem Schreiben unveränderlich. Korrekturen sind neue
kompensierende Einträge, niemals Aktualisierungen oder Löschungen.
- Der Kontostand wird aus Ledger-Einträgen abgeleitet, nicht als mutierbares Feld gespeichert, das Code
direkt setzen kann.
- Geld ist eine ganzzahlige Anzahl von Untereinheiten (Cents) plus ein ISO-4217
Währungscode. Niemals eine Gleitkommazahl. Niemals Währungen in einer Operation mischen.
- Jeder Aufruf an ein externes Zahlungs-Gateway ist idempotent, mittels
`idempotency_key` verschlüsselt. Wiederholungsversuche dürfen nicht zu doppelter Abbuchung führen.
- Guthaben wird niemals negativ, es sei denn, eine explizite `OverdraftPolicy`
autorisiert dies für dieses Konto.
## Wichtige Entscheidungen und Begründung
- **Outbox-Muster für Gateway-Aufrufe.** Handler schreiben einen Intent-Eintrag
in derselben DB-Transaktion wie die Geschäftsänderung, dann ruft ein Worker
das Gateway auf. Begründung: Das Gateway hat unter Last eine Zeitüberschreitung;
die Inline-Ausführung führte dazu, dass Anfragelatenz und Fehlerbehandlung unklar wurden.
Rufen Sie das Gateway nicht von einem Request-Handler aus auf.
- **Einziger Schreibpfad pro Aggregat.** Nur `Account.post_entry()`
schreibt in das Ledger. Begründung: Ein zweiter Schreibpfad verursachte die
Saldoabweichung vom März 2025. Fügen Sie neues Verhalten als Methoden an das
Aggregat hinzu, nicht als neue Abfragen.
- **Event Sourcing nur für das Ledger.** Der Rest des Systems ist
CRUD. Begründung: Wir benötigen einen perfekten Audit-Trail nur für Geld
und nichts anderes, und vollständiges Event Sourcing war anderswo zu kostspielig.
## Abgelehnte Alternativen (nicht wieder einführen)
- ORM Lazy-Loading über Aggregate hinweg; verursachte N+1-Probleme und unklare
Transaktionsgrenzen. Repositories geben vollständig geladene Aggregate zurück.
- Speichern des Saldos als in-place aktualisierte Spalte; siehe Vorfall mit Saldoabweichung.
Der Saldo wird immer abgeleitet.
- Eine generische `Money`-Bibliothek aus dem Registry; wir haben unsere
eigene `domain/money.py`; verwenden Sie diese.
- Synchrone Webhooks an Händler aus dem Request-Thread; sie
blockieren und schlagen stillschweigend fehl. Verwenden Sie die Benachrichtigungswarteschlange.
## Daten- und Domänenregeln
- Alle Zeitstempel sind UTC, als timestamptz gespeichert, am Rand im RFC 3339-Format
formatiert. Keine naiven Datetimes überqueren eine Funktionsgrenze.
- IDs sind ULIDs, die in der App-Schicht generiert werden, niemals DB-Autoincrement.
- Soft-Delete wird nicht verwendet. Datensätze sind entweder aktiv oder werden von einem
expliziten Anwendungsfall in eine Archivtabelle verschoben.
- Multi-Tenant: Jede Abfrage ist nach `tenant_id` begrenzt. Eine Repository-
Methode ohne Mandantengrenze ist ein Fehler.
## Maßgebliche Quelle des API-Vertrags
- Die OpenAPI 3.1-Spezifikation in `api/openapi.yaml` ist maßgeblich.
Anfrage-/Antworttypen werden daraus generiert; bearbeiten Sie die
generierten Typen in `http/generated/` nicht manuell.
- Neue oder geänderte Endpunkte: Aktualisieren Sie zuerst `api/openapi.yaml`, dann
regenerieren Sie, dann implementieren Sie. Die Spezifikation wird in
Apidog entworfen und überprüft, bevor Code geändert wird.
- Fehlerantworten folgen RFC 9457 (problem+json). Verwenden Sie den gemeinsamen
`problem()`-Helfer; erfinden Sie keine ad-hoc-Fehlertypen.
## Wohin neuer Code gehört
- Neuer Endpunkt: Route in `http/routes/`, DTO in `http/dto/`, Anwendungsfall
in `app/usecases/`, Domänenlogik in `domain/`.
- Neue externe Integration: Client in `infra/clients/`, Schnittstelle
in `app/ports/`.
- Querschnittliche Belange (Authentifizierung, Logging, Idempotenz): Middleware in
`http/middleware/`, niemals inline in Handlern.
## Nicht im Geltungsbereich / Nicht anfassen
- `http/generated/`: regeneriert aus OpenAPI, Änderungen gehen verloren.
- `legacy/billing_v1/`: eingefroren, unter Migration. Nicht erweitern.
- `migrations/`: niemals eine angewendete Migration bearbeiten; fügen Sie eine neue hinzu.
## Im Zweifelsfall
Wenn eine angeforderte Änderung erfordert, eine der oben genannten Regeln zu brechen, ist der richtige Schritt, dies zu sagen und die kleinste designkonforme Alternative vorzuschlagen, anstatt die Regel stillschweigend zu umgehen.
Dieser letzte Abschnitt ist wichtiger, als er aussieht. Einem Agenten zu sagen, was zu tun ist, wenn die Anforderung mit dem Design in Konflikt steht, verwandelt die Datei von einer passiven Dokumentation in eine aktive Leitplanke. Ohne sie neigt ein Agent, der auf eine Einschränkung stößt, dazu, diese zu umgehen und den Workaround auszuliefern.
Wie Code-Agenten DESIGN.md tatsächlich verarbeiten
Agenten haben keinen speziellen `DESIGN.md`-Parser. Sie verarbeiten es auf dieselbe Weise wie jede andere Datei: indem sie es mit ihren Dateitools lesen und den Inhalt als Kontext behandeln. Daher ist die Art und Weise, wie es geladen wird, wichtig, und sie unterscheidet sich je nach Tool geringfügig.
Das zuverlässige Muster besteht darin, `DESIGN.md` aus der Anweisungsdatei zu referenzieren, die jeder Agent bereits beim Start lädt. Für Claude Code ist das `CLAUDE.md`; die Memory-Dokumentation beschreibt eine `@path`-Importsyntax, bei der `@DESIGN.md` die Datei beim Sitzungsstart in den Kontext erweitert. Für das `AGENTS.md`-Ökosystem fügen Sie in `AGENTS.md` eine Zeile hinzu, die darauf verweist („Architektur- und Designregeln: siehe `DESIGN.md`; lesen Sie diese vor strukturellen Änderungen“). Agenten, die den Verzeichnisbaum durchlaufen, werden die nächste `AGENTS.md` aufgreifen, den Verweis sehen und `DESIGN.md` ziehen, wenn die Arbeit die Architektur betrifft. So oder so duplizieren Sie keinen Inhalt; Sie halten die kurze operative Datei kurz und lassen die ausführliche Datei ausführlich sein.
Drei praktische Hinweise zum Verhalten dieser Tools:
Erstens behandelt der Agent die Datei als Kontext, nicht als erzwungene Regeln. Die Claude Code-Dokumentation sagt unmissverständlich, dass der Inhalt von `CLAUDE.md` eine Anleitung ist, der das Modell zu folgen versucht, keine feste Einschränkung. Dasselbe gilt für alles, worauf Sie von dort aus verweisen. Deshalb formuliert die Vorlage alles als testbare Absolute und fügt eine explizite „Im Zweifelsfall“-Anweisung hinzu; vage Prosa wird unter Druck ignoriert, scharfe Regeln werden häufiger befolgt.
Zweitens beeinflussen Länge und Struktur die Einhaltung. Überschriften und Aufzählungszeichen sind Absätzen überlegen, da das Modell die Struktur so scannt, wie es ein Leser tut. Eine 3-seitige Wand aus architektonischer Philosophie wird überflogen; zehn prägnante Invarianten unter einer klaren Überschrift werden verwendet. Schreiben Sie für den Abruf, nicht für Prosa.
Drittens verändert die Datei die Ökonomie der Überprüfung, nicht nur die Generierung. Selbst wenn ein Agent sie teilweise ignoriert, kann ein Rezensent auf die verletzte Regel hinweisen, und der Agent korrigiert sie in einem Durchlauf („dies verstößt gegen die Single-Write-Path-Regel in DESIGN.md“). Diese Feedbackschleife, die die Korrektur auf die schriftliche Entscheidung stützt, ist der Ort, an dem ein Großteil des tatsächlichen Werts entsteht. Teams, die ihre eigenen Agenten-Frameworks entwickeln, stützen sich genau darauf; siehe Bauen Sie Ihr eigenes Claude Code, um zu sehen, wie diese Schleife in autonome Abläufe integriert wird.
Anti-Muster und wie man das Verrotten verhindert
Der schnellste Weg, `DESIGN.md` wertlos zu machen, ist, es wie eine Wiki-Seite zu schreiben. Eine verrottete Design-Datei ist schlimmer als keine, weil Agenten und Menschen ihr vertrauen und in die Irre geführt werden. Vermeiden Sie Folgendes.
Den Code wiederholen. „Die `UserService`-Klasse verwaltet Benutzer“ sagt einem Agenten nichts, was er nicht aus `user_service.py` lesen könnte. Wenn ein Satz durch das Lesen der Datei wahr ist, streichen Sie ihn. Behalten Sie nur das, was der Code Ihnen nicht sagen kann: Begründung, Invarianten, abgelehnte Pfade.
Tutorial-Ausweitung. Schritt-für-Schritt-Anleitungen „Wie man eine Funktion hinzufügt“ gehören in `CONTRIBUTING.md` oder eine Fertigkeit, nicht hierher. In dem Moment, in dem `DESIGN.md` Shell-Befehle und Copy-Paste-Schnipsel enthält, ist es das falsche Dokument und wird mit der Geschwindigkeit der Tools veralten.
Wunschdenken als Tatsache. Das Schreiben von „das System verwendet CQRS“, wenn die Hälfte davon nicht der Fall ist, trainiert Agenten, Code zu produzieren, der einer Fiktion entspricht. Dokumentieren Sie, was jetzt wahr ist, wohin Sie bewusst steuern, und kennzeichnen Sie den Unterschied. „Ziel: Alle Schreibvorgänge gehen über Anwendungsfälle. Aktuell: `legacy/` umgeht dies; nicht erweitern.“
Kein Eigentümer, kein Überprüfungsauslöser. Eine Design-Datei, für die niemand verantwortlich ist, driftet innerhalb eines Quartals ab. Verknüpfen Sie es mit einem Auslöser: Überprüfen Sie `DESIGN.md` in jedem PR, der ein Modul hinzufügt, eine Schichtgrenze ändert oder eine neue externe Abhängigkeit einführt. Fügen Sie diese Regel in die PR-Vorlage ein. Einige Teams fügen einen Checklistenpunkt hinzu: „Ändert dies eine Entscheidung in DESIGN.md? Wenn ja, aktualisieren Sie sie im selben PR.“
Synchronisationstheater. Versuchen Sie nicht, es zeilenweise mit dem Code synchron zu halten; das ist ein verlorenes Spiel und der Grund, warum Architekturdokumente aufgegeben werden. Halten Sie es auf der Ebene von Entscheidungen, die sich ein paar Mal im Jahr ändern, nicht von Funktionssignaturen, die sich wöchentlich ändern. Die `ARCHITECTURE.md`-Anleitung von matklad ist hier der richtige Instinkt: Schreiben Sie nur auf, was sich wahrscheinlich nicht oft ändert.
Den anderen Anweisungsdateien widersprechen. Wenn `AGENTS.md` eine Sache über Fehlerbehandlung sagt und `DESIGN.md` eine andere, wählen Agenten willkürlich eine aus. Halten Sie operative Regeln in `AGENTS.md` / `CLAUDE.md` und architektonische Regeln in `DESIGN.md` und lassen Sie sie sich nicht überschneiden. Wenn sie sich gegenseitig referenzieren müssen, zeigt die eine auf die andere; sie behaupten nicht beide dieselbe Tatsache.
Eine gesunde `DESIGN.md` ist kurz, dicht, deklarativ, gehört jemandem und wird bei einem Auslöser überprüft. Wenn Ihre lang, erzählerisch und zuletzt vor einem Jahr angefasst wurde, lesen Agenten Fiktion.
DESIGN.md für API- und Backend-Codebasen
Hier bewährt sich die Datei. API- und Backend-Dienste haben genau die Art von unsichtbaren, kostspieligen Einschränkungen, bei denen Agenten am schlechtesten sind: Vertragsgrenzen, Transaktionssemantik, Idempotenz, Datenintegrität, Schichtung. Nichts davon ist aus einer einzigen Datei ersichtlich, und Fehler dabei führen zu Bugs, die die Produktion und das Geld beeinträchtigen.
Fügen Sie diese API-spezifischen Dinge in `DESIGN.md` ein, und die Ausgabequalität des Agenten bei Backend-Tickets steigt sprunghaft an:
Der Vertrag ist die maßgebliche Quelle der Wahrheit, und sagen Sie, wo er sich befindet. Geben Sie klar an, dass die OpenAPI-Spezifikation maßgebend ist und generierte Typen nicht manuell bearbeitet werden dürfen. Agenten lieben es, einen generierten Typ „hilfsbereit“ anzupassen, um einen Build zu bestehen; eine Zeile in `DESIGN.md` stoppt dies. Verweisen Sie auf den Pfad der Spezifikationsdatei. Wenn Sie den Vertrag zuerst in Apidog entwerfen und das OpenAPI-Dokument in das Repository exportieren, kann Ihr `DESIGN.md` diese Datei als das nennen, dem jeder Endpunkt entsprechen muss, und der Agent hat ein eindeutiges Ziel. Das Argument für das Entwerfen des Vertrags vor dem Code wird in APIs für KI-Agenten entwerfen behandelt; ein Design-First-Vertrag ist genau das, was von Agenten generierte Handler sicher akzeptierbar macht.
Transaktions- und Konsistenzgrenzen. Wo beginnt und endet eine Transaktion? Was ist darin erlaubt? „Externe Aufrufe erfolgen niemals innerhalb einer DB-Transaktion; verwenden Sie die Outbox.“ Agenten greifen jedes Mal standardmäßig auf den naiven Inline-Aufruf zurück, es sei denn, die Datei verbietet es.
Idempotenz und Wiederholungsversuche. Geben Sie die Idempotenzstrategie als Invariante an. Zahlungs-, Bestell- und Bereitstellungs-Endpunkte sind Orte, an denen ein fehlender Idempotenzschlüssel zu einer doppelten Abbuchung wird. Der Agent wird dies nicht aus dem Lesen eines Handlers ableiten.
Fehlermodell. Ein Satz: „Alle Fehler sind problem+json über den `problem()`-Helfer; erfinden Sie niemals Fehlertypen.“ Ohne dies erhalten Sie für jeden Endpunkt eine andere Fehlerumhüllung, was jeden Client bricht.
Authentifizierungs- und Mandantenfähigkeit. „Jede Abfrage ist mandantenbezogen; eine nicht-mandantenbezogene Repository-Methode ist ein Fehler.“ Dies ist eine Sicherheitsinvariante und in keiner einzelnen Abfrage sichtbar, daher ist es genau die Art von Regel, die aufgeschrieben werden muss.
Versionsverwaltung und Regeln für breaking changes. Was als Breaking Change zählt, wie Sie versionieren, was in einem Minor-Release erlaubt ist. Agenten werden fröhlich ein Antwortfeld umbenennen; die Datei sagt ihnen, dass dies ein Breaking Change mit einem Prozess ist.
Für Backend-Arbeiten ist der Ertrag konkret: weniger Schichtverletzungen, keine überraschenden Inline-Gateway-Aufrufe, konsistente Fehler- und Paginierungsformen sowie vertragskonforme Handler, weil der Agent auf die OpenAPI-Spezifikation verwiesen wurde, anstatt das Schema zu erraten. Der Agent hört auf zu erfinden und beginnt, sich anzupassen. Wenn Sie möchten, dass der Agent auch die API testet, die er gerade geschrieben hat, ist die Kombination aus Vertrag und Design das, was Tools und Agenten ermöglicht, gegen eine bekannte Schnittstelle zu testen; Apidog herunterladen bietet Ihnen den Design-First-Arbeitsbereich, den OpenAPI-Export, auf den Ihr `DESIGN.md` verweist, sowie einen MCP-Server und einen KI-Agenten-Debugger, um zu überprüfen, ob generierte Endpunkte tatsächlich dem Vertrag entsprechen.
Fazit
- `DESIGN.md` dokumentiert, *warum* Ihr Code so aufgebaut ist, wie er ist: die Invarianten, Entscheidungen und abgelehnten Alternativen, die ein Agent nicht aus dem Quellcode lesen kann.
- Es ergänzt eher als ersetzt `AGENTS.md` und `CLAUDE.md`: Diese bleiben kurz und operativ; `DESIGN.md` enthält die ausführliche Architektur und wird von diesen referenziert.
- Schreiben Sie es deklarativ, als testbare Absolute plus eine Regel „im Zweifelsfall markieren, nicht umgehen“, damit es als Leitplanke dient, nicht als passive Prosa.
- Es zahlt sich am meisten bei API- und Backend-Codebasen aus, wo Vertragsgrenzen, Transaktionen, Idempotenz und Mandantenfähigkeit unsichtbar sind und Fehler teuer sein können.
- Verhindern Sie das Verrotten, indem Sie einen Eigentümer und einen Überprüfungsauslöser haben, der an Ihre PR-Vorlage gebunden ist; synchronisieren Sie es niemals zeilenweise mit dem Code.
- Der größte Gewinn im Backend ist die Benennung der OpenAPI-Spezifikation als maßgeblich, damit Agenten dem Vertrag entsprechen, anstatt Schemata zu erfinden.
- Entwerfen Sie diesen Vertrag zuerst. Apidog herunterladen, um APIs Design-First zu entwerfen, die OpenAPI-Spezifikation zu exportieren, auf die Ihr `DESIGN.md` verweist, und zu testen, ob die vom Agenten generierten Endpunkte tatsächlich damit übereinstimmen.
FAQ
Ist DESIGN.md ein offizieller Standard wie AGENTS.md?
Nein. `AGENTS.md` ist ein definiertes, weit verbreitetes Format, das jetzt unter der Agentic AI Foundation der Linux Foundation verwaltet wird. `DESIGN.md` ist eine Community-Konvention ohne einzelnen Eigentümer oder Spezifikation, in derselben Familie wie `ARCHITECTURE.md` und ADRs. Behandeln Sie es als ein nützliches Muster, das Sie anpassen, nicht als einen Standard, dem Sie sich anpassen müssen.
Brauche ich DESIGN.md, wenn ich bereits AGENTS.md oder CLAUDE.md habe?
Wenn Ihre Architektur nicht offensichtliche Einschränkungen hat, ja. `AGENTS.md` und `CLAUDE.md` sollen kurz und operativ bleiben; die Claude Code-Dokumentation empfiehlt, `CLAUDE.md` unter etwa 200 Zeilen zu halten. Tiefe architektonische Begründungen passen dort nicht hinein, ohne sie aufzublähen und die Einhaltung zu beeinträchtigen, daher legen Sie sie in `DESIGN.md` ab und verweisen darauf. Für die operative Datei selbst siehe wie man AGENTS.md-Dateien schreibt.
Wie unterscheidet sich DESIGN.md von ARCHITECTURE.md?
Hauptsächlich Absicht und Zielgruppe. `ARCHITECTURE.md` ist die ältere Konvention, die sich an menschliche Mitwirkende richtet, die die Codebasis abbilden. `DESIGN.md` ist dieselbe Idee, geschrieben für ein Publikum, das einen Code-Agenten einschließt: deklarativer, entscheidungs- und invariantenfokussierter und explizit aus den Agenten-Anweisungsdateien referenziert, damit es in den Kontext geladen wird. Viele Teams verwenden eine Datei und einen Namen; die Prinzipien sind dieselben.
Wie lang sollte DESIGN.md sein?
Lang genug, um die Entscheidungen abzudecken, bei denen Agenten immer wieder Fehler machen, kurz genug, dass jede Zeile ihren Platz verdient. Entscheidungsdicht schlägt umfassend. Wenn es sich wie ein Tutorial liest oder den Code wiederholt, streichen Sie es. Zwei bis vier fokussierte Seiten mit Invarianten und Begründungen schlagen eine fünfzehnseitige Erzählung, die kein Agent genau lesen wird.
Wie bringe ich den Agenten dazu, es tatsächlich zu lesen?
Referenzieren Sie es aus der Datei, die der Agent bereits beim Start lädt. Für Claude Code importieren Sie es aus `CLAUDE.md` mit `@DESIGN.md`. Für das `AGENTS.md`-Ökosystem fügen Sie eine Verweiszeile in `AGENTS.md` hinzu, die Agenten anweist, `DESIGN.md` vor strukturellen Änderungen zu lesen. Fügen Sie nicht das Ganze in die kurze Datei ein; verweisen Sie darauf, damit die operative Datei kurz bleibt.
Wird der Agent DESIGN.md immer folgen?
Nein, und Sie sollten dies bei Ihrem Design berücksichtigen. Agenten-Anweisungsdateien sind Kontext, dem das Modell zu folgen versucht, keine erzwungene Konfiguration. Schreiben Sie Regeln als scharfe Absolute, fügen Sie eine explizite Anweisung „Konflikte melden, nicht umgehen“ hinzu und verlassen Sie sich auf die Überprüfungsschleife; das Hinweisen auf eine verletzte Regel in `DESIGN.md` führt zu einer schnellen, korrekten Behebung, selbst wenn der erste Durchlauf sie übersehen hat.
Hilft DESIGN.md speziell bei Problemen mit API-Verträgen?
Sehr. Sein höchster Wert im Backend besteht darin, festzulegen, dass die OpenAPI-Spezifikation maßgebend ist und die Datei zu benennen, damit Agenten dem Vertrag entsprechen, anstatt Schemata zu erfinden oder generierte Typen manuell zu bearbeiten. Das Entwerfen dieses Vertrags zuerst in einem Tool wie Apidog gibt dem Agenten ein eindeutiges Ziel, auf das Ihr `DESIGN.md` direkt verweisen kann.
Wo sollte DESIGN.md im Repository liegen?
Im Stammverzeichnis des Repositorys, neben `README.md` und `AGENTS.md`, damit Agenten und Menschen es ohne Suche finden. In einem Monorepo funktioniert eine `DESIGN.md` im Stammverzeichnis für systemweite Regeln plus eine pro Paket für lokale Architektur gut, was widerspiegelt, wie Agenten die nächste `AGENTS.md` im Verzeichnisbaum lesen.
