Agentic Engineering
Ich entwerfe und betreibe Multi-Agent-Entwicklungsschleifen — Flotten von Claude Code und anderen CLI-Coding-Agenten, die eigenständig planen, implementieren, reviewen und ihre eigenen Pull Requests mergen, mit GitHub als einziger Quelle der Wahrheit und Menschen im Loop für Grundsatzentscheidungen. Codewright, eine Wissensdatenbank mit Terminal-Rezepten für Entwickler und Coding-Agenten, entsteht fast vollständig auf diese Weise: Planner-, Worker-, Reviewer-, Janitor- und Orchestrator-Agenten koordinieren sich über GitHub Issues, atomare Claims und Branch-Protection — ohne Seitenkanal-Zustand, ohne eigene Orchestrierungs-Datenbank.
Der Loop
Die Grundidee ist einfach: die Software-Delivery-Pipeline selbst als Aufgabenwarteschlange der Agenten zu behandeln und GitHub zum einzigen Ort zu machen, an dem Zustand existiert. Kein Dashboard, keine Message-Queue, keine Datenbank darüber, "was die Agenten gerade tun" — nur Issues, Branches, Pull Requests und Labels. Dadurch kann jeder agentenunabhängige Harness (Claude Code, Codex oder ein Mensch) demselben Loop beitreten und mit den anderen synchron bleiben.
Der Loop
Jeder Agent — Worker, Reviewer oder Planner — folgt demselben Protokoll:
- Zustand von GitHub lesen (offene Issues, deren Labels, offene PRs).
- Genau eine Arbeitseinheit atomar beanspruchen, sodass niemals zwei Agenten dieselbe Aufgabe greifen.
- Die Änderung auf einem eigenen Branch entwickeln.
- Einen Pull Request zurück in den Integrationsbranch öffnen, bereit für Review — niemals als Draft.
- Eine andere Agent-Instanz (oder ein Mensch) prüft ihn gegen das verknüpfte Issue und die schriftlichen Projektspezifikationen.
- Bei bestandenem Review und grüner CI mergt der PR automatisch, und das Issue schließt sich.
Warum GitHub als einzige Quelle der Wahrheit
Den gesamten Koordinationszustand in GitHub abzulegen — statt in einer Seitenkanal-Datenbank — bedeutet, dass der Loop für jeden mit Repo-Zugriff nachvollziehbar ist, das Sterben einer Agenten-Session mitten in einer Aufgabe übersteht und es erlaubt, lang laufende lokale CLI-Sessions, Cloud-Sessions und geplante, cronartige Starts beliebig zu kombinieren. Geht einem Agenten der Kontext aus oder wird sein Prozess beendet, liest der nächste einfach dieselben Issues und Labels und setzt die Koordination genau dort fort — nichts existierte je nur im Kopf dieses einen Agenten.
Branch- und Umgebungsmodell
Ich trenne die tägliche Integration klar von dem, was tatsächlich deployed ist: ein nicht deployender Integrationsbranch, auf den sich sämtliche Agentenarbeit richtet, ein Staging-Branch, der nur gebündelte Promotions erhält, sobald eine Reihe von Änderungen gemeinsam verifiziert wurde, und Produktion, die nur Promotions von Staging erhält. Agenten squash-mergen ihre eigene Feature-Arbeit in den Integrationsbranch, Promotions zwischen den langlebigen Branches laufen jedoch über Merge-Commits, damit die Branches nie dauerhaft auseinanderdriften.
Rollen
Ich teile den Loop in fünf Rollen mit jeweils klar begrenzter Aufgabe:
- Planner — liest die Roadmap und offene Issues, legt gut abgegrenzte, beanspruchbare Aufgaben mit klaren Abnahmekriterien an und hält jederzeit einen gesunden Vorrat an bereiter Arbeit, damit Worker nie untätig sind oder den Umfang erraten müssen.
- Worker — beansprucht genau eine bereite Aufgabe, setzt sie vollständig um und öffnet einen Pull Request pro Issue. Stellt sich eine Aufgabe als größer als erwartet heraus, liefert er den kleinsten sinnvollen Ausschnitt und legt eine Folgeaufgabe an, statt den PR aufzublähen.
- Reviewer — eine andere Agent-Instanz als die, die den Code geschrieben hat (ein Agent darf niemals seine eigene Arbeit reviewen) prüft den Diff gegen das Issue, die Projektspezifikationen und die Konventionen und liefert dann ein explizites Verdikt: Approve oder Request Changes.
- Janitor — ein kleiner, deterministischer, schlüsselloser Prozess (ganz ohne Modellaufrufe), der nach Zeitplan läuft, um seit Stunden unangetastete Claims freizugeben und verwaiste Pull Requests anzustoßen, damit der Loop nie unbemerkt stecken bleibt.
- Orchestrator — überwacht die Flotte direkt aus der macOS-App Codewright Agents heraus statt über einen einmaligen Kickoff-Prompt: behält jede laufende Session im Blick, hält die richtige Rollenmischung aktiv und greift dort ein, wo ein einzelner Agent nicht allein entscheiden sollte.
Jede Rolle kann eine lang laufende lokale Session, ein sich selbst taktender Loop, der so lange weiterarbeitet, bis nichts mehr übrig ist, oder ein geplanter, im Takt feuernder Start sein, der genau einen Durchlauf macht. Alle drei gleichzeitig zu mischen ist unproblematisch — nicht der startende Harness verhindert Kollisionen, sondern das Claiming-Protokoll.
Koordination
Nebenläufigkeit zwischen Agenten muss durch Konstruktion sicher sein, nicht durch Konvention — deshalb setze ich auf Primitiven, die GitHub ohnehin garantiert, statt eine eigene Locking-Schicht zu erfinden:
Atomares Claiming
Ein Worker beansprucht eine Aufgabe, indem er versucht, einen eindeutig benannten Branch-Ref für dieses Issue anzulegen. Die Erstellung eines Git-Refs ist serverseitig atomar: Konkurrieren mehrere Agenten um dieselbe Aufgabe, gelingt genau eine Erstellung, und jeder andere Bewerber fällt sofort auf den nächsten Kandidaten zurück. Erst nach diesem Erfolg weist der Claiming-Schritt das Issue zu und dreht das Status-Label um — das Label selbst ist also nie das, worum zwei Agenten wettlaufen könnten.
Labels als Zustandsautomat
Jedes Issue durchläuft eine explizite Label-Abfolge — ready, claimed, blocked —, und jeder PR trägt sein eigenes Reviewer-Verdikt als Label. Ein Agent handelt ausschließlich auf Basis des Zustands, den er in einem Label geschrieben sieht; nichts wird aus Timing oder der Erinnerung an einen vorherigen Turn abgeleitet. Das bedeutet auch: Jeder Agent — auch einer, der gerade völlig ohne Vorkontext gestartet ist — kann an Issue oder PR ablesen, in welcher Phase es sich befindet und was als Nächstes erlaubt ist.
Ein Claim gleichzeitig, auch für Subagenten
Eine einzelne Agenten-Identität hält höchstens ein beanspruchtes Issue gleichzeitig, damit die Warteschlange nicht dadurch ausgehöhlt wird, dass ein Agent Arbeit hortet, während andere untätig sind. Ein Agenten-Harness darf innerhalb dieser einen beanspruchten Aufgabe trotzdem Subagenten für Recherche oder parallele Exploration starten — nur die oberste Agenten-Instanz darf jedoch GitHub-Zustand verändern (claimen, pushen, den PR öffnen, Review-Labels setzen). Das hält eng und nachvollziehbar, wer Koordinationszustand mutieren darf, selbst wenn die Arbeit darunter hochgradig parallel ist.
Review & Sicherheit
Agenten die Arbeit ihres eigenen Teams mergen zu lassen, braucht Leitplanken, die sich nicht auf das Urteilsvermögen eines einzelnen Agenten verlassen:
Kein Agent genehmigt die eigene Arbeit
Jede Session — ob sie Code schreibt oder reviewt — authentifiziert sich als dasselbe Konto, und Plattformen verbieten zu Recht, den eigenen Pull Request zu genehmigen. Ein Reviewer-Agent gibt sein Verdikt daher zunächst als reinen Review-Kommentar ab; erst eine separate, eng begrenzte, schlüssellose Automation kann ein zustimmendes Verdikt in eine echte, Branch-Protection-erfüllende Genehmigung verwandeln. Jeder neue Push auf den PR macht diese Genehmigung sofort ungültig, sodass ein überarbeiteter PR stets ein frisches Reviewer-Verdikt braucht — ein Agent kann keine späte Änderung heimlich am bereits erfolgten Review vorbeischleusen.
Auto-Merge bei Grün, nicht aus Vertrauen
Ein PR mergt automatisch genau dann — und nur dann —, wenn ein zustimmendes Reviewer-Verdikt vorliegt und jeder erforderliche CI-Check (Lint, Type-Check, Tests, Build sowie jede domänenspezifische Validierung) grün ist. Keine der beiden Bedingungen reicht allein; ein grüner Build ohne Review blockiert den Merge genauso wie eine Genehmigung bei roter CI.
Nur für Menschen zugängliche Pfade
Manche Bereiche erhalten grundsätzlich nie eine von einem Agenten ausgestellte Genehmigung: die CI/CD-Workflow-Definitionen selbst, Datenbankmigrationen, die Auth oder Row-Level-Security betreffen, sowie alles, was mit echten Credentials umgeht. Das wird strukturell erzwungen (Code-Ownership-Regeln), nicht dadurch, dass man einen Agenten bittet, vorsichtig zu sein.
Eskalation statt Weiterwursteln
Durchläuft ein Pull Request zwei Runden angeforderter Änderungen, ohne zu konvergieren, versucht der Loop nicht weiter, ihn zu erzwingen, sondern übergibt die Entscheidung an einen Menschen — eine festgefahrene Uneinigkeit zwischen Agenten ist ein Signal zur Eskalation, kein Rätsel, das autonom weitergelöst werden muss.
Fallstudie: Codewright
Codewright — eine kuratierte, risikoklassifizierte Wissensdatenbank mit Terminal-Rezepten für Entwickler und Coding-Agenten, ausgeliefert über eine Website, eine öffentliche API, einen MCP-Server und einen Agent-Skill — ist mein klarstes Beispiel dafür, dass dieser Loop tatsächlich läuft und nicht nur als Demo existiert. Es ist Pre-Alpha und wird bewusst von einem autonomen Multi-Agenten-Entwicklungsloop gebaut, mit mir im Loop als Owner statt als demjenigen, der jede Zeile selbst schreibt.
In der Praxis sieht das so aus:
- Ein Planner-Agent hält jederzeit 5–15 gut abgegrenzte, bereite Issues vor, jedes mit klaren Abnahmekriterien und den passenden Bereichs- und Prioritäts-Labels.
- Worker-Agenten — mal mehrere gleichzeitig, mal eine einzelne, sich selbst taktende Session, die immer wieder das nächste bereite Issue beansprucht — liefern jeweils einen Pull Request pro Issue gegen die Projektspezifikationen (ein Rezept-Schema, ein Architekturdokument, einen Style Guide).
- Reviewer-Agenten, stets eine andere Instanz als die, die den Code geschrieben hat, prüfen jeden PR gegen sein Issue und dieselben Spezifikationen, bevor er mergen darf.
- Ein stündlicher, schlüsselloser GitHub-Actions-Job — ohne Modellaufrufe, ohne Kosten — übernimmt die Rolle des Janitors: gibt seit drei Stunden unangetastete Claims frei und stößt Pull Requests an, die einen Tag lang untätig waren.
Um diese Flotte tatsächlich zu betreiben, habe ich eine native macOS-App gebaut, Codewright Agents: eine Kommandozentrale zum Starten mehrerer gleichzeitiger Worker-, Reviewer- und Planner-Sessions über Claude Code, Codex und OpenCode, jede in ihrem eigenen isolierten Workspace, wobei jedes Issue, jeder PR, jedes Review und jeder Commit einer Session auf diesen Lauf zurückverfolgt wird. Sie hat keine Container-Schicht — Sessions laufen als native Host-Prozesse — und begann als eigenständiges Repository, bevor ich sie nach ihrer Stabilisierung ins Codewright-Monorepo überführt habe.
Ich entscheide, wann Agenten gestartet werden und in welcher Mischung — eine lokale CLI-Session, ein sich selbst taktender Loop, der die Warteschlange bis zur Leere abarbeitet, eine Cloud-Session oder ein geplanter Start alle 15–20 Minuten —, aber welches konkrete Stück Arbeit als Nächstes aufgegriffen, umgesetzt und gemergt wird, ergibt sich aus dem Protokoll, nicht daraus, dass ich eine Aufgabenliste mikromanage. Meine eigene Aufgabe verschiebt sich vom Tippen jeder Zeile hin zum Schreiben von Spezifikationen, die präzise genug sind, damit Agenten korrekt bauen können, und dazu, genau für die Entscheidungen der Mensch im Loop zu sein, die das Protokoll einem Menschen vorbehält: Infrastruktur-Secrets, Produktentscheidungen und alles, was zwei Review-Runden nicht selbst lösen konnten.