Codex-orkestroinnin avoimen lähdekoodin spesifikaatio: Symphony
Alex Kotliarskyi, Victor Zhu ja Zach Brock
Kuusi kuukautta sitten sisäistä tuottavuustyökalua rakentaessamme tiimimme teki kiistanalaisen (ainakin silloin) päätöksen: rakentaisimme repositoriomme ilman ihmisten kirjoittamaa koodia. Projektirepositoriomme jokaisen rivin piti olla Codexin generoima.
Jotta tämä toimisi, suunnittelimme ohjelmistokehityksen työnkulun alusta asti uusiksi. Rakensimme agenteille sopivan repositorion, panostimme voimakkaasti automatisoituihin testeihin ja suojakaiteisiin ja kohtelimme Codexia täysiverisenä tiimikaverina. Dokumentoimme tämän matkan aiemmassa blogikirjoituksessamme testauskehityksestä.
Ja se toimi, mutta sitten kohtasimme seuraavan pullonkaulan: kontekstin vaihtamisen.
Ratkaistaksemme tämän uuden ongelman rakensimme järjestelmän nimeltä Symphony. Symphony(avautuu uudessa ikkunassa) on agenttien orkestroija, joka muuttaa Linearin kaltaisen projektinhallintataulun koodausagenttien ohjaustasoksi. Jokainen avoin tehtävä saa agentin, agentit toimivat jatkuvasti, ja ihmiset tarkastavat tulokset.
Tässä kirjoituksessa kerromme, miten loimme Symphonyn – mikä johti joissakin tiimeissä 500 %:n kasvuun käyttöön hyväksytyissä pull request -pyynnöissä – ja miten voit käyttää sitä muuttaaksesi oman vikaseurantajärjestelmäsi jatkuvasti toimivaksi agenttien koordinoijaksi.
Interaktiivisten koodausagenttien yläraja
Vaikka niiden käyttö helpottuu, koodausagentit – käytettiinpä niitä web-sovellusten tai CLI:n kautta – ovat yhä interaktiivisia työkaluja.
Kun agenttityön mittakaava kasvoi OpenAIlla, huomasimme uudenlaisen rasitteen. Jokainen insinööri avasi muutaman Codex-istunnon, antoi tehtäviä, tarkasti tulokset, ohjasi agenttia ja toisti saman. Käytännössä useimmat pystyivät hallitsemaan mukavasti kolmesta viiteen istuntoa kerrallaan ennen kuin kontekstin vaihtamisesta tuli tuskallista. Sen jälkeen tuottavuus laski. Unohdimme, mikä istunto teki mitä, hyppäsimme terminaalien välillä palauttaaksemme agentit raiteilleen ja korjasimme pitkään käynnissä olleita tehtäviä, jotka olivat jumittuneet puoliväliin.
Agentit olivat nopeita, mutta järjestelmässämme oli pullonkaula: ihmisten huomio. Olimme käytännössä rakentaneet tiimin erittäin kyvykkäitä juniori-insinöörejä ja määränneet sitten ihmisinsinöörimme valvomaan heidän työtään yksityiskohtaisesti. Se ei ollut skaalautuva ratkaisu.
Näkökulman muutos
Ymmärsimme optimoivamme väärää asiaa. Rakensimme järjestelmämme koodausistuntojen ja yhdistettyjen PR:ien ympärille, vaikka PR:t ja istunnot ovat oikeasti vain keino päästä tavoitteeseen. Ohjelmistokehityksen työnkulut rakentuvat pääasiassa tuloksille: ongelmille, tehtäville, tukipyynnöille ja välitavoitteille.
Niinpä kysyimme itseltämme, mitä tapahtuisi, jos lakkaisimme valvomasta agentteja suoraan ja antaisimme niiden sen sijaan vetää työtä tehtävänseurannastamme.
Tuosta ideasta syntyi Symphony, kirjallinen spesifikaatio, joka toimii valvojana agenttien toiminnan koordinoinnissa.
Vikaseurannan muuttaminen agenttien koordinointijärjestelmäksi
Symphony alkoi yksinkertaisesta ajatuksesta: minkä tahansa avoimen tehtävän pitäisi päätyä agentin hoidettavaksi ja valmistua sen toimesta. Sen sijaan että hallitsimme Codex-istuntoja useissa välilehdissä, teimme ongelmienseurannasta hallintaympäristön.
Tässä asetelmassa jokainen avoin lineaarinen ongelma vastaa omaa agenttityötilaa. Symphony seuraa tehtävätaulua jatkuvasti ja varmistaa, että jokaisella aktiivisella tehtävällä on agentti mukana prosessissa, kunnes se on valmis. Jos agentti kaatuu tai jumittuu, Symphony käynnistää sen uudelleen. Jos uutta työtä ilmestyy, Symphony ottaa sen hoitaakseen ja alkaa järjestellä työtä.
Rakensimme työnkulkumme tukipyyntöjen tilojen varaan käyttäen tehtävienhallintatyökalu Linearia tilakoneena.
Käytännössä Symphony irrottaa työn istunnoista ja muutospyynnöistä. Jotkin ongelmat tuottavat useita PR:iä eri repositorioihin; toiset taas ovat puhdasta selvitystyötä tai analyysiä, joka ei koskaan koske koodipohjaa.
Kun työ on jaoteltu tällä tavalla, työpisteet voivat edustaa huomattavasti laajempia työyksiköitä.
Käytämme Symphonya säännöllisesti monimutkaisten ominaisuuksien ja infrastruktuurimigraatioiden orkestrointiin. Saatamme esimerkiksi luoda tehtävän, jossa agenttia pyydetään analysoimaan koodipohjaa, Slackia tai Notionia ja tuottamaan toteutussuunnitelma. Kun olemme tyytyväisiä suunnitelmaan, agentti generoi tehtäväpuun, joka pilkkoo työn vaiheisiin ja määrittelee tehtävien väliset riippuvuudet.
Agentit alkavat työstää vain tehtäviä, jotka eivät ole estyneitä, joten suoritus etenee luontevasti ja optimaalisesti rinnakkain tässä DAG:ssa (suoritusaskelten sarja). Alla olevassa esimerkissä merkitsimme React-päivityksen estyneeksi, kunnes migraatio Viteen on tehty. Kuten odotettua, agentit alkoivat päivittää Reactia vasta sen jälkeen, kun migraatio Viteen oli valmis.
Agentit voivat myös luoda työtä itse. Toteutuksen tai katselmoinnin aikana ne huomaavat usein parannuksia, jotka jäävät nykyisen tehtävän laajuuden ulkopuolelle: suorituskykyongelman, refaktorointimahdollisuuden tai paremman arkkitehtuurin. Kun näin tapahtuu, ne vain luovat uuden ilmoituksen, jonka voimme arvioida ja aikatauluttaa myöhemmin – monet näistä jatkotehtävistä päätyvät myös agenttien hoidettaviksi. Vaikka valvomme tätä prosessia, agentit pitävät työn järjestyksessä ja vievät sitä eteenpäin.
Tämä työskentelytapa vähentää dramaattisesti epäselvän työn käynnistämisen kognitiivista kuormaa. Jos agentti tekee jotain väärin, sekin on hyödyllistä tietoa, ja kustannus meille on lähes nolla. Voimme hyvin halvalla luoda agentille tukipyyntöjä prototypointia ja tutkimista varten ja hylätä kaikki tutkimussuunnat, joista emme pidä.
Koska orkestroija toimii devboxeilla eikä koskaan nuku, voimme lisätä tehtäviä mistä tahansa ja tietää, että agentti poimii ne. Esimerkiksi yksi tiimimme insinööreistä teki kolme merkittävää muutosta puhelimensa Linear-sovelluksesta mukavasta mökistä käsin heikolla wifi-yhteydellä.
Tämän työskentelytavan lisäämä tutkiminen
Kun tarkastelimme Symphonyn kanssa työskentelyn vaikutuksia, ilmeisin muutos oli tuotoksissa. Joissakin OpenAI:n tiimeissä näimme käyttöön hyväksyttyjen PR:ien määrän kasvavan kuusinkertaiseksi kolmen ensimmäisen viikon aikana. OpenAI:n ulkopuolella Linearin perustaja Karri Saarinen nosti Symphonyn julkaisun yhteydessä esiin piikin luotujen työtilojen määrässä(avautuu uudessa ikkunassa). Syvempi muutos on kuitenkin siinä, miten tiimit ajattelevat työtä.
Kun insinöörimme eivät enää käytä aikaa Codex-istuntojen valvomiseen, koodimuutosten talous muuttuu täysin. Kunkin muutoksen koettu kustannus laskee, koska emme enää sijoita ihmistyötä itse toteutuksen ohjaamiseen.
Se muutti käyttäytymistämme. Spekulatiivisten tehtävien käynnistäminen Symphonyssa on muuttunut helpoksi. Kokeile ideaa, tutki refaktorointia, testaa hypoteesia ja säilytä vain lupaavilta näyttävät tulokset.
Se myös laajentaa sitä, kuka voi käynnistää työtä. Tuotepäällikkömme ja suunnittelijamme voivat nyt tehdä ominaisuuspyyntöjä suoraan Symphonyyn. Heidän ei tarvitse ladata koodivarastoa tai hallinnoida Codex-istuntoa. He kuvaavat ominaisuuden ja saavat vastaukseksi katselmointipaketin, joka sisältää videokierroksen ominaisuuden toiminnasta oikeassa tuotteessa.
Symphony loistaa myös suurissa monorepoissa (kuten meillä OpenAIlla), joissa PR:n maaliin viemisen viimeinen maili on hidas ja hauras. Järjestelmä seuraa CI:tä, suorittaa rebase-toimenpiteiä tarvittaessa, ratkaisee konfliktit, yrittää uudelleen epävakaat tarkistukset ja yleisesti paimentaa muutokset prosessin läpi. Siihen mennessä kun tukipuyyntö saavuttaa tilan Merging, meillä on suuri varmuus siitä, että muutos päätyy päähaaraan ilman ihmisen vahtimista.
Edistys tuo mukanaan uusia, erilaisia ongelmia
Tällä tasolla toimimiseen liittyy kompromisseja. Kun siirryimme agenttien interaktiivisesta ohjaamisesta työn antamiseen niille tukipyyntötasolla, menetimme mahdollisuuden töniä niitä jatkuvasti kesken työn ja korjata suuntaa tarvittaessa. Joskus agentti tuotti jotain, mikä meni täysin ohi maalin. Sekin oli hyödyllistä – nämä epäonnistumiset paljastivat aukkoja järjestelmässä ja auttoivat meitä tekemään siitä vankemman.
Sen sijaan että olisimme paikanneet tuloksen käsin, lisäsimme suojakaiteita ja taitoja, jotta agentit onnistuisivat seuraavalla kerralla. Ajan myötä tämä johti siihen, että lisäsimme agenttikehykseemme uusia kyvykkyyksiä, kuten end-to-end-testien ajamisen, sovelluksen ohjaamisen Chrome DevToolsin kautta ja QA-savukokeiden hallinnan. Paransimme dokumentaatiotamme merkittävästi ja selkeytimme, miltä hyvä näyttää.
Kaikki tehtävät eivät sovi Symphonyn tyyppiseen työskentelyyn. Jotkin ongelmat vaativat yhä insinöörejä, jotka työskentelevät suoraan interaktiivisten Codex-istuntojen kanssa, erityisesti monitulkintaiset ongelmat tai työ, joka vaatii vahvaa harkintaa ja asiantuntemusta. Käytännössä nämä ovat yleensä kiinnostavimpia ja miellyttävimpiä tehtäviä, joihin insinöörimme käyttävät aikaansa.
Erona on se, että Symphony voi hoitaa rutiininomaisen toteutustyön massan. Näin insinöörit voivat keskittyä yhteen vaikeaan ongelmaan kerrallaan sen sijaan, että vaihtaisivat jatkuvasti kontekstia pienempien tehtävien välillä.
Opimme myös, ettei agenttien käsitteleminen jäykkinä solmuina tilakoneessa toimi hyvin. Mallit kehittyvät yhä älykkäämmiksi ja pystyvät ratkaisemaan suurempia ongelmia kuin mihin yritämme ne ahtaa. Esimerkiksi varhaisissa versioissa kaikki GitHub-integraatiot olivat osa ulkoista kehystä – esimerkiksi varhaiset versiot odottivat Codexin tekevän vain koodimuutoksia ja määrittelivät muun prosessin (muutosten lähettäminen, testien ajaminen) koodissa. Varhaisissa agenttityön versioissamme pyysimme Codexia vain toteuttamaan tehtävän. Tämä lähestymistapa osoittautui liian rajoittavaksi. Codex pystyy täysin luomaan useita PR:iä sekä lukemaan katselmointipalautetta ja korjaamaan sen perusteella. Niinpä annoimme sille työkaluja – gh-CLI:n, taitoja lukea CI-lokeja jne. – ja nyt voimme pyytää Codexia tekemään enemmän, kuten sulkemaan vanhoja PR:iä tai vetämään raportteja valmiista vs. hylätyistä töistä. Tällaiset tehtävät olivat kaukana alkuperäisen ominaisuustoteutuksen laatikon ulkopuolella.
Lopulta siirryimme siis antamaan agenteille tiukkojen siirtymien sijaan tavoitteita, samaan tapaan kuin hyvä esihenkilö antaisi tavoitteen tiiminsä suoralle alaiselle. Mallien voima tulee niiden kyvystä päätellä, joten anna niille työkalut ja konteksti ja anna niiden kokata.
Symphonyn käyttäminen Symphonyn rakentamiseen
Kun avaat Symphony-repositorion, ensimmäinen asia jonka huomaat on, että Symphony on teknisesti vain SPEC.md-tiedosto – ongelman ja tarkoitetun ratkaisun määritelmä. Monimutkaisen valvontajärjestelmän rakentamisen sijaan määrittelimme ongelman ja aiotut ratkaisut ja annoimme agenteille korkean tason ohjausta.
Referenssitoteutus on kirjoitettu Elixirillä – koska kun koodi on käytännössä ilmaista, voit vihdoin valita kielet niiden vahvuuksien perusteella, kuten Elixirin rinnakkaisuuden – mutta ydinidea voidaan ilmaista yksinkertaisessa merkintädokumentissa. Kannustamme sinua ohjaamaan suosikkikoodausagenttisi spesifikaation pariin ja pyytämään sitä toteuttamaan oman versionsa.
Symphonyn ensimmäinen versio oli vain tmuxissa pyörivä Codex-istunto, joka pollasi Linearia ja käynnisti aliagentteja uusille tehtäville. Se toimi, mutta ei ollut erityisen luotettava. Toinen versio eli pääprojektimme repositoriossa, joka oli rakennettu agentteja ajatellen. Olimme jo rakentaneet agenttikehyksen antamaan agenteille taidot ja kontekstin tehdä laadukasta työtä tässä repositoriossa, joten Symphony vain yhdistää kaiken.
Kun perustoiminnallisuus oli olemassa, käytimme Symphonya Symphonyn rakentamiseen.
Kun esittelimme sisäisesti järjestelmän, jolla hallitaan tehtäviä ja liitetään niihin todistusvideot, reaktio oli erittäin myönteinen: Symphony-projektikanavamme kasvoi, ja tiimit eri puolilla organisaatiota alkoivat käyttää sitä spontaanisti. Sisäinen tuotteen ja markkinoiden yhteensopivuus on OpenAI:ssa edellytys tuotteen julkaisemiselle ulkoisesti. OpenAIlla näkemämme käytön perusteella kävi selväksi, että meidän pitäisi jakaa Symphony myös yrityksen ulkopuolelle.
Niinpä erittelimme idean omaksi SPEC.md:ksi ja pyysimme Codexia toteuttamaan sen. Viitetoteutukseksi valitsimme Elixirin, suhteellisen kapean kohderyhmän kielen, jolla on erinomaiset perusrakenteet rinnakkaisten prosessien koordinointiin ja valvontaan. Codex rakensi Elixir-toteutuksen yhdellä kertaa, ja siitä lähtien jatkoimme sekä spesifikaation että toteutuksen kehittämistä. Spesifikaation hiomiseksi pyysimme Codexia jopa toteuttamaan sen useilla muilla kielillä – TypeScriptillä, Golla, Rustilla, Javalla ja Pythonilla – ja käyttämään tuloksia epäselvyyksien tunnistamiseen ja järjestelmän yksinkertaistamiseen. Se onnistui kaikilla kielillä.
Codexin rakentamisen aikana poistimme paljon satunnaista monimutkaisuutta, kuten riippuvuuksia tietyistä repositorioista tai Linear MCP:stä. Symphony ei enää riipu sisäisistä repositorioistamme tai työnkuluistamme. Peruslähestymistapa yksinkertaistui:
Varmista, että jokaiselle avoimelle tehtävälle on oma työtilansa, jossa agentti toimii.
Sen lisäksi, että se auttaa aktiivisessa työssä, kehitystyönkulku on nyt jotain, minkä agentit tuntevat ja jota ne noudattavat. Kehitystyönkulku – ongelman käsittely, repositorion tarkistaminen, työn asettaminen ”työn alla” -tilaan, jotta projektipäällikkö tietää, että sitä työstetään, pull-pyynnön lisääminen, sen siirtäminen ”Tarkastus”-tilaan, videoiden liittäminen jne. – on nyt tallennettu yksinkertaiseen WORKFLOW.md-tiedostoon. Kaikki tämä oli prosessi, jota ihmiset noudattivat, mutta sitä ei koskaan dokumentoitu. Sen sijaan että nojaisimme tähän implisiittiseen askelsarjaan, dokumentoimme sen nyt, ja Symphony varmistaa, että agentit noudattavat sitä. Näin voimme rakentaa agentteja, jotka työskentelevät rinnallamme. Jos päätämme, että agenttien pitäisi myös liittää itsearviointi valmiiseen työhön, lisäämme sen WORKFLOW.md:hen, ja Symphony ohjaa agentit siihen vaiheeseen.
Saimme myös käyttää Codexia sovelluspalvelintilassa(avautuu uudessa ikkunassa), Codexin sisäänrakennetussa headless-tilassa. Tässä tilassa pystyimme ajamaan Codexia ja keskustelemaan sen kanssa ohjelmallisesti hyvin dokumentoidun JSON-RPC-rajapinnan kautta esimerkiksi säikeen käynnistämistä tai vuoroihin reagoimista varten. Se on paljon kätevämpi ja skaalautuvampi tapa kuin yrittää olla vuorovaikutuksessa Codexin kanssa CLI:n tai live-tmux-istuntojen kautta.
Codex App Server sopi käyttötapaukseemme täydellisesti: hyödynnämme Codexin tarjoamaa kehystä samalla kun meillä on säätimet ja koukut, joihin voimme kytkeytyä. Esimerkiksi jotta Linearin pääsytokenia ei paljastettaisi aliagenteille, käytämme dynaamisia työkalukutsuja(avautuu uudessa ikkunassa) paljastamaan raakaa linear_graphql-funktiota, joka suorittaa mielivaltaisia pyyntöjä Linearia vastaan, ilman että nojaudumme MCP:hen tai paljastamme pääsytokenin konteille.
Mitä seuraavaksi
Symphony on tarkoituksella minimaalinen orkestrointikerros. Julkaisemme sen avoimena lähdekoodina osoittaaksemme Codex App Serverin voiman, kun se yhdistetään erilaisiin työnkulkutyökaluihin, kuten Lineariin. Siksi emme suunnittele ylläpitävämme Symphonya erillisenä tuotteena. Ajattele sitä referenssitoteutuksena. Samalla tavalla kuin monet kehittäjät ohjasivat koodausagenttinsa harness engineering -julkaisun pariin luodakseen repositorioidensa rakenteet, toivomme, että ohjaat suosikkikoodausagenttisi Symphonyn spesifikaatioon(avautuu uudessa ikkunassa) ja repositorion(avautuu uudessa ikkunassa) pariin rakentaaksesi omat ympäristöösi räätälöidyt versiosi.
Voima piilee Codexissa ja sen sovelluspalvelimessa. Symphony oli tapa yhdistää Codex ja Linear, kaksi jo ennestään käyttämäämme asiaa, työnhallinnan ongelman ratkaisemiseksi. Kun koodausagentit paranevat päättelyssä ja ohjeiden noudattamisessa, epäilemme, että myös muissa yrityksissä pullonkaula siirtyy koodin kirjoittamisesta agenttityön hallintaan. Jännittävää on se, että kynnys kokeilla näitä koodausagenttijärjestelmiä on nyt yllättävän matala. Voit vain rakentaa asioita Codexilla.
Yhteisön tervehdykset
On mahtavaa nähdä ohjelmistokehitysyhteisön käyttävän Symphonya julkaisemisen jälkeisinä viikkoina; se on kerännyt 23. huhtikuuta mennessä yli 15 000 GitHub-tähteä(avautuu uudessa ikkunassa).