Open-source špecifikácia pre orchestráciu Codex: Symphony
Autori: Alex Kotliarskyi, Victor Zhu a Zach Brock
Pred šiestimi mesiacmi náš tím pri práci na internom nástroji produktivity urobil kontroverzné (v tom čase) rozhodnutie: náš repo zitár postavíme bez kódu napísaného človekom. Každý riadok v našom projektovom repozitári musel byť vygenerovaný Codexom.
Aby to fungovalo, od základov sme prepracovali náš inžiniersky workflow. Vybudovali sme repozitár priateľský k agentom, výrazne investovali do automatizovaných testov a guardrailov a ku Codex sme pristupovali ako k plnohodnotnému spoluhráčovi. Túto cestu sme zdokumentovali v našom predchádzajúcom blogovom príspevku o harness engineeringu.
Fungovalo to, ale potom sme narazili na ďalšie úzke hrdlo: prepínanie kontextu.
Aby sme tento nový problém vyriešili, vytvorili sme systém s názvom Symphony. Symphony(otvorí sa v novom okne) je orchestrátor agentov, ktorý z projektovej tabule, ako je Linear, robí riadiacu rovinu pre agentov na písanie kódu. Každá otvorená úloha dostane agenta, agenti bežia nepretržite a ľudia kontrolujú výsledky.
Tento príspevok vysvetľuje, ako sme Symphony vytvorili — čo viedlo v niektorých tímoch k 500 % nárastu zlúčených žiadostí o zlúčenie — a ako ho použiť na premenu vlastného sledovača problémov na stále zapnutý orchestrátor agentov.
Strop interaktívnych agentov na písanie kódu
Aj keď sa ich používanie zjednodušuje, agenti na písanie kódu — či už cez webové aplikácie alebo CLI — sú stále interaktívne nástroje.
Keď sa rozsah agentickej práce v OpenAI zväčšoval, narazili sme na nový typ záťaže. Každý inžinier otvoril niekoľko relácií Codex, priradil úlohy, skontroloval výstup, navigoval agenta a opakoval to. V praxi väčšina ľudí dokázala pohodlne spravovať tri až päť relácií naraz, kým sa prepínanie kontextu nestalo bolestivé. Nad touto hranicou produktivita klesala. Zabúdali sme, ktorá relácia čo robí, preskakovali medzi terminálmi, aby sme agentov jemne nasmerovali späť na správnu cestu, a ladili dlhobežné úlohy, ktoré sa v polovici zasekli.
Agenti boli rýchli, ale mali sme systémové úzke hrdlo: ľudskú pozornosť. V podstate sme si vybudovali tím mimoriadne schopných juniorných inžinierov a potom našim ľudským inžinierom pridelili úlohu mikromanažovať ich. To sa nedalo škálovať.
Zmena perspektívy
Uvedomili sme si, že optimalizujeme nesprávnu vec. Náš systém sme orientovali okolo coding sessions a zlúčených PR, pričom PR a relácie sú v skutočnosti len prostriedkom k cieľu. Softvérové workflowy sú vo veľkej miere organizované okolo výstupov: issue, úloh, tiketov, míľnikov.
Položili sme si teda otázku, čo by sa stalo, keby sme prestali na agentov dohliadať priamo a namiesto toho im dovolili ťahať si prácu z nášho task trackeru.
Z tejto myšlienky vznikla Symphony, písaná špecifikácia, ktorá funguje ako supervízor na orchestráciu agentickej práce.
Premena nášho issue trackeru na orchestrátor agentov
Symphony začala jednoduchým konceptom: každú otvorenú úlohu by mal prevziať a dokončiť agent. Namiesto spravovania relácií Codex vo viacerých kartách sme z nášho issue trackeru urobili riadiacu rovinu.
V tomto nastavení sa každý otvorený tiket v Linear mapuje na vyhradený pracovný priestor agenta. Symphony nepretržite sleduje tabuľu úloh a zabezpečuje, aby každá aktívna úloha mala v slučke spusteného agenta, kým nebude hotová. Ak agent spadne alebo sa zasekne, Symphony ho reštartuje. Ak sa objaví nová práca, Symphony ju prevezme a začne organizovať prácu.
Náš workflow sme postavili na stavoch tiketov, pričom sme správcu úloh Linear používali ako stavový automat.
V praxi Symphony odpája prácu od relácií aj od žiadostí o zlúčenie. Niektoré issue vedú k viacerým PR naprieč repozitármi, iné sú čisto investigatívne alebo analytické a nikdy sa nedotknú kódovej základne.
Keď je práca takto abstrahovaná, tikety môžu predstavovať oveľa väčšie jednotky práce.
Symphony pravidelne používame na orchestráciu komplexných funkcií a migrácií infraštruktúry. Môžeme napríklad zadať úlohu, v ktorej agenta požiadame, aby analyzoval kódovú základňu, Slack alebo Notion a vytvoril implementačný plán. Keď sme s plánom spokojní, agent vygeneruje strom úloh, rozdelí prácu do etáp a určí závislosti medzi úlohami.
Agenti začínajú pracovať len na úlohách, ktoré nie sú blokované, takže vykonávanie sa pre tento DAG (sekvenciu vykonávacích krokov) prirodzene a optimálne rozvíja paralelne. V príklade nižšie sme označili aktualizáciu Reactu ako blokovanú migráciou na Vite. Podľa očakávania začali agenti aktualizovať React až po dokončení migrácie na Vite.
Agenti si môžu prácu vytvárať aj sami. Počas implementácie alebo review si často všimnú zlepšenia, ktoré nespadajú do rozsahu aktuálnej úlohy: problém s výkonom, príležitosť na refaktoring alebo lepšiu architektúru. Keď sa to stane, jednoducho vytvoria novú issue, ktorú môžeme vyhodnotiť a naplánovať neskôr — mnohé z týchto nadväzujúcich úloh si tiež prevezmú agenti. Hoci nad týmto procesom dohliadame, agenti zostávajú organizovaní a posúvajú prácu dopredu.
Tento spôsob práce dramaticky znižuje kognitívne náklady na spustenie nejednoznačnej práce. Ak agent niečo urobí zle, je to stále užitočná informácia a náklady pre nás sú takmer nulové. Môžeme veľmi lacno vytvárať tikety, aby agent šiel prototypovať a skúmať, a zahodiť všetky experimenty, ktoré sa nám nepáčia.
Keďže orchestrátor beží na devboxoch a nikdy nespí, môžeme pridávať úlohy odkiaľkoľvek a vedieť, že si ich agent prevezme. Napríklad jeden inžinier z nášho tímu urobil tri významné zmeny v aplikácii Linear na svojom telefóne z útulnej chaty so slabou wifi.
Nárast explorácie pri takomto spôsobe práce
Pri pozorovaní účinkov práce so Symphony bola najzjavnejšou zmenou produkcia. V niektorých tímoch v OpenAI sme v prvých troch týždňoch videli 6-násobný nárast počtu zlúčených PR. Mimo OpenAI zakladateľ spoločnosti Linear Karri Saarinen upozornil na nárast vytvorených pracovných priestorov(otvorí sa v novom okne) po tom, ako sme Symphony vydali. Hlbšia zmena sa však týka toho, ako tímy premýšľajú o práci.
Keď naši inžinieri už netrávia čas dohľadom nad reláciami Codex, ekonomika zmien v kóde sa úplne mení. Vnímané náklady na každú zmenu klesajú, pretože už neinvestujeme ľudské úsilie do samotného riadenia implementácie.
To zmenilo naše správanie. V Symphony je teraz triviálne rozbehnúť špekulatívne úlohy. Vyskúšajte nápad, preskúmajte refaktoring, otestujte hypotézu a ponechajte si len výsledky, ktoré vyzerajú sľubne.
Zároveň to rozširuje okruh ľudí, ktorí môžu iniciovať prácu. Náš produktový manažér a dizajnér teraz môžu zadávať požiadavky na funkcie priamo do Symphony. Nemusia si checkoutovať repozitár ani spravovať reláciu Codex. Opíšu funkciu a dostanú späť balík na review, ktorý zahŕňa videoprehliadku fungujúcej funkcie v reálnom produkte.
Symphony vyniká aj vo veľkých monorepozitároch (ako ten, ktorý máme v OpenAI), kde je posledná míľa pri zlúčení PR pomalá a krehká. Systém sleduje CI, podľa potreby robí rebase, rieši konflikty, opakuje flaky kontroly a vo všeobecnosti prevádza zmeny potrubím. Keď tiket dosiahne stav Merging, máme vysokú istotu, že sa zmena dostane do hlavnej vetvy bez ľudského stráženia.
Po implementácii Symphony delegujeme viac práce na agentov a sústreďujeme sa na náročnejšie, viac prieskumné úlohy.
Pokrok prináša nové, odlišné problémy
Prevádzka na tejto úrovni prináša kompromisy. Keď sme prešli od interaktívneho navigovania agentov k zadávaniu práce na úrovni tiketov, stratili sme schopnosť ich priebežne postrkovať počas letu a podľa potreby korigovať smer. Niekedy agent vytvoril niečo, čo úplne minulo cieľ. Bolo to užitočné — tieto zlyhania odhalili medzery v systéme a pomohli nám urobiť ho robustnejším.
Namiesto ručného opravovania výsledku sme pridali guardraily a zručnosti, aby agenti nabudúce uspeli. Časom nás to viedlo k pridaniu nových schopností do nášho harnessu, napríklad spúšťania end-to-end testov, ovládania aplikácie cez Chrome DevTools a správy QA smoke testov. Výrazne sme zlepšili našu dokumentáciu a spresnili, ako vyzerá dobrý výsledok.
Nie každá úloha sa hodí na štýl práce Symphony. Niektoré problémy si stále vyžadujú inžinierov, ktorí pracujú priamo s interaktívnymi reláciami Codex, najmä nejednoznačné problémy alebo práca, ktorá si vyžaduje silný úsudok a expertízu. V praxi sú to zvyčajne najzaujímavejšie a najpríjemnejšie úlohy, ktorým sa naši inžinieri venujú.
Rozdiel je v tom, že Symphony dokáže zvládnuť väčšinu rutinnej implementačnej práce. To umožňuje inžinierom sústrediť sa naraz na jeden ťažký problém namiesto neustáleho prepínania kontextu medzi menšími úlohami.
Tiež sme sa naučili, že zaobchádzať s agentmi ako s rigidnými uzlami v stavovom automate nefunguje dobre. Modely sú čoraz inteligentnejšie a dokážu riešiť väčšie problémy, než je škatuľka, do ktorej sa ich snažíme vmestiť. Napríklad v skorých verziách boli všetky integrácie s GitHubom súčasťou vonkajšieho harnessu — napríklad skoré verzie očakávali, že Codex bude robiť len zmeny v kóde, zatiaľ čo zvyšok procesu (odosielanie zmien, spúšťanie testov) bol špecifikovaný v kóde. V našich skorých verziách agentickej práce sme Codex žiadali len o implementáciu úlohy. Tento prístup sa ukázal ako príliš obmedzujúci. Codex je úplne schopný vytvárať viacero PR, čítať spätnú väzbu z review a reagovať na ňu. Preto sme mu dali nástroje — CLI gh, zručnosti na čítanie logov CI atď. — a teraz môžeme Codex požiadať, aby robil viac, napríklad zatváral staré PR alebo pripravoval reporty o dokončenej vs. opustenej práci. Tieto typy úloh boli ďaleko za hranicou pôvodného rámca implementácie funkcií.
Napokon sme sa teda posunuli smerom k tomu, že agentom dávame ciele namiesto prísnych prechodov, podobne ako dobrý manažér zadáva cieľ priamo podriadenému vo svojom tíme. Sila modelov vychádza z ich schopnosti uvažovať, takže im dajte nástroje a kontext a nechajte ich pracovať.
Používanie Symphony na tvorbu Symphony
Keď otvoríte repozitár Symphony, prvé, čo si všimnete, je, že Symphony je technicky len súbor SPEC.md — definícia problému a zamýšľaného riešenia. Namiesto budovania komplexného dohliadacieho systému sme definovali problém a zamýšľané riešenia, čím sme agentom poskytli riadenie na vysokej úrovni.
Referenčná implementácia je napísaná v Elixire — pretože keď je kód prakticky zadarmo, konečne si môžete vyberať jazyky podľa ich silných stránok, ako je napríklad súbežnosť v Elixire — no základnú myšlienku možno vyjadriť v jednoduchom dokumente Markdown. Odporúčame vám nasmerovať svoj obľúbený agent na písanie kódu na špecifikáciu a nechať ho implementovať vlastnú verziu.
Prvá verzia Symphony bola len relácia Codex spustená v tmux, ktorá pollovala Linear a pre nové úlohy spúšťala subagentov. Fungovalo to, ale nebolo to obzvlášť spoľahlivé. Druhá verzia žila v našom hlavnom projektovom repozitári, ktorý bol vytvorený s ohľadom na agentov. Už predtým sme vytvorili agent harness, aby agentom poskytoval zručnosti a kontext na vykonávanie kvalitnej práce v tomto repozitári, takže Symphony to všetko jednoducho prepája.
Keď už existovala základná funkcionalita, použili sme Symphony na vytvorenie Symphony.
Keď sme interne demonštrovali systém, ktorý spravuje úlohy a pripája k nim video ako dôkaz vykonanej práce, reakcia bola mimoriadne pozitívna: náš projektový kanál Symphony rástol a tímy naprieč organizáciou ho začali prirodzene používať. Interný product-market fit je v OpenAI predpokladom externého spustenia. Na základe používania, ktoré sme videli v OpenAI, bolo jasné, že by sme mali Symphony zdieľať aj mimo firmy.
Preto sme túto myšlienku vyčlenili do samostatného súboru SPEC.md a požiadali Codex, aby ju implementoval. Pre referenčnú implementáciu sme zvolili Elixir, relatívne okrajový jazyk s vynikajúcimi primitívami na orchestráciu a dohľad nad súbežnými procesmi. Codex vytvoril implementáciu v Elixire na prvý pokus a odvtedy sme ďalej iterovali na špecifikácii aj implementácii. Aby sme špecifikáciu doladili, dokonca sme Codex požiadali, aby ju implementoval v niekoľkých ďalších jazykoch — TypeScript, Go, Rust, Java, Python — a výsledky použil na identifikáciu nejednoznačností a zjednodušenie systému. Uspel v každom jazyku.
Počas procesu budovania Codex sme odstránili veľa náhodnej zložitosti, napríklad závislosti od konkrétnych repozitárov alebo od Linear MCP. Symphony už nezávisí od našich interných repozitárov ani workflowov. Základný prístup sa zjednodušil na toto:
Pre každú otvorenú úlohu zabezpečte, aby vo vlastnom pracovnom priestore bežal agent.
Okrem pomoci s aktívnou prácou je teraz vývojový workflow niečím, čo agenti poznajú a dodržiavajú. Vývojový workflow — pracovať na issue, checkoutnuť repozitár, označiť ju ako in progress, aby PM vedel, že sa na nej pracuje, pridať PR, presunúť ju do stavu Review, pripojiť videá atď. — je teraz zachytený v jednoduchom súbore WORKFLOW.md. Toto všetko bol proces, ktorý ľudia dodržiavali, ale nikdy nebol zdokumentovaný. Namiesto spoliehania sa na tento implicitný súbor krokov ho teraz dokumentujeme a Symphony zabezpečuje, aby sa ním agenti riadili. To nám umožňuje budovať agentov, ktorí pracujú po našom boku. Ak sa rozhodneme, že agenti by mali k dokončenej práci pripájať aj sebareflexiu, pridáme to do WORKFLOW.md a Symphony agentov navedie aj na tento krok.
Zároveň sme mohli používať Codex v režime app server(otvorí sa v novom okne), vstavanom bezhlavom režime pre Codex. Tento režim nám umožnil spúšťať Codex a komunikovať s ním programovo cez dobre zdokumentované JSON-RPC API na veci, ako je spustenie vlákna alebo reakcia na jednotlivé ťahy. Je to oveľa pohodlnejší a škálovateľnejší spôsob než snaha komunikovať s Codex cez CLI alebo živé relácie tmux.
Codex App Server sa pre náš prípad použitia perfektne hodil: využívame harness, ktorý Codex poskytuje, a zároveň máme ovládacie prvky a hooky na napojenie. Napríklad, aby sme subagentom nevystavili prístupový token k Linear, používame dynamické volania nástrojov(otvorí sa v novom okne) na vystavenie surovej funkcie linear_graphql, ktorá vykonáva ľubovoľné požiadavky voči Linear, bez spoliehania sa na MCP alebo vystavenia prístupového tokenu kontajnerom.
Čo ďalej
Symphony je zámerne minimálna orchestračná vrstva. Sprístupňujeme ju ako open source, aby sme demonštrovali silu Codex App Servera v spojení s rôznymi workflow nástrojmi, ako je Linear. Preto neplánujeme Symphony udržiavať ako samostatný produkt. Berte ju ako referenčnú implementáciu. Podobne ako mnohí vývojári nasmerovali svojich agentov na písanie kódu na príspevok o harness engineeringu, aby si vygenerovali kostru svojich repozitárov, dúfame, že nasmerujete svojho obľúbeného agenta na písanie kódu na špecifikáciu(otvorí sa v novom okne) a repozitár(otvorí sa v novom okne) Symphony a vytvoríte si vlastné verzie prispôsobené vašim prostrediam.
Sila pochádza z Codex a jeho app servera. Symphony bola spôsob, ako prepojiť Codex s Linear, dve veci, ktoré sme už používali, aby sme vyriešili problém riadenia práce. Ako sa agenti na písanie kódu budú zlepšovať v uvažovaní a dodržiavaní pokynov, predpokladáme, že úzke hrdlo sa aj v iných firmách posunie od písania kódu smerom k riadeniu agentickej práce. Vzrušujúce je, že bariéra na experimentovanie s týmito systémami agentov na písanie kódu je teraz prekvapivo nízka. Veci môžete jednoducho vytvárať s Codex.
Ohlasy komunity
S radosťou sledujeme, ako inžinierska komunita používa Symphony v týždňoch od vydania; k 23. aprílu získala už viac než 15-tisíc hviezdičiek na GitHube(otvorí sa v novom okne).