Eine Open-Source-Spezifikation für Codex-Orchestrierung: Symphony
Von Alex Kotliarskyi, Victor Zhu und Zach Brock
Vor sechs Monaten traf unser Team bei der Arbeit an einem internen Produktivitätstool eine damals umstrittene Entscheidung: Wir würden unser Repository ohne von Menschen geschriebenen Code bauen. Jede Zeile in unserem Projekt-Repository musste von Codex generiert werden.
Damit das funktioniert, haben wir unseren Entwicklungs-Workflow von Grund auf neu gestaltet. Wir bauten ein agentenfreundliches Repository, investierten stark in automatisierte Tests und Schutzmaßnahmen und behandelten Codex wie ein vollwertiges Teammitglied. Diese Reise haben wir in unserem vorherigen Blogbeitrag über Harness Engineering dokumentiert.
Und es funktionierte, aber dann stießen wir auf den nächsten Engpass: Kontextwechsel.
Um dieses neue Problem zu lösen, bauten wir ein System namens Symphony. Symphony(wird in einem neuen Fenster geöffnet) ist ein Agenten-Orchestrator, der ein Projektmanagement-Board wie Linear in eine Steuerungsebene für Programmier-Agenten verwandelt. Jede offene Aufgabe bekommt einen Agenten, Agenten laufen kontinuierlich, und Menschen prüfen die Ergebnisse.
Dieser Beitrag erklärt, wie wir Symphony entwickelt haben – was in manchen Teams zu 500 % mehr gemergten Pull Requests führte – und wie du es nutzen kannst, um deine eigenen Issue-Tracker in einen ständig aktiven Agenten-Orchestrator zu verwandeln.
Die Grenze interaktiver Programmier-Agenten
Auch wenn sie immer einfacher zu nutzen sind, sind Programmier-Agenten – ob über Web-Apps oder CLI – weiterhin interaktive Werkzeuge.
Als der Umfang agentischer Arbeit bei OpenAI zunahm, stellten wir eine neue Art von Belastung fest. Jede:r Entwickler:in öffnete einige Codex-Sitzungen, wies Aufgaben zu, prüfte die Ausgabe, steuerte den Agenten und wiederholte das Ganze. In der Praxis konnten die meisten drei bis fünf Sitzungen gleichzeitig gut handhaben, bevor der Kontextwechsel schmerzhaft wurde. Darüber hinaus sank die Produktivität. Wir vergaßen, welche Sitzung was machte, sprangen zwischen Terminals hin und her, um Agenten wieder auf Kurs zu bringen, und debuggten lang laufende Aufgaben, die auf halbem Weg stecken blieben.
Die Agenten waren schnell, aber wir hatten einen Systemengpass: menschliche Aufmerksamkeit. Wir hatten faktisch ein Team aus extrem fähigen unerfahrenen Entwickler:innen aufgebaut und dann unsere menschlichen Entwickler:innen damit beauftragt, sie mikrozumanagen. Das ließ sich nicht skalieren.
Ein Perspektivwechsel
Uns wurde klar, dass wir das Falsche optimierten. Wir richteten unser System an Programmiersitzungen und gemergten PRs aus, obwohl PRs und Sitzungen in Wirklichkeit nur Mittel zum Zweck sind. Software-Workflows sind größtenteils um Lieferobjekte organisiert: Issues, Aufgaben, Tickets, Meilensteine.
Also fragten wir uns, was passieren würde, wenn wir Agenten nicht mehr direkt beaufsichtigen, sondern sie stattdessen Arbeit aus unserem Task-Tracker ziehen lassen.
Diese Idee wurde zu Symphony, einer geschriebenen Spezifikation, die als Supervisor fungiert, um agentische Arbeit zu orchestrieren.
Unseren Issue-Tracker in einen Agenten-Orchestrator verwandeln
Symphony begann mit einem einfachen Konzept: Jede offene Aufgabe sollte von einem Agenten übernommen und abgeschlossen werden. Anstatt Codex-Sitzungen in mehreren Tabs zu verwalten, machten wir unseren Issue-Tracker zur Steuerungsebene.
In diesem Setup wird jedes offene Linear-Issue einem dedizierten Agenten-Workspace zugeordnet. Symphony überwacht kontinuierlich das Aufgaben-Board und stellt sicher, dass für jede aktive Aufgabe ein Agent in der Schleife läuft, bis sie abgeschlossen ist. Wenn ein Agent abstürzt oder hängen bleibt, startet Symphony ihn neu. Wenn neue Arbeit auftaucht, greift Symphony sie auf und beginnt, die Arbeit zu organisieren.
Wir haben unseren Workflow auf Ticket-Status aufgebaut und den Aufgabenmanager Linear als Zustandsmaschine genutzt.
In der Praxis entkoppelt Symphony Arbeit von Sitzungen und von Pull Requests. Manche Issues erzeugen mehrere PRs über Repositorys hinweg; andere sind reine Untersuchungs- oder Analysearbeit und berühren die Codebasis nie.
Sobald Arbeit auf diese Weise abstrahiert ist, können Tickets deutlich größere Arbeitseinheiten darstellen.
Wir nutzen Symphony regelmäßig, um komplexe Features und Infrastrukturmigrationen zu orchestrieren. Zum Beispiel können wir eine Aufgabe erstellen, in der der Agent aufgefordert wird, die Codebasis, Slack oder Notion zu analysieren und einen Implementierungsplan zu erstellen. Sobald wir mit dem Plan zufrieden sind, erzeugt der Agent einen Aufgabenbaum, unterteilt die Arbeit in Phasen und definiert Abhängigkeiten zwischen den Aufgaben.
Agenten beginnen nur mit Aufgaben, die nicht blockiert sind, sodass die Ausführung für diesen DAG (eine Folge von Ausführungsschritten) auf natürliche und optimale Weise parallel abläuft. Im Beispiel unten haben wir das React-Upgrade als durch eine Migration zu Vite blockiert markiert. Wie erwartet begannen Agenten erst dann mit dem Upgrade von React, nachdem die Migration zu Vite abgeschlossen war.
Agenten können auch selbst Arbeit erzeugen. Während der Implementierung oder Prüfung bemerken sie oft Verbesserungen, die außerhalb des Umfangs der aktuellen Aufgabe liegen: ein Performance-Problem, eine Refactoring-Möglichkeit oder eine bessere Architektur. Wenn das passiert, erstellen sie einfach ein neues Issue, das wir später bewerten und einplanen können – viele dieser Folgeaufgaben werden ebenfalls von Agenten übernommen. Während wir diesen Prozess überblicken, bleiben Agenten organisiert und halten die Arbeit am Laufen.
Diese Arbeitsweise reduziert die kognitiven Kosten, mehrdeutige Arbeit anzustoßen, drastisch. Wenn der Agent etwas falsch macht, ist das immer noch nützliche Information, und die Kosten für uns sind nahezu null. Wir können sehr günstig Tickets erstellen, damit der Agent Prototypen baut und exploriert, und alle Erkundungen verwerfen, die uns nicht gefallen.
Weil der Orchestrator auf Devboxen läuft und nie schläft, können wir von überall Aufgaben hinzufügen und wissen, dass ein Agent sie übernehmen wird. So hat zum Beispiel ein Entwickler in unserem Team drei wichtige Änderungen über die Linear-App auf seinem Handy vorgenommen – aus einer gemütlichen Hütte mit unzuverlässigem WLAN.
Mehr Exploration durch diese Arbeitsweise
Als wir die Auswirkungen der Arbeit mit Symphony beobachteten, war die offensichtlichste Veränderung der Output. In einigen Teams bei OpenAI sahen wir in den ersten drei Wochen einen Anstieg der gemergten PRs um das Sechsfache. Außerhalb von OpenAI hob der Linear-Gründer Karri Saarinen einen Anstieg der erstellten Workspaces(wird in einem neuen Fenster geöffnet) hervor, als wir Symphony veröffentlichten. Die tiefere Veränderung betrifft jedoch die Art und Weise, wie Teams über Arbeit nachdenken.
Wenn unsere Entwickler:innen keine Zeit mehr damit verbringen, Codex-Sitzungen zu beaufsichtigen, verändert das die Ökonomie von Codeänderungen vollständig. Die wahrgenommenen Kosten jeder Änderung sinken, weil wir keine menschliche Arbeit mehr in die eigentliche Umsetzung investieren.
Das hat unser Verhalten verändert. Es ist in Symphony trivial geworden, spekulative Aufgaben anzustoßen. Probiere eine Idee aus, erkunde ein Refactoring, teste eine Hypothese und behalte nur die Ergebnisse, die vielversprechend aussehen.
Es erweitert auch den Kreis der Personen, die Arbeit initiieren können. Unsere Produktmanager:in und Designer:in können jetzt Feature-Anfragen direkt in Symphony einstellen. Sie müssen weder das Repository auschecken noch eine Codex-Sitzung verwalten. Sie beschreiben das Feature und erhalten ein Review-Paket zurück, das eine Video-Tour des Features im echten Produkt enthält.
Symphony glänzt auch in großen Monorepositorys (wie dem, das wir bei OpenAI haben), in denen der letzte Schritt bis zum Mergen einer PR langsam und anfällig ist. Das System überwacht CI, erstellt bei Bedarf eine neue Basis, löst Konflikte, wiederholt fehleranfällige Checks und begleitet Änderungen generell durch die Pipeline. Bis ein Ticket den Status Merging erreicht, sind wir sehr zuversichtlich, dass die Änderung es ohne menschliches Babysitting in den Main-Branch schafft.
Fortschritt bringt neue, andere Probleme mit sich
Auf diesem Niveau zu arbeiten bringt Abwägungen mit sich. Als wir von der interaktiven Steuerung von Agenten dazu übergingen, ihnen Arbeit auf Ticket-Ebene zuzuweisen, verloren wir die Möglichkeit, sie während der Ausführung ständig anzustupsen und bei Bedarf nachzusteuern. Manchmal produzierte der Agent etwas, das das Ziel komplett verfehlte. Das war nützlich – diese Fehlschläge zeigten Lücken im System auf und halfen uns, es robuster zu machen.
Anstatt das Ergebnis manuell zu flicken, fügten wir Schutzmaßnahmen und Fähigkeiten hinzu, damit die Agenten beim nächsten Mal erfolgreich sein konnten. Mit der Zeit führte uns das dazu, unserem Harness neue Fähigkeiten hinzuzufügen, etwa End-to-End-Tests auszuführen, die App über Chrome DevTools zu steuern und QA-Smoke-Tests zu verwalten. Wir haben unsere Dokumentation deutlich verbessert und präzisiert, wie gute Ergebnisse aussehen.
Nicht jede Aufgabe passt zum Symphony-Arbeitsstil. Manche Probleme erfordern weiterhin Entwickler:innen, die direkt mit interaktiven Codex-Sitzungen arbeiten, insbesondere mehrdeutige Probleme oder Arbeit, die starkes Urteilsvermögen und Fachwissen verlangt. In der Praxis sind das meist die interessantesten und angenehmsten Aufgaben, mit denen unsere Entwickler:innen ihre Zeit verbringen.
Der Unterschied ist, dass Symphony den Großteil der routinemäßigen Implementierungsarbeit übernehmen kann. Dadurch können sich Entwickler:innen jeweils auf ein einziges schwieriges Problem konzentrieren, statt ständig zwischen kleineren Aufgaben den Kontext zu wechseln.
Wir haben außerdem gelernt, dass es nicht gut funktioniert, Agenten als starre Nodes in einer Zustandsmaschine zu behandeln. Modelle werden intelligenter und können größere Probleme lösen als die Schublade, in die wir sie stecken wollen. In frühen Versionen waren zum Beispiel alle GitHub-Integrationen Teil des äußeren Harness – frühe Versionen erwarteten etwa, dass Codex nur Codeänderungen vornimmt, während der Rest des Prozesses (Änderungen einreichen, Tests ausführen) im Code festgelegt wurde. In unseren frühen Versionen agentischer Arbeit baten wir Codex nur darum, die Aufgabe zu implementieren. Dieser Ansatz erwies sich als zu einschränkend. Codex ist durchaus in der Lage, mehrere PRs zu erstellen, Review-Feedback zu lesen und darauf einzugehen. Also gaben wir ihm Tools – gh-CLI, Fähigkeiten zum Lesen von CI-Logs usw. – und jetzt können wir Codex um mehr bitten, etwa alte PRs zu schließen oder Berichte über abgeschlossene vs. aufgegebene Arbeit zu erstellen. Diese Arten von Aufgaben lagen weit außerhalb des ursprünglichen Rahmens der Feature-Implementierung.
Deshalb gingen wir schließlich dazu über, Agenten Ziele statt strikter Übergänge zu geben, ähnlich wie eine gute Führungskraft einer direkt unterstellten Person im Team ein Ziel zuweist. Die Stärke von Modellen kommt aus ihrer Fähigkeit zum Reasoning, also gib ihnen Werkzeuge und Kontext und lass sie machen.
Symphony nutzen, um Symphony zu bauen
Wenn du das Symphony-Repository öffnest, fällt dir als Erstes auf, dass Symphony technisch gesehen nur eine SPEC.md-Datei ist – eine Definition des Problems und der beabsichtigten Lösung. Anstatt ein komplexes Aufsichtssystem zu bauen, definierten wir das Problem und die vorgesehenen Lösungen und gaben Agenten damit Steuerung auf hoher Ebene.
Die Referenzimplementierung ist in Elixir geschrieben – denn wenn Code praktisch kostenlos ist, können Sprachen endlich nach ihren Stärken ausgewählt werden, etwa Elixirs Nebenläufigkeit – aber die Kernidee lässt sich in einem einfachen Markdown-Dokument ausdrücken. Wir empfehlen, deinen bevorzugten Programmier-Agenten auf die Spezifikation anzusetzen und eine eigene Version implementieren zu lassen.
Die erste Version von Symphony war nur eine Codex-Sitzung in tmux, die Linear abfragte und für neue Aufgaben Unteragenten startete. Das funktionierte, war aber nicht besonders zuverlässig. Die zweite Version lebte in unserem Haupt-Repository, das von Anfang an mit Blick auf Agenten gebaut wurde. Wir hatten die Agenten-Umgebung bereits aufgebaut, um Agenten in diesem Repository die nötigen Fähigkeiten und den passenden Kontext für hochwertige Arbeit zu geben, daher verbindet Symphony das einfach alles.
Sobald die Grundfunktionalität vorhanden war, nutzten wir Symphony, um Symphony zu bauen.
Als wir intern demonstrierten, wie das System Aufgaben verwaltet und sein Proof-of-Work-Video anhängt, war die Reaktion überwältigend positiv: Unser Symphony-Projektkanal wuchs, und Teams im ganzen Unternehmen begannen, es ganz von selbst zu nutzen. Interne Produkteignung ist bei OpenAI eine Voraussetzung für einen externen Launch. Auf Basis der Nutzung, die wir bei OpenAI gesehen haben, wurde klar, dass wir Symphony über die Unternehmensgrenzen hinaus teilen sollten.
Also erstellten wir anhand der Idee eine eigenständige SPEC.md und baten Codex, sie zu implementieren. Für die Referenzimplementierung wählten wir Elixir, eine vergleichsweise nischenhafte Sprache mit hervorragenden Grundbausteinen zum Orchestrieren und Überwachen nebenläufiger Prozesse. Codex baute die Elixir-Implementierung in einem Durchgang, und danach iterierten wir sowohl an der Spezifikation als auch an der Implementierung weiter. Um die Spezifikation zu verfeinern, baten wir Codex sogar, sie in mehreren anderen Sprachen zu implementieren – TypeScript, Go, Rust, Java, Python – und die Ergebnisse zu nutzen, um Mehrdeutigkeiten zu erkennen und das System zu vereinfachen. Das gelang in jeder Sprache.
Beim Aufbau von Codex entfernten wir viel beiläufige Komplexität, etwa Abhängigkeiten von bestimmten Repositorys oder vom Linear MCP. Symphony hängt nicht länger von unseren internen Repositorys oder Workflows ab. Der Kernansatz wurde einfach:
Stelle für jede offene Aufgabe sicher, dass ein Agent in seinem eigenen Workspace läuft.
Neben der Unterstützung bei der aktiven Arbeit ist der Entwicklungsworkflow jetzt etwas, das Agenten kennen und befolgen. Der Entwicklungsworkflow – an einem Issue arbeiten, ein Repository auschecken, es auf in Bearbeitung setzen, damit der:die Projektleiter:in weiß, dass daran gearbeitet wird, die PR hinzufügen, in den Status Review verschieben, Videos anhängen usw. – ist jetzt in einer einfachen WORKFLOW.md-Datei festgehalten. All das war ein Prozess, dem Menschen folgten, aber er war nie dokumentiert. Statt uns auf diese implizite Abfolge von Schritten zu verlassen, dokumentieren wir sie jetzt, und Symphony stellt sicher, dass Agenten ihr folgen. So können wir Agenten bauen, die mit uns zusammenarbeiten. Wenn wir entscheiden, dass Agenten abgeschlossener Arbeit auch eine Selbstreflexion anhängen sollen, fügen wir das der WORKFLOW.md hinzu, und Symphony führt die Agenten zu diesem Schritt.
Wir konnten Codex außerdem im App-Server-Modus(wird in einem neuen Fenster geöffnet) nutzen, einem integrierten Headless-Modus für Codex. Dieser Modus ermöglichte es uns, Codex auszuführen und über eine gut dokumentierte JSON-RPC-API programmatisch mit ihm zu kommunizieren, etwa um einen Thread zu starten oder auf Turns zu reagieren. Das ist viel bequemer und besser skalierbar, als zu versuchen, über CLI oder Live-tmux-Sitzungen mit Codex zu interagieren.
Codex App Server passte perfekt zu unserem Anwendungsfall: Wir profitieren von dem Harness, das Codex bereitstellt, und es hat gleichzeitig Integrationspunkte. Um zum Beispiel zu vermeiden, dass das Linear-Zugriffstoken Unteragenten offengelegt wird, verwenden wir dynamische Tool-Aufrufe(wird in einem neuen Fenster geöffnet), um die rohe Funktion linear_graphql bereitzustellen, die beliebige Requests gegen Linear ausführt, ohne sich auf MCP zu verlassen oder das Zugriffstoken Containern offenzulegen.
Was kommt als Nächstes?
Symphony ist eine bewusst minimale Orchestrierungsschicht. Wir veröffentlichen es als Open Source, um die Stärke von Codex App Server in Kombination mit verschiedenen Workflow-Tools wie Linear zu demonstrieren. Daher planen wir nicht, Symphony als eigenständiges Produkt weiter zu pflegen. Betrachte es als Referenzimplementierung. Ähnlich wie viele Entwickler:innen ihre Programmier-Agenten auf den Beitrag über Harness Engineering angesetzt haben, um ihre Repositorys zu stützen, hoffen wir, dass du deinen bevorzugten Programmier-Agenten auf die Symphony-Spezifikation(wird in einem neuen Fenster geöffnet) und das Repository(wird in einem neuen Fenster geöffnet) ansetzt, um eigene Versionen zu bauen, die auf deine Umgebungen zugeschnitten sind.
Die Stärke kommt von Codex und seinem App Server. Symphony war ein Weg, Codex mit Linear zu verbinden, zwei Dinge, die wir bereits nutzten, um das Problem des Arbeitsmanagements zu lösen. Wenn Programmier-Agenten besser im Reasoning werden und Anweisungen besser folgen, vermuten wir, dass sich der Engpass auch in anderen Unternehmen vom Schreiben von Code hin zum Management agentischer Arbeit verschieben wird. Der spannende Teil ist, dass die Hürde, mit diesen Programmier-Agent-Systemen zu experimentieren, inzwischen überraschend niedrig ist. Mit Codex können einfach Dinge entwickelt werden.
Ein Lob an die Community
Wir freuen uns sehr zu sehen, dass die Entwicklungs-Community Symphony in den Wochen seit der Veröffentlichung nutzt und bis zum 23. April bereits über 15.000 GitHub-Stars(wird in einem neuen Fenster geöffnet) vergeben hat.