Спецификација отвореног кода за оркестрацију Codex-а: Symphony
Аутори су: Алекс Котљарски (Alex Kotliarskyi), Виктор Џу (Victor Zhu) и Зак Брок (Zach Brock)
Пре шест месеци, док смо радили на интерном алату за продуктивност, наш тим је донео контроверзну (у то време) одлуку: направићемо свој репозиторијум без икаквог кода који су написали људи. Сваки ред у депоу нашег пројекта морао је да буде генерисан помоћу Codex-а.
Да би то функционисало, редизајнирали смо наш инжењерски ток рада од темеља. Изградили смо депо прилагођен агентима, много уложили у аутоматизоване тестове и заштитне механизме, и третирали Codex као пуноправног члана тима. Документовали смо тај процес у нашој претходној објави на блогу на тему искориштења инжењерског рада.
И то је функционисало, али смо онда наишли на следеће уско грло: пребацивање контекста.
Да бисмо решили овај нови проблем, направили смо систем под називом Symphony. Symphony(отвара се у новом прозору) је оркестратор агената који претвара таблу за управљање пројектима као што је Linear у контролну раван за агенте за програмирање. Сваком отвореном задатку се додељује агент, агенти раде непрекидно, а људи прегледају резултате.
Овај пост објашњава како смо креирали Symphony — што је довело до повећања броја прихваћених pull request-ова за 500% у неким тимовима — и како да га користите да свој систем за праћење проблема претворите у увек активан оркестратор агената.
Горња граница могућности интерактивних агената за програмирање
Иако постају све лакши за коришћење, агенти за кодирање – било да им се приступа путем веб апликација или CLI-ја – и даље су интерактивни алати.
Како се обим агентског рада у компанији OpenAI повећавао, открили смо нову врсту оптерећења. Сваки инжењер би покренуо неколико сесија у апликацији Codex, доделио задатке, прегледао резултате, усмеравао агента и поновио поступак. У пракси, већина људи могла је без већих потешкоћа управљати три до пет сесија истовремено пре него што би пребацивање контекста постало напорно. Након тога, продуктивност је опала. Заборављали смо која сесија шта ради, скакали између терминала да бисмо вратили агенте на прави пут и исправљали грешке у дуготрајним задацима који би застали на пола пута.
Агенти су били брзи, али је постојало уско грло у систему: људска пажња. Практично смо изградили тим изузетно способних млађих инжењера, а затим задужили наше људске инжењере да управљају њима до најситнијих детаља. То није могло да се скалира.
Промена перспективе
Схватили смо да оптимизујемо погрешну ствар. Постављали смо систем тако да буде усредсређен на сесије кодирања и спојене PR-ове, иако су PR-ови и сесије заправо само средство за постизање циља. Софтверски радни токови су у великој мери организовани око резултата: проблема, задатака, тикета и прекретница.
Запитали смо се шта би се десило ако бисмо престали директно да надзиремо агенте и дозволили им да сами преузимају задатке из нашег система за праћење задатака.
Та идеја је постала Symphony, писана спецификација која служи као супервизор за оркестрирање рада агената.
Претварање нашег система за праћење проблема у систем за управљање агентима
Symphony је започео са једноставним концептом: сваки отворени задатак треба да буде преузет и завршен од стране агента. Уместо управљања Codex сесијама у више картица, наш систем за праћење проблема претворили смо у управљачки слој.
У овој конфигурацији, сваки отворени проблем у Linear-у повезује се са наменским радним простором агента. Symphony непрекидно прати таблу задатака и осигурава да сваки активни задатак има агента који ради у петљи док не буде завршен. Ако агент откаже или се заглави, Symphony га поново покреће. Ако се појави нови посао, Symphony га преузима и почиње да организује рад.
Радни процес смо поставили на основу статуса задатака, користећи Linear као систем за праћење стања.
У пракси, Symphony одваја рад од сесија и pull request-ова. Неки проблеми доводе до више PR-ова у различитим репозиторијумима; други су искључиво истрага или анализа и никада не захватају базу кода.
Када се рад постави на овај начин, задаци могу представљати много веће радне целине.
Редовно користимо Symphony за управљање сложеним функцијама и миграцијама инфраструктуре. На пример, могли бисмо да креирамо задатак којим се од агента тражи да анализира базу кода, Slack или Notion и направи план имплементације. Када будемо задовољни планом, агент генерише стабло задатака, разлажући рад на фазе и дефинишући зависности између задатака.
Агенти почињу да раде само на задацима који нису блокирани, тако да се извршавање одвија природно и оптимално паралелно у оквиру овог DAG-а (низа корака извршавања). На пример, означили смо надоградњу React-а као блокирану све док се не заврши миграција на Vite. Као што се очекивало, агенти су почели да надограђују React тек након што је миграција на Vite завршена.
Агенти могу и сами да креирају посао. Током имплементације или прегледа, они често уочавају побољшања која су ван опсега тренутног задатка: проблем са перформансама, прилику за преуређивање кода или бољу архитектуру. Када се то догоди, они једноставно пријаве нови проблем који можемо да проценимо и закажемо за касније — многе од ових накнадних задатака такође преузимају агенти. Док ми надгледамо овај процес, агенти остају организовани и одржавају напредак у раду.
Овакав начин рада значајно смањује когнитивни напор потребан за започињање неодређеног посла. Ако агент у нечему погреши, то је и даље корисна информација, а трошак за нас је готово нула. Можемо уз веома мале трошкове да отварамо тикете за агента како би направио прототип и истраживао, а затим да одбацимо сва истраживања која нам се не допадну.
Пошто оркестратор ради на развојним кутијама и никада не спава, можемо да додајемо задатке са било ког места и знамо да ће их агент преузети. На пример, један инжењер из нашег тима унео је три значајне измене из апликације Linear на свом телефону, из удобне брвнаре, преко лоше Wi‑Fi везе.
Повећање истраживања као резултат оваквог начина рада
Када су се посматрали ефекти рада са Symphony-јем, најочигледнија промена била је у излазним резултатима. У појединим тимовима у компанији OpenAI, приметили смо да се број интегрисаних PR-ова повећао за 500% током прве три недеље. Изван компаније OpenAI, оснивач компаније Linear, Кари Саринен, истакао је скок у броју креираних радних простора(отвара се у новом прозору) у тренутку када смо објавили Symphony. Међутим, дубља промена је у томе како тимови размишљају о раду.
Када наши инжењери више не троше време на надгледање сесија Codex-а, економија програмирања се потпуно мења. Перципирани трошак сваке промене опада јер више не улажемо људски напор у спровођење саме имплементације.
То је променило наше понашање. Покретање спекулативних задатака у Symphony-ју постало је веома једноставно. Испробајте идеју, истражите рефакторизацију, тестирајте хипотезу и задржите само резултате који делују обећавајуће.
Такође проширује круг оних који могу да започну рад. Наш менаџер производа и дизајнер сада могу да подносе захтеве за функционалности директно у Symphony. Не морају да клонирају репозиторијум нити да управљају Codex сесијом. Они описују функционалност и добијају пакет за ревизију који укључује видео водич са приказом како та функционалност ради унутар стварног производа.
Symphony такође долази до изражаја у великим монорепозиторијумима (попут оног који имамо у компанији OpenAI), где је завршна фаза интегрисања PR-а спора и осетљива. Систем прати CI, по потреби усклађује грану с најновијим изменама, решава конфликте, поново покреће нестабилне провере и стара се да измене прођу кроз цео процес до краја. Док тикет стигне до фазе Спајање, можемо бити прилично сигурни да ће измена бити укључена у главну грану без сталног људског надзора.
Након увођења Symphony-ја, делегирамо више посла агентима и фокусирамо се на захтевније, истраживачке задатке.
Напредак доноси нове, другачије проблеме
Рад на овом нивоу подразумева компромисе. Када смо са интерактивног усмеравања агената прешли на додељивање посла на нивоу тикета, изгубили смо могућност да их стално благо усмеравамо у ходу и по потреби коригујемо курс. Понекад је агент генерисао нешто што је потпуно промашило циљ. То је било корисно – ти неуспеси су открили недостатке у систему и помогли нам да га учинимо робуснијим.
Уместо да ручно исправљамо резултат, додали смо заштитне механизме и вештине како би агенти могли да буду успешни следећи пут. Временом нас је то навело да у наш тестни оквир додамо нове могућности, као што су покретање тестова од почетка до краја, управљање апликацијом преко Chrome DevTools-а и управљање QA smoke тестовима. Значајно смо унапредили нашу документацију и разјаснили шта се сматра добрим.
Није сваки задатак погодан за Symphony стил рада. Неки проблеми и даље захтевају да инжењери раде директно са интерактивним Codex сесијама, посебно када су проблеми нејасни или је реч о раду који захтева добро расуђивање и стручност. У пракси, то су обично најзанимљивији и најпријатнији задаци којима наши инжењери могу да посвете своје време.
Разлика је у томе што Symphony може да обави већи део рутинског рада на имплементацији. То омогућава инжењерима да се усредсреде на један захтеван проблем у датом тренутку, уместо на стално пребацивање контекста између мањих задатака.
Такође смо научили да третирање агената као крутих чворова у стањима није ефикасно. Модели постају паметнији и могу да решавају веће проблеме од оквира у који их покушавамо уклопити. Наше ране верзије агентског рада сводиле су се само на то да од Codex-а затражимо имплементацију задатка. Тај приступ се показао као превише ограничавајући. Codex је у потпуности способан да креира више PR-ова, као и да чита повратне информације из прегледа и реагује на њих. Зато смо му дали алате –gh CLI, вештине за читање CI логова итд. – и сада можемо да затражимо од Codex-а да ради више, као што је затварање старих PR-ова или извлачење извештаја о завршеном у односу на напуштени рад. Ове врсте задатака су биле далеко изван почетног оквира за имплементацију функција.
Тако смо на крају прешли на то да агентима задајемо циљеве уместо строгих прелаза, слично као што би добар менаџер доделио циљ подређеном члану свог тима. Снага модела проистиче из њихове способности да резонују, зато им дајте алате и контекст и пустите их да раде своје.
Коришћење Symphony-ја за изградњу Symphony-ја
Када отворите депо Symphony,(отвара се у новом прозору) прво што ћете приметити јесте да је Symphony, технички гледано, само датотека SPEC.md — дефиниција проблема и предвиђеног решења. Уместо да градимо сложен систем надзора, дефинисали смо проблем и предвиђена решења, дајући агентима усмеравање на високом нивоу.
Референтна имплементација је написана у језику Elixir – јер када је кôд практично бесплатан, коначно можете да бирате програмске језике према њиховим предностима, као што је Elixir-ова подршка за конкурентно извршавање – али основна идеја може да се изрази у једноставном Markdown документу. Подстичемо вас да свог омиљеног агента за програмирање усмерите на спецификацију и да га наведете да имплементира своју верзију.
Прва верзија Symphony-ја била је само сесија Codex-а која је радила у tmux-у, периодично проверавала Linear и покретала подагенте за нове задатке. Функционисало је, али није било нарочито поуздано. Друга верзија се налазила унутар нашег главног пројектног репозиторијума, направљеног имајући у виду агенте. Већ смо изградили оквир за агенте који агентима пружа вештине и контекст потребне за рад високог квалитета у овом репозиторијуму, тако да Symphony једноставно све то повезује.
Када је основна функционалност била успостављена, користили смо Symphony да бисмо изградили Symphony.
Када смо интерно демонстрирали систем за управљање задацима и прилагање видео записа као доказа обављеног рада, реакција је била изузетно позитивна: наш канал за пројекат Symphony је порастао, а тимови широм организације су га почели спонтано користити. Интерна усклађеност производа са потребама тржишта је предуслов за екстерно представљање у компанији OpenAI. На основу употребе коју смо видели у компанији OpenAI, постало је јасно да Symphony треба учинити доступним и ван оквира компаније.
Тако смо издвојили идеју у самостални SPEC.md и затражили од Codex-а да је имплементира. За референтну имплементацију смо изабрали Elixir, релативно редак језик са одличним основним механизмима за оркестрацију и надзор истовремених процеса. Codex је изградио Elixir имплементацију са једним примером, од тада смо наставили да усклађујемо и разрађујемо и спецификацију и имплементацију. Да бисмо усавршили спецификацију, чак смо затражили од Codex-а да је имплементира на неколико других језика — TypeScript, Go, Rust, Java, Python — и да резултате употреби за препознавање нејасноћа и поједностављивање система. Успело је на сваком језику.
Током процеса изградње Symphony-а уклонили смо много непотребне сложености, као што су зависности од одређених репозиторијума или Linear MCP-а. Symphony више не зависи од наших интерних депоа или токова рада. Основни приступ је постао једноставан:
За сваки отворени задатак, обезбедите да агент ради у свом радном простору.
Поред тога што помажу у текућем раду, агенти сада познају и прате ток развоја рада. Ток развоја рада — рад на задатку, преузимање репозиторијума, означавање да је у току како би PM знао да се на њему ради, додавање PR-а, премештање у статус Преглед, прилагање видео-снимака итд. — сада је забележен у једноставној датотеци WORKFLOW.md. Све ово је процес који су људи пратили, али никада није био документован. Уместо да се ослањамо на овај имплицитни скуп корака, сада га документујемо, а Symphony осигурава да га агенти следе. Ово нам омогућава да креирамо агенте који раде заједно са нама. Ако одлучимо да агенти треба и да прилажу саморефлексију уз завршени рад, додаћемо то у WORKFLOW.md, а Symphony ће усмерити агенте ка том кораку.
Такође смо имали прилику да користимо Codex у режиму сервера апликације(отвара се у новом прозору), уграђеном режиму без графичког интерфејса за Codex. Овај режим нам је омогућио да покрећемо Codex и да с њим комуницирамо програмски преко добро документованог JSON-RPC API-ја, за радње као што су покретање теме или реаговање на поруке. То је практичније и скалабилније него покушавати интеракцију са Codex-ом путем CLI-ја или активних tmux сесија.
Codex App Server је био савршено решење за наш случај употребе: користимо предности окружења које Codex пружа, а истовремено имамо опције за конфигурисање и прикључне тачке за интеграцију. На пример, да бисмо избегли излагање Linear приступног токена подагентима, користимо динамичке позиве алатки(отвара се у новом прозору) да изложимо сирову функцију linear_graphql, која извршава произвољне захтеве према Linear-у, без ослањања на MCP или излагања приступног токена контејнерима.
Шта је следеће
Symphony је намерно минималистички оркестрациони слој. Објављујемо га као отворени код како бисмо показали снагу Codex App Server-а када се упари са различитим алаткама за токове рада, као што је Linear. Стога не планирамо да одржавамо Symphony као самосталан производ. Посматрајте то као референтну имплементацију. Слично томе како су многи програмери усмерили своје агенте за кодирање на објаву о инжењерингу harness-а да би поставили основу својих депоа, надамо се да ћете усмерити свог омиљеног агента за кодирање на Symphony спецификацију(отвара се у новом прозору) и депо(отвара се у новом прозору) да бисте направили сопствене верзије прилагођене својим окружењима.
Снага потиче од Codex-а и његовог сервера апликације. Symphony је био начин да повежемо Codex са Linearом, две ствари које смо већ користили, како бисмо решили проблем управљања радом. Како агенти за програмирање постају бољи у резоновању и праћењу упутстава, претпостављамо да ће се уско грло у другим компанијама такође померити са писања кода ка управљању агентским радом. Узбудљиво је то што је препрека за експериментисање са овим системима агената за програмирање сада изненађујуће мала. Можете једноставно да правите ствари уз Codex.
Похвале заједнице
Одушевљени смо што видимо да инжењерска заједница користи Symphony у недељама након објављивања, прикупивши више од 15.000 GitHub звездица(отвара се у новом прозору) закључно са 23. 4.