„Codex“ karkaso atrakinimas: kaip sukūrėme „App Server“
Celia Chen, techninio personalo narė
„OpenAI“ programavimo agentas „Codex“ veikia daugelyje skirtingų aplinkų: interneto programoje(atsidaro naujame lange), CLI(atsidaro naujame lange), IDE plėtinyje(atsidaro naujame lange) ir naujoje „Codex“ programoje, skirtoje „macOS“. Iš esmės juos visus valdo tas pats „Codex“ karkasas – agento ciklas ir logika, kuria grindžiamos visos „Codex“ patirtys. Svarbiausia grandis, jungianti juos? „Codex App Server“(atsidaro naujame lange) – klientui patogus dvikryptis JSON-RPC1 API.
Šiame įraše pristatysime „Codex App Server“; pasidalysime savo ligšiolinėmis įžvalgomis apie geriausius būdus integruoti „Codex“ galimybes į savo produktą, kad padėtumėte naudotojams gerokai patobulinti savo darbo eigas. Aptarsime „App Server“ architektūrą ir protokolą, kaip jis integruojasi su skirtingomis „Codex“ aplinkomis, taip pat patarimus, kaip pasitelkti „Codex“, nesvarbu, ar norite paversti „Codex“ kodo recenzentu, SRE agentu ar programavimo asistentu.
Prieš neriant į architektūrą, naudinga žinoti „App Server“ priešistorę. Iš pradžių „App Server“ buvo praktiškas būdas pakartotinai naudoti „Codex“ karkasą įvairiuose produktuose, kuris palaipsniui tapo mūsų standartiniu protokolu.
„Codex“ CLI prasidėjo kaip TNS (terminalo naudotojo sąsaja), o tai reiškia, kad „Codex“ pasiekiamas per terminalą. Kurdami „VS Code“ plėtinį (IDE patogesnį būdą sąveikauti su „Codex“ agentais), turėjome rasti būdą naudoti tą patį karkasą, kad galėtume valdyti tą patį agento ciklą iš IDE naudotojo sąsajos, jo neįgyvendindami iš naujo. Tai reiškė, kad reikėjo palaikyti sudėtingesnius sąveikos modelius nei užklausa ir atsakymas, pavyzdžiui, darbo srities tyrinėjimą, eigos transliavimą agentui mąstant ir skirtumų siuntimą. Pirmiausia eksperimentavome atverdami „Codex“ kaip MCP serverį(atsidaro naujame lange), tačiau palaikyti MCP semantiką taip, kad ji tiktų „VS Code“, pasirodė sudėtinga. Vietoj to pristatėme JSON-RPC protokolą, atkartojantį TUI ciklą, kuris tapo neoficialia pirmąja „App Server“ versija(atsidaro naujame lange). Tuo metu nesitikėjome, kad kiti klientai priklausys nuo „App Server“, todėl jis nebuvo sukurtas kaip stabilus API.
Per kelis kitus mėnesius augant „Codex“ naudojimui, vidinės komandos ir išorės partneriai norėjo galimybės įterpti tą patį karkasą į savo produktus, kad paspartintų savo naudotojų programinės įrangos kūrimo darbo eigas. Pavyzdžiui, „JetBrains“ ir „Xcode“ norėjo IDE lygio agento patirties, o „Codex“ kompiuterio programai reikėjo lygiagrečiai orkestruoti daugelį „Codex“ agentų. Šie reikalavimai paskatino mus sukurti platformos aplinką, kuria ilgą laiką galėtų saugiai pasikliauti tiek mūsų produktai, tiek partnerių integracijos. Ji turėjo būti lengvai integruojama ir suderinama su senesnėmis versijomis, o tai reiškia, kad galėtume tobulinti protokolą nesutrikdydami esamų klientų veiklos.
Toliau apžvelgsime, kaip sukūrėme architektūrą ir protokolą, kad skirtingi klientai galėtų naudoti tą patį karkasą.
Pirmiausia atidžiau pažvelkime į tai, kas yra „Codex“ karkaso viduje ir kaip „Codex App Server“ atveria jį klientams. Paskutiniame „Codex“ tinklaraščio įraše išskaidėme pagrindinį agento ciklą, orkestruojantį sąveiką tarp naudotojo, modelio ir įrankių. Tai yra pagrindinė „Codex“ karkaso logika, tačiau visapusiška agento patirtis apima daugiau.
1. Gijos gyvavimo ciklas ir išlikimas. Gija – tai „Codex“ pokalbis tarp naudotojo ir agento. „Codex“ sukuria, atnaujina, atšakoja ir archyvuoja gijas bei išsaugo įvykių istoriją, kad klientai galėtų vėl prisijungti ir matyti nuoseklią laiko juostą.
2. Konfigūracija ir tapatybės nustatymas. „Codex“ įkelia konfigūraciją, valdo numatytąsias nuostatas ir vykdo tapatybės nustatymo eigas, pvz., „Sign in with ChatGPT“ (Prisijungti naudojant „ChatGPT“), įskaitant kredencialų būseną.
3. Įrankių vykdymas ir plėtiniai. „Codex“ vykdo apvalkalo / failų įrankius smėlio dėžėje ir prijungia integracijas, pvz., MCP serverius ir įgūdžius, kad jie galėtų dalyvauti agento cikle pagal nuoseklų politikos modelį.
Visa čia paminėta agento logika, įskaitant pagrindinį agento ciklą, yra „Codex“ CLI kodų bazės dalyje, vadinamoje „Codex core(atsidaro naujame lange)“. „Codex core“ yra ir biblioteka, kurioje yra visas agento kodas, ir vykdymo aplinka, kurią galima paleisti agento ciklui vykdyti ir vienos „Codex“ gijos (pokalbio) išsaugojimui valdyti.
Kad „Codex“ karkasas būtų naudingas, jis turi būti prieinamas klientams. Čia į pagalbą ateina „App Server“.
„App Server“ yra ir JSON-RPC protokolas tarp kliento ir serverio, ir ilgai veikiantis procesas, kuriame talpinamos „Codex core“ gijos. Kaip matome iš aukščiau pateiktos diagramos, „App Server“ procesą sudaro keturi pagrindiniai komponentai: „stdio“ skaitytuvas, „Codex“ pranešimų procesorius, gijų tvarkytuvė ir pagrindinės sesijos. Gijų tvarkytuvė paleidžia po vieną pagrindinę sesiją kiekvienai gijai, o „Codex“ pranešimų procesorius tada tiesiogiai bendrauja su kiekviena pagrindine sesija, kad pateiktų kliento užklausas ir gautų atnaujinimus.
Viena kliento užklausa gali lemti daugybę įvykių atnaujinimų, ir būtent šie detalūs įvykiai leidžia mums kurti turtingą naudotojo sąsają „App Server“ pagrindu. Be to, „stdio“ skaitytuvas ir „Codex“ pranešimų procesorius veikia kaip vertimo sluoksnis tarp kliento ir „Codex core“ gijų. Jie verčia kliento JSON-RPC užklausas į „Codex core“ operacijas, klausosi „Codex core“ vidinio įvykių srauto ir transformuoja tuos žemo lygio įvykius į nedidelį stabilių, NS paruoštų JSON-RPC pranešimų rinkinį.
JSON-RPC protokolas tarp kliento ir „App Server“ yra visiškai dvikryptis. Įprastą giją sudaro kliento užklausa ir daugybė serverio pranešimų. Be to, serveris gali inicijuoti užklausas, kai agentui reikia įvesties, pavyzdžiui, patvirtinimo, ir tada pristabdyti etapą, kol klientas atsakys.
Toliau išskaidysime pokalbio pirminius elementus – „App Server“ protokolo pagrindinius blokus. Sukurti API agento ciklui yra sudėtinga, nes naudotojo ir agento sąveika nėra paprasta užklausa ir atsakymas. Viena naudotojo užklausa gali išsiskleisti į susistemintą veiksmų seką, kurią klientas turi tiksliai atvaizduoti: naudotojo įvestį, agento laipsnišką eigą, proceso metu sukurtus artefaktus (pvz., skirtumus). Kad šį sąveikos srautą būtų lengva integruoti ir jis būtų atsparus įvairiose NS, pasirinkome tris pagrindinius pirminius elementus su aiškiomis ribomis ir gyvavimo ciklais:
1. Elementas: elementas yra „Codex“ įvesties / išvesties atominis vienetas. Elementai turi tipus (pvz., naudotojo žinutė, agento žinutė, įrankio vykdymas, patvirtinimo užklausa, skirtumas) ir kiekvienas turi aiškų gyvavimo ciklą:
item/started, kai elementas prasideda;- pasirenkami
item/*/deltaįvykiai, kai turinys perduodamas srautu (srautu perduodamiems elementų tipams); item/completed, kai elementas užbaigiamas su galutiniu duomenų rinkiniu.
Šis gyvavimo ciklas leidžia klientams pradėti atvaizdavimą iškart gavus started, , transliuoti laipsniškus atnaujinimus gavus delta ir užbaigti gavus completed.
2. Etapas: etapas yra vienas agento darbo vienetas, inicijuotas naudotojo įvesties. Jis prasideda, kai klientas pateikia įvestį (pavyzdžiui, „run tests and summarize failures“ (paleisk testus ir apibendrink nesėkmes)), ir baigiasi, kai agentas baigia kurti išvestis tai įvesčiai. Etapą sudaro elementų seka, reiškianti tarpinius žingsnius ir proceso metu sukurtas išvestis.
3. Gija: gija yra ilgalaikė talpykla vykstančiai „Codex“ sesijai tarp naudotojo ir agento. Ją sudaro keli etapai. Gijos gali būti sukuriamos, atnaujinamos, atšakojamos ir archyvuojamos. Gijos istorija išsaugoma, kad klientai galėtų vėl prisijungti ir matyti nuoseklią laiko juostą.
Dabar pažvelgsime į supaprastintą pokalbį tarp kliento ir agento, kur pokalbis vaizduojamas pirminiais elementais.
Pokalbio pradžioje klientas ir serveris turi atlikti initialize pasisveikinimą. Klientas privalo išsiųsti vieną initialize užklausą prieš bet kurį kitą metodą, o serveris patvirtina atsakymu. Tai suteikia serveriui galimybę paskelbti apie galimybes ir leidžia abiem pusėms susitarti dėl protokolo versijų, funkcijų žymų ir numatytųjų nuostatų prieš pradedant realų darbą. Štai „OpenAI“ „VS Code“ plėtinio naudingosios apkrovos pavyzdys:
Štai ką grąžina serveris:
Kai klientas pateikia naują užklausą, jis pirmiausia sukuria giją, o tada etapą. Serveris atsiųs pranešimus apie eigą (thread/started ir turn/started). Jis taip pat atsiųs įvestis, kurias registruoja kaip elementus, pavyzdžiui, šią naudotojo žinutę.
Įrankių kvietimai taip pat siunčiami atgal klientui kaip elementai. Be to, serveris gali paprašyti kliento patvirtinimo prieš vykdydamas veiksmą, išsiųsdamas serverio užklausą. Patvirtinimas pristabdys etapą, kol klientas atsakys „allow“ (leisti) arba „deny“ (atmesti). Štai kaip atrodo patvirtinimo eiga „VS Code“ plėtinyje:

Galiausiai serveris išsiunčia agento žinutę ir užbaigia etapą su turn/completed. Agento žinutės delta įvykiai siunčia žinutės dalis srautu atgal, kol žinutė užbaigiama su item/completed.
Diagramoje esančios žinutės yra supaprastintos, kad būtų lengviau skaityti. Jei norite pamatyti viso etapo JSON, galite paleisti bandomąjį klientą iš „Codex“ CLI saugyklos:
Dabar pažvelkime, kaip skirtingos klientų aplinkos įterpia „Codex“ per „App Server“. Aptarsime tris modelius: vietines programas ir IDE, „Codex“ interneto vykdymo aplinką ir TNS.
Visais trimis atvejais duomenys perduodami naudojant JSON-RPC per „stdio“ (JSONL). JSON-RPC leidžia paprastai sukurti klientų sąsajas pasirinkta kalba. „Codex“ aplinkos ir partnerių integracijos įgyvendino „App Server“ klientus įvairiomis kalbomis, įskaitant „Go“, „Python“, „TypeScript“, „Swift“ ir „Kotlin“. Naudojant „TypeScript“, apibrėžtis galima sugeneruoti tiesiogiai iš „Rust“ protokolo vykdant:
Kitoms kalboms galite sugeneruoti JSON schemų rinkinį ir pateikti jį pasirinktam kodo generatoriui vykdydami:

Vietiniai klientai paprastai įtraukia arba atsisiunčia konkrečiai platformai skirtą „App Server“ dvejetainį failą, paleidžia jį kaip ilgai veikiantį antrinį procesą ir palaiko atvirą dvikryptį „stdio“ kanalą JSON-RPC ryšiui. Pavyzdžiui, mūsų „VS Code“ plėtinyje ir kompiuterio programoje pristatomas artefaktas apima platformai skirtą „Codex“ dvejetainį failą ir yra susietas su patikrinta versija, kad klientas visada naudotų tiksliai tuos bitus, kuriuos patvirtinome.
Ne kiekviena integracija gali dažnai siųsti klientų atnaujinimus. Kai kurie partneriai, pvz., „Xcode“, atskiria išleidimo ciklus išlaikydami klientą stabilų ir leisdami jam prireikus nukreipti į naujesnį „App Server“ dvejetainį failą. Taip jie gali pritaikyti serverio patobulinimus (pavyzdžiui, geresnį automatinį sutankinimą „Codex core“ arba naujai palaikomus konfigūracijos raktus) ir diegti klaidų pataisymus nelaukdami kliento išleidimo. „App Server“ JSON-RPC aplinka sukurta taip, kad būtų suderinama su senesnėmis versijomis, todėl senesni klientai gali saugiai bendrauti su naujesniais serveriais.

„Codex Web“ naudoja „Codex“ karkasą, bet vykdo jį programinėje vykdymo aplinkoje (konteineryje). Darbinis procesas paruošia konteinerį su atsiųsta darbo sritimi, paleidžia jame „App Server“ dvejetainį failą ir palaiko ilgalaikį JSON-RPC ryšį per „stdio“2 kanalą. Interneto programa (veikianti naudotojo naršyklės kortelėje) bendrauja su „Codex“ vidine sistema per HTTP ir SSE, kurie srautu perduoda darbinio proceso sugeneruotus užduoties įvykius. Tai išlaiko naršyklės NS lengvą, kartu užtikrinant nuoseklų vykdymą tiek kompiuteryje, tiek internete.
Kadangi interneto sesijos yra trumpalaikės (kortelės užsidaro, tinklas nutrūksta), interneto programa negali būti ilgai trunkančių užduočių tiesos šaltinis. Būsenos ir eigos laikymas serveryje reiškia, kad darbas tęsiamas net dingus kortelei. Srautinis protokolas ir išsaugotos gijų sesijos leidžia lengvai prisijungti naujai sesijai, tęsti darbą nuo ten, kur jis buvo baigtas, ir pasivyti neatkuriant būsenos kliente.

Istoriškai TUI buvo „tikrasis“ klientas, veikiantis tame pačiame procese kaip ir agento ciklas ir bendraujantis tiesiogiai su „Rust“ pagrindiniais tipais, o ne per „app-server“ protokolą. Tai leido ankstyvosioms iteracijoms būti greitoms, bet kartu pavertė TNS specialiu atveju.
Dabar, kai yra „App Server“, planuojame pertvarkyti TNS(atsidaro naujame lange), kad ji naudotų jį taip, kaip bet kuris kitas klientas: paleistų „App Server“ antrinį procesą, bendrautų JSON-RPC per „stdio“ ir atvaizduotų tuos pačius srautinius įvykius bei patvirtinimus. Tai atveria darbo eigas, kuriose TUI gali prisijungti prie „Codex“ serverio, veikiančio nuotoliniame įrenginyje, laikant agentą arti skaičiavimo išteklių ir tęsiant darbą net nešiojamajam kompiuteriui užmigus ar atsijungus, kartu pateikiant tiesioginius atnaujinimus ir valdiklius vietoje.
„Codex App Server“ bus pagrindinis integravimo metodas, kurį palaikysime ateityje, tačiau yra ir kitų metodų su labiau ribotu funkcionalumu. Pagal numatytąją praktiką rekomenduojame klientams naudoti „Codex App Server“ integracijai su „Codex“, tačiau verta pasidomėti skirtingais integravimo metodais ir suprasti jų privalumus bei trūkumus. Toliau pateikiami dažniausi būdai valdyti „Codex“ ir kada kiekvienas iš jų gali būti tinkamas.
Vykdykite codex mcp-server(atsidaro naujame lange) ir prisijunkite iš bet kurio MCP kliento, palaikančio „stdio“ serverius (pvz., „OpenAI Agents SDK“(atsidaro naujame lange)). Tai tinkamas pasirinkimas, jei jau turite MCP pagrįstą darbo eigą ir norite iškviesti „Codex“ kaip iškviečiamą įrankį. Trūkumas tas, kad gaunate tik tai, ką atveria MCP, todėl specifinės „Codex“ sąveikos, priklausančios nuo turtingesnės sesijos semantikos (pvz., skirtumų atnaujinimai), gali būti netiksliai atvaizduojamos per MCP prieigos taškus.
Kai kurios ekosistemos siūlo perkeliamą sąsają, kuri gali būti taikoma keliems modelių teikėjams ir vykdymo aplinkoms. Tai gali būti geras pasirinkimas, jei norite vienos abstrakcijos, koordinuojančios kelis agentus. Kompromisas tas, kad šie protokolai dažnai susijungia į bendrą galimybių poaibį, todėl gali būti sunku atvaizduoti turtingesnes sąveikas, ypač kai svarbi konkretaus teikėjo įrankių ir sesijos semantika. Ši erdvė sparčiai vystosi, ir tikimės, kad atsiras daugiau bendrų standartų, kai išsiaiškinsime geriausius pirminius elementus realaus pasaulio agentų darbo eigoms atvaizduoti (įgūdžiai(atsidaro naujame lange) yra geras to pavyzdys).
Rinkitės „App Server“, kai norite viso „Codex“ karkaso, pateikiamo kaip stabilus, NS pritaikytas įvykių srautas. Gaunate tiek visą agento ciklo funkcionalumą, tiek kitas pagalbines funkcijas, tokias kaip „Sign in with ChatGPT“, modelių paieška ir konfigūracijos valdymas. Pagrindinė kaina yra integravimo darbas, nes reikia sukurti kliento pusės JSON-RPC sąsają savo kalba. Tačiau praktiškai „Codex“ gali atlikti didžiąją dalį sunkaus darbo, jei pateiksite jam JSON schemą ir dokumentaciją. Daugelis komandų, su kuriomis dirbome, sugebėjo greitai sukurti veikiančią integraciją naudodamos „Codex“.Kiti būdai įterpti „Codex“
Lengvas, scenarijais valdomas CLI režimas vienkartinėms užduotims ir CI vykdymui. Tai geras pasirinkimas automatizavimui ir konvejeriams, kai norite, kad viena komanda būtų vykdoma iki pabaigos neinteraktyviai, perduotų struktūruotą išvestį žurnalams ir išeitų su aiškiu sėkmės ar nesėkmės signalu.
„TypeScript“ biblioteka, skirta programiškai valdyti vietinius „Codex“ agentus iš savo programos. Geriausia, kai norite vietinės bibliotekos sąsajos serverio pusės įrankiams ir darbo eigoms, nekurdami atskiro JSON-RPC kliento. Kadangi ji buvo išleista anksčiau nei „App Server“, šiuo metu ji palaiko mažiau kalbų ir apima mažesnę sritį. Jei bus kūrėjų susidomėjimas, galime pridėti papildomų SDK, apimančių „App Server“ protokolą, kad komandos galėtų apimti daugiau karkaso galimybių nerašydamos JSON-RPC sąsajų.
Šiame įraše pasidalijome, kaip kuriame naują standartą sąveikai su agentais ir kaip paversti „Codex“ karkasą stabiliu, klientams patogiu protokolu. Aptarėme, kaip „App Server“ atveria „Codex core“, leidžia klientams valdyti visą agento ciklą ir įgalina daugybę aplinkų, įskaitant TNS, vietines IDE integracijas ir interneto vykdymo aplinką.
Jei tai sukėlė idėjų, kaip integruoti „Codex“ į savo darbo eigas, verta išbandyti „App Server“. Visas pirminis kodas yra „Codex“ CLI atvirojo kodo saugykloje(atsidaro naujame lange). Drąsiai dalinkitės atsiliepimais ir funkcijų užklausomis. Džiaugiamės galėdami jus išgirsti ir toliau daryti agentus prieinamesnius visiems.
Autorius
Padėkos
Ypatingas ačiū Michaelui Bolinui, Owenui Linui, Ericui Trautui ir Rasmusui Rygaardui, prisidėjusiems prie šio įrašo, ir visai „Codex“ komandai, dirbusiai prie „App Server“.
Pastabos
- 1
Naudojame „JSON‑RPC lite“ variantą: jis išlaiko užklausos / atsakymo / pranešimo formą, bet praleidžia
„jsonrpc“: „2.0“antraštę ir yra suformuotas kaip JSONL per „stdio“, o ne griežtas „JSON‑RPC 2.0“. - 2
„stdio“ reiškia „app-server“ „stdin“ / „stdout“ konteinerio viduje. Prieglobos sąrankose šie srautai dažnai tuneliuojami per nuolatinį tinklo ryšį (pvz., panašų į „WebSocket“) į konteinerio vykdymo aplinką, todėl tai veikia kaip „stdio“, net jei tai nėra tiesioginis vietinis vamzdis.


