Der Stack, den ich meinem KI-Agenten übergebe
- ai-agents
- developer-tools
- next-js
- workflow
Ein fester, meinungsstarker Stack, der einem KI-Coding-Agenten zu Beginn jeder Sitzung übergeben wird, schlägt das freie Auswählen von Abhängigkeiten jedes Mal. Weniger Entscheidungen, wiederverwendbare Konventionen, wachsende Vertrautheit über Projekte hinweg. Hier ist, was ich übergebe und warum.
Jedes Mal, wenn ich ein neues Projekt mit einem KI-Coding-Agenten starte, übergebe ich ihm denselben Stack. Keine Liste von Vorschlägen. Eine feste, verbindliche Konfiguration, von der der Agent nicht abweichen darf ohne ausdrückliche Genehmigung. Das klingt starr. Das ist es auch. Und genau diese Starrheit ist der Punkt.
Wenn der Agent den Stack von Anfang an kennt, hört er auf zu raten. Er verwendet Muster wieder, die er bereits in demselben Kontextfenster gesehen hat, greift auf die Helper zurück, die ich ihm bereits genannt habe, und produziert Output, der sich reibungslos in den Rest der Codebasis einfügt. Wenn der Agent den Stack selbst wählen darf, verbringst du die ersten drei Stunden damit, darüber zu streiten, ob er das richtige ORM gewählt hat.

Der Stack
Die Entscheidungen sind nicht willkürlich. Jede wurde nach dem Einsatz in mindestens zwei Produktionsprojekten getroffen und für gut genug befunden, um sie nicht mehr in Frage zu stellen. Das ist das Kriterium: nicht perfekt, gut genug, um zu stoppen.
- Next.js App Router + TypeScript strict -- Server Components, Server Actions, kein separater API-Server für die meisten Projekte
- Tailwind CSS -- nur Utility-Klassen, kein CSS-in-JS, null Runtime-Overhead
- MySQL 8 oder Postgres 16 via Prisma -- Prisma für Schema, Migrationen und typsicheren Client; MySQL für Projekte auf Ploi, Postgres sonst
- Better Auth -- Session und OAuth in wenigen Zeilen, Auth-Handler an einem festen Pfad, den der Agent bereits kennt
- Resend -- Transaktions-E-Mail, hervorragendes SDK, kein dedizierter Server nötig
- MinIO -- self-hosted S3-kompatibles Object Storage, läuft lokal in Docker Compose und auf Hetzner in Produktion
- Redis + BullMQ -- Hintergrundjobs mit Wiederholungsversuchen, Parallelitätskontrolle und einem einfachen Job-Klassen-Muster
- Docker Compose -- ein Befehl startet Datenbank, Redis und MinIO lokal; gleiche Image-Versionen in Produktion
- Ploi + Hetzner -- VPS-Hosting, Serververwaltung ohne Ops-Aufwand, vorhersagbare Kosten
- Cloudflare -- DNS, CDN, SSL-Terminierung, DDoS-Schutz vor allem
Warum Fest Flexibel schlägt
Der KI-Agent ist ein zustandsloser Ausführer. Er trägt weder Meinung noch Loyalität noch Gewohnheit von Sitzung zu Sitzung. Bei einer leeren Tafel und einer vagen Anweisung wie "einen Hintergrundjob hinzufügen" wählt er die BullMQ-Alternative, die er in seinen Trainingsdaten am häufigsten gesehen hat. Das kann jedes Mal eine andere Abstraktion sein. Es könnte einen zweiten Redis-Client einführen. Es könnte mit dem Session-Store der Auth-Bibliothek in Konflikt geraten.
Ein fester Stack eliminiert diese Entscheidungsklasse vollständig. Der Agent wählt die Queue-Bibliothek nicht aus. Er verwendet BullMQ, weil die AGENTS.md es sagt und weil die Basis-Job-Klasse bereits in der Codebasis existiert. Die Entscheidung wurde einmal getroffen, ist aufgeschrieben, und der Agent liest sie.
Die AGENTS.md: Den Stack als Agenten-Gedächtnis kodieren
Ein KI-Coding-Agent hat kein Gedächtnis zwischen Sitzungen. Der Agent, der letzte Woche deinen BullMQ-Worker konfiguriert hat, weiß heute nicht, dass er existiert. Ohne einen Mechanismus zur Kontextpersistenz beginnt jede neue Sitzung bei null und der Agent erfindet Muster neu, die du bereits festgelegt hast.
Der Mechanismus ist eine Datei. Eine Markdown-Datei im Projektstamm, die zu Beginn jeder Sitzung in den Agenten-Kontext geladen wird. Ich nenne sie AGENTS.md. Sie ist keine Dokumentation für Menschen (das macht die README). Sie ist das Arbeitsgedächtnis des Agenten: der Stack ist fest, hier sind die Konventionen, hier sind die Befehle, hier sind die explizit verbotenen Muster.
Die AGENTS.md ist das einzige Artefakt, das einen zustandslosen LLM in einen projektbewussten Mitarbeiter verwandelt. Schreibe sie so, als müsste sie einen Kontext-Reset zwischen jeder Sitzung überstehen, denn das muss sie.
Unten ist der tatsächliche Stack-Abschnitt, den ich in die AGENTS.md jedes neuen Projekts einfüge. Der Agent liest ihn, bevor er irgendeinen Code anfasst. Ersetze die Datenbankwahl (MySQL vs Postgres), halte alles andere fest.
# AGENTS.md -- Stack & Conventions for AI Coding Agents
## Stack (fixed, do not substitute without explicit approval)
- Framework : Next.js App Router, TypeScript strict mode
- Styles : Tailwind CSS utility classes only -- no CSS-in-JS, no plain CSS files
- Database : MySQL 8 or Postgres 16 via Prisma (schema in prisma/schema.prisma)
- Auth : Better Auth (src/lib/auth.ts) -- do NOT roll a custom session system
- Email : Resend SDK (src/lib/email.ts) -- transactional only, no bulk marketing
- Object store: MinIO, S3-compatible (src/lib/storage.ts)
- Queues : BullMQ backed by Redis (src/queues/) -- background jobs only
- Environment : Docker Compose (docker-compose.yml at repo root) -- run locally with:
docker compose up -d
- Hosting : Ploi on Hetzner CX21+, Cloudflare in front (proxied, SSL full-strict)
## House conventions
- All server actions in src/app/actions/ -- never in route handlers or components
- API routes under src/app/api/v1/ return { data, error } -- use ApiResponse type
- BullMQ jobs extend BaseJob (src/queues/base-job.ts) -- no bare Queue instantiation
- File naming : kebab-case files, PascalCase components, camelCase utils
- No any in TypeScript -- use unknown and narrow explicitly
- No console.log in committed code -- use src/lib/logger.ts
## Commands
npx prisma migrate dev # apply local migrations
npx prisma generate # regenerate client after schema change
docker compose up -d # start MySQL/Postgres, Redis, MinIO
npm run dev # Next.js dev server
npm run typecheck # tsc --noEmit
npm run lint # ESLint + Prettier check
## Known gotchas
- Better Auth requires the auth handler at src/app/api/auth/[...all]/route.ts exactly
- MinIO presigned URLs expire in 1 h by default -- adjust in src/lib/storage.ts
- BullMQ concurrency defaults to 1 per worker -- set explicitly for each queue
- Prisma Client is a singleton -- import from src/lib/prisma.ts, never instantiate inline
Drei Dinge machen diese Datei wirksam. Erstens ist sie vorschreibend: "do NOT roll a custom session system" ist kein Vorschlag. Zweitens nennt sie den genauen Dateipfad für jede Abstraktion (src/lib/auth.ts, src/lib/prisma.ts). Der Agent muss nicht suchen. Drittens listet sie die Tücken auf: die, die du auf die harte Tour entdeckt hast, damit der Agent sie nicht nochmal entdecken muss.
Die lokale Umgebung mit einem einzigen Befehl
Docker Compose ist aus einem bestimmten Grund Teil des Stacks: Es macht die lokale Umgebung zu einem erstklassigen Artefakt, über das der Agent nachdenken kann. Wenn der Agent AGENTS.md liest und sieht, dass docker compose up -d MySQL, Redis und MinIO startet, weiß er genau, was er dir sagen soll, wenn etwas nicht läuft. Er muss nicht raten, ob du eine lokale MySQL-Installation oder eine Cloud-Datenbank in der Entwicklung hast.
# docker-compose.yml (excerpt -- services the agent can rely on)
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: 'root'
MYSQL_DATABASE: 'app'
ports:
- '3306:3306'
volumes:
- db_data:/var/lib/mysql
redis:
image: redis:7-alpine
ports:
- '6379:6379'
minio:
image: minio/minio
command: server /data --console-address ':9001'
environment:
MINIO_ROOT_USER: 'minio'
MINIO_ROOT_PASSWORD: 'minio123'
ports:
- '9000:9000'
- '9001:9001'
volumes:
- minio_data:/data
volumes:
db_data:
minio_data:
Dieselben Image-Versionen laufen lokal und in Produktion auf Hetzner. Der Agent kennt die Verbindungsstrings aus den Umgebungsvariablen, die ihm mitgeteilt werden. Es gibt keine "läuft nur auf meinem Rechner"-Oberfläche.

Wachsende Vertrautheit über Projekte hinweg
Die echte Auszahlung ist nicht das erste Projekt. Es ist das fünfte. Wenn du diesen Stack fünfmal verwendet hast, ist die AGENTS.md verfeinert. Der Tücken-Abschnitt hat echte Bugs abgefangen. Der Abschnitt über verbotene Muster hat mindestens zwei architektonische Fehler verhindert. Die Basis-Job-Klasse wurde in eine gemeinsame Vorlage extrahiert, die du klonen kannst.
Jedes neue Projekt erbt die angesammelte Disziplin der vorherigen. Der Agent kommt am ersten Tag bereits mit den Mustern vertraut an, für deren Etablierung du zwei Projekte gebraucht hast. Das ist keine Magie. Es ist einfach Dokumentation, die tatsächlich gelesen wird.
- Starte jedes Projekt, indem du die AGENTS.md-Vorlage klonst und die Datenbankwahl anpasst.
- Aktualisiere die AGENTS.md, wenn du eine neue Abstraktion hinzufügst, ein Muster verbietest oder auf eine Tücke stößt.
- Behandle sie als lebendige Spezifikation: Wenn sich die Codebasis ändert, ändert sich zuerst die AGENTS.md.
- Lade sie explizit zu Beginn jeder Agenten-Sitzung -- nimm nicht an, dass der Agent sie findet.
Auch das Review wird schneller
Ein sekundärer Vorteil, der es wert ist, erwähnt zu werden: Code-Reviews werden schneller, wenn du den Stack kennst. Du bewertest nicht, ob der Agent eine sinnvolle Bibliothek gewählt hat. Du bewertest nur, ob er die vereinbarte Bibliothek korrekt verwendet hat. Das ist eine viel engere Frage, und sie akkumuliert auch: Je länger du den Stack verwendest, desto schneller erkennst du eine Abweichung.
Die These ist einfach: Ein fester Stack ist ein Kraftmultiplikator für KI-gestützte Entwicklung. Der Agent kennt die Tools, du kennst die Tools, die AGENTS.md überbrückt die Sitzungen. Du hörst auf, über Infrastruktur zu diskutieren, und fängst an, Features auszuliefern. Das ist der ganze Punkt.