Спецификација со отворен код за оркестрација на Codex: Symphony
Од Alex Kotliarskyi, Victor Zhu и Zach Brock
Пред шест месеци, додека работевме на интерна алатка за продуктивност, нашиот тим донесе контроверзна (во тоа време) одлука: ќе го изградиме нашиот репозиториум без код напишан од луѓе. Секоја линија во нашиот проектен репозиториум мораше да биде генерирана од Codex.
За да успее тоа, го редизајниравме нашиот инженерски работен тек од темел. Изградивме репозиториум пријателски за агенти, многу вложивме во автоматизирани тестови и заштитни механизми и го третиравме Codex како полноправен соиграч. Тоа патување го документиравме во нашата претходна објава на блог за harness engineering.
И успеа, но потоа наидовме на следното тесно грло: префрлување на контекст.
За да го решиме овој нов проблем, изградивме систем наречен Symphony. Symphony(се отвора во нов прозорец) е оркестратор на агенти што претвора табла за управување со проекти како Linear во контролна рамнина за агенти за кодирање. Секоја отворена задача добива агент, агентите работат континуирано, а луѓето ги прегледуваат резултатите.
Оваа објава објаснува како го создадовме Symphony — што резултираше со зголемување од 500% на прифатени барања за повлекување кај некои тимови — и како да го користите за да го претворите вашиот сопствен тракер за проблеми во секогаш вклучен оркестратор на агенти.
Плафонот на интерактивните агенти за кодирање
Иако стануваат полесни за користење, агентите за кодирање — без разлика дали им се пристапува преку веб-апликации или CLI — сè уште се интерактивни алатки.
Како што обемот на агентска работа се зголемуваше во OpenAI, наидовме на нов вид оптоварување. Секој инженер ќе отвораше неколку Codex сесии, доделуваше задачи, го прегледуваше излезот, го насочуваше агентот и го повторуваше циклусот. Во пракса, повеќето луѓе можеа удобно да управуваат со три до пет сесии одеднаш пред префрлувањето на контекст да стане болно. Над тоа, продуктивноста опаѓаше. Заборававме која сесија што прави, скокавме меѓу терминали за да ги вратиме агентите на вистинскиот пат и дебагиравме долготрајни задачи што заглавуваа на половина.
Агентите беа брзи, но имавме системско тесно грло: човечкото внимание. Практично изградивме тим од исклучително способни помлади инженери, а потоа им доделивме на нашите човечки инженери да ги микроменаџираат. Тоа немаше да може да се скалира.
Промена на перспективата
Сфативме дека ја оптимизираме погрешната работа. Го ориентиравме нашиот систем околу сесии за кодирање и споени PRs, кога PRs и сесиите всушност се само средство до целта. Софтверските работни текови во голема мера се организирани околу испораки: проблеми, задачи, тикети, пресвртници.
Затоа се запрашавме што би се случило ако престанеме директно да ги надгледуваме агентите и наместо тоа им дозволиме да ја преземаат работата од нашиот тракер за задачи.
Таа идеја стана Symphony, пишана спецификација што функционира како супервизор за оркестрација на агентска работа.
Претворање на нашиот тракер за проблеми во оркестратор на агенти
Symphony започна со едноставен концепт: секоја отворена задача треба да биде преземена и завршена од агент. Наместо да управуваме со Codex сесии во повеќе јазичиња, го направивме нашиот тракер за проблеми контролна рамнина.
Во оваа поставка, секој отворен проблем во Linear се мапира на посебен работен простор за агент. Symphony постојано ја следи таблата со задачи и осигурува дека за секоја активна задача има агент што работи во циклусот сè додека не заврши. Ако агентот падне или заглави, Symphony го рестартира. Ако се појави нова работа, Symphony ја презема и почнува да ја организира работата.
Нашиот работен тек го изградивме врз основа на статуси на тикети, користејќи го менаџерот на задачи Linear како машина на состојби.
Во пракса, Symphony ја раздвојува работата од сесиите и од барањата за повлекување. Некои проблеми создаваат повеќе PRs низ различни репозиториуми; други се чисто истражување или анализа што никогаш не го допираат кодниот базен.
Штом работата ќе се апстрахира на овој начин, тикетите можат да претставуваат многу поголеми единици работа.
We regularly use Symphony to orchestrate complex features and infrastructure migrations. For example, we might file a task asking the agent to analyze the codebase, Slack, or Notion and produce an implementation plan. Once we’re happy with the plan, the agent generates a tree of tasks, breaking the work into stages and defining dependencies between tasks.
Agents only start working on tasks that aren’t blocked, so execution unfolds naturally and optimally in parallel for this DAG (a sequence of execution steps). For example, we marked the React upgrade as blocked on a migration to Vite. As expected, agents started upgrading React only after the migration to Vite was complete.
Agents can also create work themselves. During implementation or review, they often notice improvements that fall outside the scope of the current task: a performance issue, a refactoring opportunity, or a better architecture. When that happens, they simply file a new issue that we can evaluate and schedule later—many of these follow-up tasks also get picked up by agents. While we oversee this process, agents stay organized and keep work moving forward.
This way of working dramatically reduces the cognitive cost of kicking off ambiguous work. If the agent gets something wrong, that’s still useful information, and the cost to us is near zero. We can very cheaply file tickets for the agent to go prototype and explore, and throw away any explorations we don’t like.
Because the orchestrator runs on devboxes and never sleeps, we can add tasks from anywhere and know an agent will pick it up. For instance, one engineer on our team made three significant changes from the Linear app on his phone from a cozy cabin on shoddy wifi.
An increase in exploration from working this way
When observing the effects of working with Symphony, the most obvious change was output. Among some teams at OpenAI, we saw the number of landed PRs increase by 500% in the first three weeks. Outside of OpenAI, Linear founder Karri Saarinen highlighted a spike in workspaces created(се отвора во нов прозорец) as we released Symphony. However, the deeper shift is how teams think about work.
When our engineers no longer spend time supervising Codex sessions, the economics of code changes completely. The perceived cost of each change drops because we’re no longer investing human effort in driving the implementation itself.
That changed our behavior. It's become trivial to spin up speculative tasks in Symphony. Try an idea, explore a refactor, test a hypothesis, and only keep the results that look promising.
It also broadens who can initiate work. Our product manager and designer can now file feature requests directly into Symphony. They don’t need to check out the repo or manage a Codex session. They describe the feature and get back a review packet that includes a video walkthrough of the feature working inside the real product.
Symphony also shines in large monorepos (like the one we have at OpenAI) where the last mile of landing a PR is slow and fragile. The system watches CI, rebases when needed, resolves conflicts, retries flaky checks, and generally shepherds changes through the pipeline. By the time a ticket reaches Merging, we have high confidence the change will make it into the main branch without human babysitting.
По имплементацијата на Symphony, делегираме повеќе работа на агенти и се фокусираме на потешки, поистражувачки задачи.
Напредокот носи нови, поинакви проблеми
Работењето на ова ниво носи компромиси. Кога преминавме од интерактивно насочување на агентите кон доделување работа на ниво на тикет, ја изгубивме можноста постојано да ги поттурнуваме среде лет и да ја коригираме насоката кога е потребно. Понекогаш агентот создаваше нешто што целосно ја промашуваше целта. Тоа беше корисно — тие неуспеси откриваа празнини во системот и ни помогнаа да го направиме поотпорен.
Наместо рачно да го крпиме резултатот, додадовме заштитни механизми и вештини за агентите да успеат следниот пат. Со текот на времето, тоа нè доведе до додавање нови можности во нашиот harness, како извршување end-to-end тестови, управување со апликацијата преку Chrome DevTools и менаџирање QA smoke тестови. Значително ја подобривме нашата документација и појаснивме како изгледа добро извршена работа.
Не секоја задача одговара на стилот на работа на Symphony. Некои проблеми сè уште бараат инженери што работат директно со интерактивни Codex сесии, особено двосмислени проблеми или работа што бара силно расудување и експертиза. Во пракса, тоа обично се најинтересните и најпријатните задачи на кои нашите инженери трошат време.
Разликата е што Symphony може да го преземе најголемиот дел од рутинската имплементациска работа. Тоа им овозможува на инженерите да се фокусираат на еден тежок проблем во даден момент, наместо постојано да префрлуваат контекст меѓу помали задачи.
Исто така научивме дека не функционира добро агентите да се третираат како ригидни јазли во машина на состојби. Моделите стануваат попаметни и можат да решаваат поголеми проблеми од кутијата во која се обидуваме да ги сместиме. На пример, раните верзии ги имаа сите GitHub интеграции како дел од надворешниот harness — на пример, раните верзии очекуваа Codex само да прави промени во кодот, а остатокот од процесот (поднесување промени, извршување тестови) беше специфициран во код. Нашите рани верзии на агентска работа само бараа од Codex да ја имплементира задачата. Тој пристап се покажа како премногу ограничувачки. Codex е сосема способен да создава повеќе PRs, како и да чита повратни информации од преглед и да постапува по нив. Затоа му дадовме алатки — CLI gh, вештини за читање CI логови итн. — и сега можеме да побараме од Codex да прави повеќе, како затворање стари PRs или извлекување извештаи за завршена наспроти напуштена работа. Овие видови задачи беа далеку надвор од првичната рамка за имплементација на функционалност.
Затоа на крај се придвиживме кон тоа на агентите да им даваме цели наместо строги транзиции, слично како што добар менаџер би доделил цел на директно подреден во својот тим. Моќта на моделите доаѓа од нивната способност за расудување, па дајте им алатки и контекст и пуштете ги да работат.
Користење на Symphony за изградба на Symphony
Кога ќе го отворите репозиториумот на Symphony, првото нешто што ќе го забележите е дека Symphony технички е само датотека SPEC.md — дефиниција на проблемот и наменетото решение. Наместо да градиме сложен систем за надзор, ги дефиниравме проблемот и наменетите решенија, давајќи им на агентите управување на високо ниво.
Референтната имплементација е напишана во Elixir — затоа што кога кодот е практично бесплатен, конечно можете да избирате јазици според нивните предности, како конкурентноста на Elixir — но основната идеја може да се изрази во едноставен Markdown документ. Ве охрабруваме да го насочите вашиот омилен агент за кодирање кон спецификацијата и да му дозволите да имплементира своја верзија.
Првата верзија на Symphony беше само сесија на Codex што работеше во tmux, ги анкетираше задачите во Linear и стартуваше подагенти за нови задачи. Работеше, но не беше особено сигурна. Втората верзија живееше во нашиот главен проектен репозиториум, кој беше изграден имајќи ги предвид агентите. Веќе го имавме изградено agent harness-от за да им даде на агентите вештини и контекст за да вршат висококвалитетна работа во овој репозиториум, па Symphony едноставно го поврзува сето тоа.
Откако постоеше основната функционалност, го користевме Symphony за да го изградиме Symphony.
Кога внатрешно го демонстриравме системот што управува со задачи и го прикачува своето видео како доказ за извршена работа, реакцијата беше исклучително позитивна: нашиот проектен канал за Symphony порасна, а тимови низ целата организација почнаа органски да го користат. Внатрешното усогласување на производот со пазарот е предуслов за надворешно лансирање во OpenAI. Врз основа на користењето што го видовме во OpenAI, стана јасно дека треба да го споделиме Symphony и надвор од ѕидовите на компанијата.
Затоа ја издвоивме идејата во самостоен SPEC.md и побаравме од Codex да ја имплементира. За референтната имплементација го избравме Elixir, релативно редок јазик со одлични примитиви за оркестрација и надзор на конкурентни процеси. Codex ја изгради имплементацијата во Elixir со промпт со еден пример, а оттогаш продолживме да ги доработуваме и спецификацијата и имплементацијата. За да ја исполираме спецификацијата, дури побаравме од Codex да ја имплементира и на неколку други јазици — TypeScript, Go, Rust, Java, Python — и да ги искористи резултатите за да открие двосмислености и да го поедностави системот. Успеа на секој јазик.
Низ процесот на градење на Codex, отстранивме многу случајна сложеност, како зависности од конкретни репозиториуми или Linear MCP. Symphony веќе не зависи од нашите внатрешни репозиториуми или работни текови. Основниот пристап стана едноставен:
За секоја отворена задача, гарантирајте дека агент работи во свој работен простор.
Покрај тоа што помага со активната работа, развојниот работен тек сега е нешто што агентите го знаат и го следат. Развојниот работен тек — работи на проблем, клонирај репозиториум, стави го во тек за PM да знае дека се работи на него, додај го PR, премести го во статус Review, прикачи видеа итн. — сега е опфатен во едноставна датотека WORKFLOW.md. Сето ова беше процес што го следеа луѓето, но никогаш не беше документиран. Наместо да се потпираме на овој имплицитен сет чекори, сега го документираме, а Symphony осигурува агентите да го следат. Ова ни овозможува да изградиме агенти што работат заедно со нас. Ако одлучиме дека агентите треба да прикачуваат и саморефлексија кон завршената работа, ќе го додадеме тоа во WORKFLOW.md, а Symphony ќе ги насочи агентите кон тој чекор.
Исто така добивме можност да го користиме Codex во режим app server(се отвора во нов прозорец), вграден headless режим за Codex. Овој режим ни овозможи да го извршуваме Codex и да комуницираме со него програмски преку добро документиран JSON-RPC API за работи како започнување нишка или реагирање на потези. Тоа е многу попрактичен и поскалабилен начин отколку да се обидуваме да комуницираме со Codex преку CLI или живи tmux сесии.
Codex App Server беше совршено усогласен со нашиот случај на употреба: ги користиме предностите на harness-от што го обезбедува Codex, а притоа имаме копчиња и закачки за приклучување. На пример, за да избегнеме да го изложиме токенот за пристап до Linear на подагентите, користиме динамички повици на алатки(се отвора во нов прозорец) за да ја изложиме суровата функција linear_graphql што извршува произволни барања кон Linear, без потпирање на MCP или изложување на токенот за пристап кон контејнерите.
Што следува
Symphony е намерно минимален слој за оркестрација. Го објавуваме како отворен код за да ја покажеме моќта на Codex App Server кога е спарен со различни алатки за работен тек, како Linear. Затоа не планираме да го одржуваме Symphony како самостоен производ. Сметајте го како референтна имплементација. Слично на тоа како многу развивачи ги насочија своите агенти за кодирање кон објавата за harness engineering за да ги скелираат своите репозиториуми, се надеваме дека ќе го насочите вашиот омилен агент за кодирање кон spec(се отвора во нов прозорец) и repository(се отвора во нов прозорец) на Symphony за да изградите сопствени верзии прилагодени на вашите околини.
Моќта доаѓа од Codex и неговиот апликациски сервер. Symphony беше начин да се поврзат Codex и Linear, две работи што веќе ги користевме, за да се реши проблемот со управувањето со работата. Како што агентите за кодирање стануваат подобри во расудување и следење инструкции, се сомневаме дека тесното грло и во други компании ќе се префрли од пишување код кон управување со агентска работа. Возбудливиот дел е што бариерата за експериментирање со овие системи на агенти за кодирање сега е изненадувачки ниска. Можете едноставно да градите работи со Codex.
Поздрави до заедницата
Воодушевени сме што ја гледаме инженерската заедница како го користи Symphony во неделите по објавувањето, при што заклучно со 23 април има собрано повеќе од 15K ѕвезди на GitHub(се отвора во нов прозорец).