Open-source specifikace pro orchestraci Codex: Symphony
Alex Kotliarskyi, Victor Zhu a Zach Brock
Před šesti měsíci se náš tým při práci na interním nástroji pro produktivitu rozhodl pro tehdy kontroverzní krok: vybudujeme naše úložiště bez jediného řádku kódu napsaného člověkem. Každý řádek v našem projektovém úložišti musel být vygenerován Codexem.
Aby to fungovalo, přepracovali jsme náš technologický postup od základů. Vybudovali jsme úložiště přívětivé pro agenty, výrazně investovali do automatizovaných testů a ochranný opatření a přistupovali ke Codex jako k plnohodnotnému kolegovi. Tuto cestu jsme zdokumentovali v našem předchozím blogovém příspěvku o efektivním využití práce technických týmů.
A fungovalo to, ale pak jsme narazili na další úzké hrdlo: přepínání kontextu.
Abychom tento nový problém vyřešili, vybudovali jsme systém nazvaný Symphony. Symphony(otevře se v novém okně) je orchestrátor agentů, který z projektového panelu, jako je Linear, dělá řídicí rovinu pro programovací agenty. Každý otevřený úkol dostane agenta, agenti běží nepřetržitě a lidé kontrolují výsledky.
Tento článek vysvětluje, jak jsme Symphony vytvořili (v některých týmech to vedlo k 500% nárůstu přijatých žádostí o přijetí změn) a jak ho použít k tomu, abyste i ze svého vlastního issue trackeru udělali stále aktivního orchestrátora agentů.
Strop interaktivních programovacích agentů
I když se používají stále snadněji, programovací agenti (ať už přes webové aplikace, nebo CLI) jsou stále interaktivní nástroje.
Jak se rozsah agentní práce v OpenAI zvětšoval, narazili jsme na nový typ zátěže. Každý vývojář otevřel několik relací Codexu, zadal úkoly, zkontroloval výstup, navedl agenta a vše opakoval. V praxi většina lidí dokázala pohodlně spravovat tři až pět relací najednou, než se přepínání kontextu stalo problémovým. Za touto hranicí produktivita klesala. Zapomínali jsme, která relace co dělá, přeskakovali mezi terminály, abychom agenty vrátili na správnou cestu, a ladili dlouho běžící úkoly, které se v půlce zasekly.
Agenti byli rychlí, ale měli jsme systémové úzké hrdlo: lidskou pozornost. Fakticky jsme vybudovali tým mimořádně schopných juniorních vývojářů a pak našim lidským inženýrům přidělili úkol je mikromanažovat. Nebylo možné to škálovat.
Změna perspektivy
Uvědomili jsme si, že optimalizujeme špatnou věc. Náš systém jsme orientovali kolem coding programovacích a sloučených pull requestů, přestože pull requesty i relace jsou ve skutečnosti jen prostředkem k cíli. Softwarové workflow je z velké části organizováno kolem výstupů: problémů, úkolů, ticketů, milníků.
Začali jsme si tedy klást otázku, co by se stalo, kdybychom přestali agenty přímo kontrolovat a místo toho je nechali tahat práci z našeho sledovače úkolů.
Z této myšlenky vznikla Symphony, psaná specifikace, která funguje jako supervizor pro orchestraci práce agentů.
Proměna našeho sledovače problémů na orchestrátora agentů
Symphony začala jednoduchým konceptem: každý otevřený úkol by měl převzít a dokončit agent. Místo správy relací Codexu v několika záložkách jsme z našeho sledovače problémů udělali řídicí vrstvu.
V tomto nastavení se každý otevřený ticket v Linear mapuje na vyhrazený pracovní prostor agenta. Symphony průběžně sleduje panel úkolů a zajišťuje, aby u každého aktivního úkolu běžel agent ve smyčce, dokud není hotový. Pokud se agent zastaví nebo se zasekne, Symphony ho restartuje. Pokud se objeví nová práce, Symphony ji převezme a začne práci organizovat.
Náš workflow jsme postavili na stavech ticketů a správce úkolů Linear používáme jako stavový automat.
V praxi Symphony odděluje práci od relací i od žádostí o přijetí změn. Některé problémy vedou k více pull requestům v rámci úložiště, jiné jsou čistě investigace nebo analýza a nikdy se nedotknou kódové základny.
Jakmile je práce takto abstrahovaná, tickety mohou představovat mnohem větší jednotky práce.
Symphony pravidelně používáme ke koordinaci komplexních funkcí a migrací infrastruktury. Můžeme například založit úkol, ve kterém agenta požádáme, aby analyzoval kódovou základnu, Slack nebo Notion a vytvořil implementační plán. Jakmile jsme s plánem spokojeni, agent vygeneruje strom úkolů, rozdělí práci do etap a určí závislosti mezi úkoly.
Agenti začínají pracovat jen na úkolech, které nejsou blokované, takže se provádění u tohoto DAG (sekvence kroků provedení) přirozeně a optimálně rozvíjí paralelně. V níže uvedeném příkladu jsme upgrade React označili jako blokovaný migrací na Vite. Podle očekávání začali agenti React upgradovat až poté, co byla migrace na Vite dokončena.
Agenti si také mohou vytvářet práci sami. Během implementace nebo kontroly si často všimnou zlepšení, která nespadají do rozsahu aktuálního úkolu: problém s výkonem, příležitost k refaktoringu nebo lepší architektura. Když se to stane, jednoduše založí nový problém, který můžeme vyhodnotit a naplánovat na později. Mnoho z těchto navazujících úkolů pak také převezmou agenti. I když na tento proces dohlížíme, agenti zůstávají organizovaní a posouvají práci kupředu.
Tento způsob práce dramaticky snižuje kognitivní náklady na rozbíhání nejednoznačné práce. Pokud agent něco udělá špatně, je to stále užitečná informace a náklady pro nás jsou téměř nulové. Můžeme velmi levně zakládat tickety, aby agent šel prototypovat a zkoumat, a vyhodit jakékoli směry, které se nám nelíbí.
Protože orchestrátor běží na devboxech a nikdy nespí, můžeme přidávat úkoly odkudkoli a víme, že je agent převezme. Jeden vývojář v našem týmu například provedl tři významné změny z aplikace Linear v telefonu z útulné chaty s mizernou wifi.
Více zkoumání díky tomuto způsobu práce
Když jsme pozorovali dopady práce se Symphony, nejzřetelnější změnou byl výstup. V některých týmech v OpenAI jsme během prvních tří týdnů zaznamenali 6× více přijatých pull requestů. Mimo OpenAI upozornil zakladatel Linear Karri Saarinen při vydání Symphony na nárůst vytvořených pracovních prostorů(otevře se v novém okně). Hlubší změna se ale týká toho, jak týmy o práci přemýšlejí.
Když už naši vývojáři netráví čas dohledem nad relacemi Codexu, ekonomika změn v kódu se úplně mění. Vnímané náklady každé změny klesají, protože už nevkládáme lidské úsilí do samotného řízení implementace.
To změnilo naše chování. Ve Symphony je teď triviální rozběhnout spekulativní úkoly. Zkuste nápad, prozkoumejte refaktor, otestujte hypotézu a ponechte si jen výsledky, které vypadají slibně.
Zároveň se rozšiřuje okruh lidí, kteří mohou práci iniciovat. Náš produktový manažer i designér teď mohou zadávat požadavky na funkce přímo do Symphony. Nemusí kontrolovat úložiště ani spravovat relaci Codex. Popíšou funkci a zpět dostanou balíček ke kontrole, který zahrnuje videoukázku funkce běžící ve skutečném produktu.
Symphony také vyniká ve velkých monorepozitářích (jako je ten náš v OpenAI), kde je poslední krok k přijetí pull requestu pomalý a křehký. Systém dohlíží na CI, v případě potřeby rebazuje změny, řeší konflikty, znovu spouští nespolehlivé kontroly a celkově provází změny celým procesem pipeline. V okamžiku, kdy se ticket dostane do stavu Merging, máme vysokou důvěru, že se změna dostane do hlavní větve bez lidského dohledu.
Pokrok přináší nové, jiné problémy
Práce na této úrovni s sebou nese kompromisy. Když jsme přešli od interaktivního navádění agentů k zadávání práce na úrovni ticketů, ztratili jsme možnost je průběžně posouvat během běhu a podle potřeby korigovat směr. Někdy agent vytvořil něco, co se úplně minulo cílem. To ale bylo užitečné. Tato selhání odhalila mezery v systému a pomohla nám ho udělat odolnějším.
Místo ručního opravování výsledku jsme přidali pravidla a dovednosti, aby agenti příště uspěli. Postupem času nás to vedlo k rozšíření našeho rámce o nové schopnosti, jako je spouštění end-to-end testů, ovládání aplikace přes Chrome DevTools a správa smoke testů QA. Výrazně jsme zlepšili dokumentaci a zpřesnili, jak vypadá dobrý výsledek.
Ne každý úkol se hodí pro styl práce Symphony. Některé problémy stále vyžadují vývojáře, kteří pracují přímo s interaktivními relacemi Codex, zejména nejednoznačné problémy nebo práce vyžadující silný úsudek a odbornost. V praxi jsou to obvykle právě ty nejzajímavější a nejpříjemnější úkoly, kterým naši vývojáři věnují čas.
Rozdíl je v tom, že Symphony zvládne většinu rutinní implementační práce. To umožňuje vývojářům soustředit se vždy na jeden těžký problém místo neustálého přepínání kontextu mezi menšími úkoly.
Zjistili jsme také, že zacházet s agenty jako s rigidními uzly ve stavovém automatu nefunguje dobře. Modely jsou chytřejší a dokážou řešit větší problémy, než kolik se jich snažíme vměstnat do škatulky. Například v raných verzích byly všechny integrace s GitHub součástí vnějšího rámce. Očekávalo se třeba, že Codex bude dělat jen změny v kódu, zatímco zbytek procesu (odeslání změn, spouštění testů) byl definován v kódu. Naše rané verze agentní práce chtěly po Codexu jen implementaci úkolu. Tento přístup se ukázal jako příliš omezující. Codex je naprosto schopný vytvářet více pull requestů a také číst zpětnou vazbu z kontrol a reagovat na ni. Poskytli jsme mu tedy nástroje (CLI gh, dovednosti pro čtení CI logů atd.) a teď můžeme Codex požádat o víc, například o uzavírání starých pull requestů nebo vytahování reportů se srovnáním dokončené a opuštěné práce. Tyto typy úkolů byly daleko za hranicemi původního rámce implementace funkcí.
Nakonec jsme se tedy dostali k tomu, že agentům dáváme cíle místo striktních přechodů, podobně jako dobrý manažer zadává cíl člověku, který mu v týmu podléhá. Síla modelů vychází z jejich schopnosti uvažování, takže je třeba jim dát nástroje a kontext a nechat je pracovat.
Použití Symphony k vytvoření Symphony
Když otevřete úložiště Symphony, první věc, které si všimnete, je, že Symphony je technicky vzato jen soubor SPEC.md – definice problému a zamýšleného řešení. Místo budování složitého dohledového systému jsme definovali problém a zamýšlená řešení a dali agentům vysokou míru řízení.
Referenční implementace je napsaná v programovacím jazyce Elixir (když je kód fakticky zdarma, můžete si konečně vybírat jazyky podle jejich silných stránek, jako je souběžnost v Elixiru), ale základní myšlenku lze vyjádřit v jednoduchém dokumentu Markdown. Doporučujeme nasměrovat vašeho oblíbeného programovacího agenta na specifikaci a nechat ho implementovat vlastní verzi.
První verze Symphony byla jen relace Codex běžící v tmux, která dotazovala Linear a spouštěla subagenty pro nové úkoly. Fungovalo to, ale nebylo to nijak zvlášť spolehlivé. Druhá verze žila v našem hlavním projektovém úložišti, které bylo navržené s ohledem na agenty. Už jsme měli vytvořený rámec pro agenty, který jim v tomto úložišti dával dovednosti i kontext pro kvalitní práci, takže Symphony to všechno jednoduše propojuje.
Jakmile existovala základní funkcionalita, použili jsme Symphony k vytvoření Symphony.
Když jsme interně předvedli systém, který spravuje úkoly a přikládá své demonstrační video s výsledky, reakce byla převážně pozitivní: náš projektový kanál Symphony rostl a týmy napříč organizací ho začaly organicky používat. Interní soulad produktu s trhem je v OpenAI předpokladem pro externí spuštění. Na základě toho, jaké používání jsme v OpenAI viděli, bylo jasné, že bychom měli Symphony sdílet i mimo firmu.
Proto jsme myšlenku vyčlenili do samostatného SPEC.md a požádali Codex, aby ji implementoval. Pro referenční implementaci jsme zvolili Elixir, relativně okrajový jazyk s výbornými základními prvky pro orchestraci a dohled nad souběžnými procesy. Codex vytvořil implementaci v Elixiru na jeden zátah a od té doby jsme dál iterovali jak na specifikaci, tak na implementaci. Abychom specifikaci vyladili, požádali jsme Codex dokonce, aby ji implementoval v několika dalších jazycích (TypeScript, Go, Rust, Java, Python) a výsledky využili k odhalení nejasností a zjednodušení systému. Uspěl ve všech jazycích.
Během procesu vývoje Codex jsme odstranili spoustu náhodných složitých problémů, například závislosti na konkrétních úložištích nebo na Linear MCP. Symphony už nezávisí na našich interních úložištích ani pracovních postupech. Základní přístup se zjednodušil na toto:
Pro každý otevřený úkol zajistěte, aby ve vlastním pracovním prostoru běžel agent.
Kromě pomoci s aktivní prací je vývojový workflow nyní také něco, co agenti znají a dodržují. Vývojový postup (pracovat na problému, zkontrolovat úložiště, označit práci jako rozpracovanou, aby PM věděl, že se na ní pracuje, přidat pull request, přesunout ji do stavu kontroly, připojit videa atd.) je nyní zachycen v jednoduchém souboru WORKFLOW.md. To vše byl proces, který lidé dodržovali, ale nikdy nebyl zdokumentován. Místo spoléhání na tento implicitní soubor kroků jej teď dokumentujeme a Symphony zajišťuje, aby ho agenti dodržovali. Díky tomu můžeme budovat agenty, kteří pracují po našem boku. Pokud se rozhodneme, že agenti mají k dokončené práci připojovat i sebereflexi, přidáme to do WORKFLOW.md a Symphony agenty dovede i k tomuto kroku.
Mohli jsme také používat Codex v režimu aplikačního serveru(otevře se v novém okně), tedy v integrovaném režimu bez grafického rozhraní pro Codex. Tento režim nám umožnil provozovat Codex a programově s ním komunikovat přes dobře zdokumentované JSON-RPC API pro věci jako spuštění vlákna nebo reakce na jednotlivé tahy. Je to mnohem pohodlnější a škálovatelnější způsob než snaha interagovat s Codex přes CLI nebo živé relace tmux.
Codex App Server se pro náš případ použití dokonale hodil: využíváme rámec, který Codex poskytuje, a zároveň máme ovládací prvky a hooky, do kterých se můžeme napojit. Abychom například nemuseli subagentům zpřístupnit přístupový token do Linear, používáme volání dynamických nástrojů(otevře se v novém okně), abychom zpřístupnili surovou funkci linear_graphql, která provádí libovolné požadavky vůči Linear, aniž bychom spoléhali na MCP nebo zpřístupňovali přístupový token kontejnerům.
Co bude dál
Symphony je záměrně minimální vrstva pro orchestraci. Zveřejňujeme ji jako open source, abychom ukázali sílu Codex App Server při spárování s různými workflow nástroji, jako je Linear. Proto Symphony neplánujeme udržovat jako samostatný produkt. Berte ji jako referenční implementaci. Podobně jako mnoho vývojářů nasměrovalo své programovací agenty na článek o využití rámce AI, aby si nechali vytvořit kostru svých úložišť, doufáme, že nasměrujete svého oblíbeného programovacího agenta na specifikaci(otevře se v novém okně) a úložiště(otevře se v novém okně) Symphony a vytvoříte si vlastní verze přizpůsobené vašemu prostředí.
Síla vychází z Codex a jeho app serveru. Symphony byl způsob, jak propojit Codex a Linear, dvě věci, které jsme už používali, a vyřešit problém řízení práce. Jak se bude zlepšovat uvažování a dodržování instrukcí programovacích agentů, předpokládáme, že se úzké hrdlo i v dalších firmách přesune od psaní kódu ke správě agentní práce. Vzrušující je, že bariéra pro experimentování s těmito systémy programovacích agentů je teď překvapivě nízká. Prostě můžete budovat s Codexem.
Ohlasy komunity
Máme velkou radost, že vývojářská komunita používá Symphony už během několika týdnů od vydání; k 23. dubnu získala více než 15 tisíc hvězdiček na GitHubu(otevře se v novém okně).