Codex orkestrasyonu için açık kaynaklı bir spec: Symphony
Yazan: Alex Kotliarskyi, Victor Zhu ve Zach Brock
Altı ay önce, kurum içi bir üretkenlik aracı üzerinde çalışırken ekibimiz o zamanlar tartışmalı sayılan bir karar aldı: depomuzu hiç insan eliyle yazılmış kod olmadan inşa edecektik. Proje depomuzdaki her satırın Codex tarafından üretilmesi gerekiyordu.
Bunu mümkün kılmak için mühendislik iş akışımızı temelden yeniden tasarladık. Ajan dostu bir depo oluşturduk, otomatik testlere ve güvenlik tedbirlerine ciddi yatırım yaptık ve Codex'i tam teşekküllü bir ekip arkadaşı gibi ele aldık. Bu yolculuğu önceki harness engineering hakkındaki blog yazımızda belgeledik.
Ve işe yaradı, ama sonra bir sonraki darboğazla karşılaştık: bağlam değiştirme.
Bu yeni sorunu çözmek için Symphony adını verdiğimiz bir sistem kurduk. Symphony(yeni bir pencerede açılır), Linear gibi bir proje yönetim panosunu kodlama ajanları için bir kontrol düzlemine dönüştüren bir ajan orkestratörüdür. Her açık göreve bir ajan atanır, ajanlar sürekli çalışır ve insanlar sonuçları gözden geçirir.
Bu yazı, Symphony'yi nasıl oluşturduğumuzu (bazı ekiplerde üretime alınan çekme isteklerinde %500 artışla sonuçlanarak) ve kendi issue tracker'ınızı her zaman açık bir ajan orkestratörüne dönüştürmek için bunu nasıl kullanacağınızı açıklıyor.
Etkileşimli kodlama ajanlarının tavanı
Kullanımları kolaylaştıkça bile, kodlama ajanları (ister web uygulamaları ister CLI üzerinden erişilsin) hâlâ etkileşimli araçlardır.
OpenAI'da ajan tabanlı işlerin ölçeği büyüdükçe, yeni tür bir yük keşfettik. Her mühendis birkaç Codex oturumu açıyor, görev atıyor, çıktıyı gözden geçiriyor, ajanı yönlendiriyor ve bunu tekrarlıyordu. Pratikte çoğu kişi, bağlam değiştirme can sıkıcı hale gelmeden önce aynı anda rahatça üç ila beş oturumu yönetebiliyordu. Bunun ötesinde üretkenlik düşüyordu. Hangi oturumun ne yaptığını unutuyor, ajanları yeniden yola sokmak için terminaller arasında atlıyor ve yarıda takılan uzun süreli görevlerde hata ayıklıyorduk.
Ajanlar hızlıydı, ama sistemde bir darboğazımız vardı: insan dikkati. Fiilen son derece yetenekli junior mühendislerden oluşan bir ekip kurmuş, ardından insan mühendislerimizi onları mikro düzeyde yönetmekle görevlendirmiştik. Bunun ölçeklenmeyeceği açıktı.
Bakış açısında değişim
Yanlış şeyi optimize ettiğimizi fark ettik. Sistemimizi kodlama oturumları ve birleştirilen PR'ler etrafında şekillendiriyorduk; oysa PR'ler ve oturumlar gerçekte bir amaç değil, amaca giden araçlardır. Yazılım iş akışları büyük ölçüde teslimatlar etrafında düzenlenir: issue'lar, görevler, destek talepleri, kilometre taşları.
Bu yüzden kendimize şu soruyu sorduk: ajanları doğrudan denetlemeyi bırakıp bunun yerine iş çekmelerine görev takip sistemimizden izin verseydik ne olurdu?
Bu fikir, ajan tabanlı işi orkestre etmek için bir gözetmen işlevi gören yazılı bir spec olan Symphony'ye dönüştü.
Issue tracker'ımızı bir ajan orkestratörüne dönüştürmek
Symphony basit bir kavramla başladı: herhangi bir açık görev, bir ajan tarafından ele alınıp tamamlanmalı. Codex oturumlarını birden fazla sekmede yönetmek yerine, issue tracker'ımızı kontrol düzlemi hâline getirdik.
Bu düzende, her açık Linear meselesi özel bir ajan çalışma alanına eşlenir. Symphony, görev panosunu sürekli izler ve tamamlanana kadar her aktif görevin döngü içinde çalışan bir ajanı olmasını sağlar. Bir ajan çökerse veya takılırsa, Symphony onu yeniden başlatır. Yeni iş ortaya çıkarsa, Symphony bunu alır ve işi organize etmeye başlar.
İş akışımızı destek talepleri durumları üzerine kurduk; görev yöneticisi Linear'ı bir durum makinesi olarak kullandık.
Pratikte Symphony, işi oturumlardan ve çekme isteklerinden ayırır. Bazı issue'lar depolar arasında birden fazla PR üretir; bazılarıysa kod tabanına hiç dokunmayan, yalnızca araştırma veya analizden ibarettir.
İş bu şekilde soyutlandığında, destek talepleri çok daha büyük iş birimlerini temsil edebilir.
Symphony'yi düzenli olarak karmaşık özellikleri ve altyapı geçişlerini orkestre etmek için kullanıyoruz. Örneğin, ajandan kod tabanını, Slack'i veya Notion'ı analiz edip bir uygulama planı üretmesini isteyen bir görev açabiliyoruz. Plandan memnun kaldığımızda, ajan görevlerden oluşan bir ağaç üretip işi aşamalara bölüyor ve görevler arasındaki bağımlılıkları tanımlıyor.
Ajanlar yalnızca engellenmemiş görevlerde çalışmaya başlar; bu yüzden yürütme, bu DAG için (bir yürütme adımları dizisi) doğal ve en iyi şekilde paralel ilerler. Aşağıdaki örnekte React yükseltmesini Vite'a geçişe bağlı olarak engelli işaretledik. Beklendiği gibi, ajanlar React'i ancak Vite'a geçiş tamamlandıktan sonra yükseltmeye başladı.
Ajanlar kendileri de iş oluşturabilir. Uygulama veya inceleme sırasında sık sık mevcut görevin kapsamı dışında kalan iyileştirmeler fark ederler: bir performans sorunu, bir refaktör fırsatı ya da daha iyi bir mimari. Böyle olduğunda, değerlendirebileceğimiz ve daha sonra planlayabileceğimiz yeni bir issue açarlar — bu takip görevlerinin çoğu da ajanlar tarafından ele alınır. Biz bu süreci denetlerken, ajanlar düzenli kalır ve işin ilerlemesini sürdürür.
Bu çalışma biçimi, belirsiz işleri başlatmanın bilişsel maliyetini dramatik biçimde azaltıyor. Ajan bir şeyi yanlış yaparsa, bu yine de yararlı bilgidir ve bize maliyeti neredeyse sıfırdır. Ajanın prototip çıkarması ve keşif yapması için çok düşük maliyetle destek talepleri açabilir, hoşumuza gitmeyen keşifleri de yok edebiliriz.
Orkestratör geliştirme kutularında çalıştığı ve hiç uyumadığı için, her yerden görev ekleyebiliyor ve bir ajanın bunu ele alacağını biliyoruz. Örneğin, ekibimizdeki bir mühendis, kötü bir wifi bağlantısıyla rahat bir kulübede telefonundaki Linear uygulamasından üç önemli değişiklik yaptı.
Bu şekilde çalışmanın keşfi artırması
Symphony ile çalışmanın etkilerini gözlemlerken en belirgin değişim çıktı tarafında oldu. OpenAI'daki bazı ekiplerde, üretime alınan PR sayısının ilk üç haftada 6 kat arttığını gördük. OpenAI dışında, Linear'ın kurucusu Karri Saarinen, Symphony'yi yayımlamamızla birlikte oluşturulan çalışma alanlarında bir sıçramaya(yeni bir pencerede açılır) dikkat çekti. Ancak daha derin değişim, ekiplerin işe nasıl baktığında yatıyor.
Mühendislerimiz artık Codex oturumlarını denetlemek için zaman harcamadığında, kod değişikliklerinin ekonomisi tamamen değişiyor. Her değişikliğin algılanan maliyeti düşüyor; çünkü artık uygulamanın kendisini yönlendirmek için insan emeği harcamıyoruz.
Bu da davranışımızı değiştirdi. Symphony'de spekülatif görevler başlatmak sıradan hale geldi. Bir fikir deneyin, bir refaktörü keşfedin, bir hipotezi test edin ve yalnızca umut vadeden sonuçları tutun.
Ayrıca işi kimin başlatabileceğini de genişletiyor. Ürün yöneticimiz ve tasarımcımız artık özellik taleplerini doğrudan Symphony'ye girebiliyor. Depoyu checkout etmeleri veya bir Codex oturumu yönetmeleri gerekmiyor. Özelliği tarif ediyorlar ve karşılığında, özelliğin gerçek ürün içinde çalıştığını gösteren bir video anlatımını da içeren bir inceleme paketi alıyorlar.
Symphony, ayrıca büyük monorepo'larda da (OpenAI'daki gibi) öne çıkıyor; burada bir PR'yi son aşamada üretime almak yavaş ve kırılgan olabiliyor. Sistem CI'ı izliyor, gerektiğinde rebase yapıyor, çakışmaları çözüyor, kararsız kontrolleri yeniden deniyor ve genel olarak değişiklikleri boru hattı boyunca yönlendiriyor. Bir bilet Merging aşamasına ulaştığında, değişikliğin insan gözetimi olmadan ana dala gireceğine yüksek güven duyuyoruz.
İlerleme, yeni ve farklı sorunlarla gelir
Bu seviyede çalışmanın ödünleşimleri var. Ajanları etkileşimli olarak yönlendirmekten onlara destek talebi düzeyinde iş atamaya geçtiğimizde, ihtiyaç olduğunda uçuş ortasında sürekli dürtme ve rotayı düzeltme becerimizi kaybettik. Bazen ajan tamamen hedefi ıskalayan bir şey üretti. Bu yararlıydı — bu başarısızlıklar sistemdeki boşlukları ortaya çıkardı ve onu daha sağlam hale getirmemize yardımcı oldu.
Sonucu elle yamamak yerine, ajanların bir dahaki sefere başarılı olabilmesi için güvenlik tedbirleri ve beceriler ekledik. Zamanla bu, harness'imize uçtan uca test çalıştırma, uygulamayı Chrome DevTools üzerinden kullanma ve QA smoke testlerini yönetme gibi yeni yetenekler eklememize yol açtı. Belgelerimizi önemli ölçüde iyileştirdik ve iyinin neye benzediğini netleştirdik.
Her görev Symphony tarzı çalışmaya uymaz. Bazı problemler hâlâ mühendislerin doğrudan etkileşimli Codex oturumlarıyla çalışmasını gerektirir; özellikle belirsiz problemler ya da güçlü muhakeme ve uzmanlık gerektiren işler. Pratikte bunlar, mühendislerimizin zaman harcaması için genellikle en ilginç ve en keyifli görevlerdir.
Fark şu ki Symphony, rutin uygulama işlerinin büyük kısmını üstlenebilir. Bu da mühendislerin sürekli daha küçük görevler arasında bağlam değiştirmek yerine aynı anda tek bir zor probleme odaklanmasına olanak tanır.
Ayrıca ajanları bir durum makinesindeki katı düğümler gibi ele almanın iyi işlemediğini de öğrendik. Modeller daha akıllı hale geliyor ve onları sığdırmaya çalıştığımız kutudan daha büyük problemleri çözebiliyor. Örneğin, ilk sürümlerde tüm GitHub entegrasyonları dış harness'in parçasıydı — örneğin erken sürümler Codex'in yalnızca kod değişiklikleri yapmasını bekliyor, sürecin geri kalanını (değişiklikleri gönderme, testleri çalıştırma) kod içinde belirliyordu. Ajan tabanlı çalışmanın ilk sürümlerinde Codex'ten yalnızca görevi uygulamasını istiyorduk. Bu yaklaşım fazla sınırlayıcı çıktı. Codex, birden fazla PR oluşturmanın yanı sıra inceleme geri bildirimini okuyup buna göre düzeltme yapma konusunda da gayet yetenekli. Bu yüzden ona araçlar(gh CLI, CI günlüklerini okuma becerileri vb.) verdik ve artık Codex'ten eski PR'leri kapatmak ya da tamamlanan işe karşı terk edilen işle ilgili raporlar çekmek gibi daha fazlasını isteyebiliyoruz. Bu tür görevler, ilk özellik uygulama kutusunun çok dışındaydı.
Bu nedenle sonunda ajanlara katı geçişler yerine hedefler vermeye yöneldik; tıpkı iyi bir yöneticinin ekibindeki doğrudan bağlı çalışanına bir hedef vermesi gibi. Modellerin gücü akıl yürütme yeteneklerinden gelir; bu yüzden onlara araçları ve bağlamı verin ve işlerini yapmalarına izin verin.
Symphony'yi geliştirmek için Symphony'yi kullanmak
Symphony deposunu açtığınızda ilk fark edeceğiniz şey, Symphony'nin teknik olarak yalnızca bir SPEC.md dosyası (problemin ve amaçlanan çözümün bir tanımı) olduğudur. Karmaşık bir denetim sistemi kurmak yerine, problemi ve amaçlanan çözümleri tanımladık; ajanlara üst düzey yönlendirme verdik.
Referans uygulama Elixir ile yazıldı; çünkü kod fiilen ücretsiz hâle geldiğinde, sonunda dilleri güçlü yanlarına göre seçebilirsiniz; örneğin Elixir'in eşzamanlılık yetenekleri gibi. Ancak temel fikir basit bir Markdown belgesinde ifade edilebilir. Favori kodlama ajanınızı spec'e yönlendirip kendi sürümünü uygulamasını teşvik ediyoruz.
Symphony'nin ilk sürümü, tmux içinde çalışan, Linear'ı yoklayan ve yeni görevler için alt ajanlar başlatan bir Codex oturumundan ibaretti. İşe yarıyordu, ama özellikle güvenilir değildi. İkinci sürüm, ajanlar düşünülerek oluşturulmuş ana proje depomuzun içinde yer alıyordu. Bu depoda ajanlara yüksek kaliteli iş yapmaları için gereken beceri ve bağlamı vermek üzere ajan harness'ini zaten kurmuştuk; Symphony de bunu basitçe bir araya getiriyor.
Temel işlevsellik ortaya çıktıktan sonra, Symphony'yi geliştirmek için Symphony'yi kullandık.
Sistemin görevleri yönettiğini ve proof-of-work videosunu eklediğini kurum içinde demoda gösterdiğimizde, tepki son derece olumluydu: Symphony proje kanalımız büyüdü ve organizasyon genelindeki ekipler onu doğal biçimde kullanmaya başladı. OpenAI'da dışarıya açılmadan önce kurum içinde ürün-pazar uyumu yakalamak bir ön koşuldur. OpenAI'da gördüğümüz kullanıma dayanarak, Symphony'yi şirket sınırlarının ötesinde de paylaşmamız gerektiği netleşti.
Bunun üzerine aklımızdaki fikri, bağımsız bir SPEC.md dosyasına çıkardık ve Codex'ten bunu uygulamasını istedik. Referans uygulama için, eşzamanlı süreçleri orkestre etmek ve denetlemek adına mükemmel primitive'lere sahip, nispeten niş bir dil olan Elixir'i seçtik. Codex, Elixir uygulamasını tek seferde oluşturdu, biz de oradan sonra hem spec hem uygulama üzerinde iterasyon yapmayı sürdürdük. Spec'i iyileştirmek için Codex'ten bunu birkaç başka dilde (TypeScript, Go, Rust, Java, Python daha uygulamasını istedik ve belirsizlikleri belirlemek ve sistemi sadeleştirmek için sonuçları kullandık. Her dilde başarılı oldu.
Codex'i geliştirme sürecinde, belirli depolara veya Linear MCP'ye bağımlılık gibi pek çok tesadüfi karmaşıklığı kaldırdık. Symphony artık kurum içi depolarımıza veya iş akışlarımıza bağlı değil. Temel yaklaşım basitleşti:
Her açık görev için, kendi çalışma alanında çalışan bir ajanın olmasını garanti edin.
Etkin işe yardımcı olmanın yanı sıra, geliştirme iş akışı artık ajanların bildiği ve takip ettiği bir şey. Geliştirme iş akışı (bir issue üzerinde çalışmak, bir depoyu checkout etmek, PM bunun üzerinde çalışıldığını bilsin diye durumu progress'e almak, PR'yi eklemek, Review durumuna taşımak, videolar eklemek vb.) artık basit bir WORKFLOW.md dosyasında yer alıyor. Bunların hepsi insanların izlediği bir süreçti, ama hiçbir zaman belgelenmemişti. Bu örtük adımlar kümesine güvenmek yerine artık onu belgeliyoruz ve Symphony, ajanların buna uymasını sağlıyor. Bu da bizimle birlikte çalışan ajanlar kurmamıza olanak tanıyor. Ajanların tamamlanmış işe öz değerlendirme de eklemesini istersek, bunu WORKFLOW.md'ye ekleriz ve Symphony, ajanları bu adıma yönlendirir.
Ayrıca, Codex'i app server modunda(yeni bir pencerede açılır), yani Codex için yerleşik arayüzsüz modda kullanma fırsatımız da oldu. Bu mod, bir ileti dizisini başlatmak veya dönüşlere tepki vermek gibi işler için Codex'i çalıştırmamıza ve iyi belgelenmiş bir JSON-RPC API üzerinden onunla programatik olarak konuşmamıza olanak sağladı. Bu, Codex ile CLI veya canlı tmux oturumları üzerinden etkileşime girmeye çalışmaktan çok daha kullanışlı ve ölçeklenebilir bir yol.
Codex App Server, kullanım senaryomuza kusursuz uydu: Codex'in sağladığı harness'ten yararlanırken içine bağlanabileceğimiz ayarlar ve kancalara da sahibiz. Örneğin, Linear erişim token'ını alt ajanlara açığa çıkarmamak için, MCP'ye güvenmeden veya erişim token'ını container'lara göstermeden, Linear'a karşı rastgele istekler yürüten ham linear_graphql işlevini açığa çıkarmak üzere dynamic tool calls(yeni bir pencerede açılır) kullanıyoruz.
Sırada ne var
Symphony kasıtlı olarak minimal bir orkestrasyon katmanıdır. Bunu, Linear gibi farklı iş akışı araçlarıyla eşleştirildiğinde Codex App Server'ın gücünü göstermek için açık kaynak yapıyoruz. Bu nedenle Symphony'yi bağımsız bir ürün olarak sürdürmeyi planlamıyoruz. Onu bir referans uygulama olarak düşünün. Pek çok geliştiricinin depolarını iskeletlemek için kodlama ajanlarını harness engineering yazısına yönlendirmesine benzer şekilde, sizin de favori kodlama ajanınızı kendi ortamlarınıza göre uyarlanmış sürümlerinizi oluşturması için Symphony spec'ine(yeni bir pencerede açılır) ve deposuna(yeni bir pencerede açılır) yönlendirmenizi umuyoruz.
Güç, Codex'ten ve onun app server'ından geliyor. Symphony, iş yönetimi sorununu çözmek için halihazırda kullandığımız iki şeyi, Codex ile Linear'ı, birbirine bağlamanın bir yoluydu. Kodlama ajanları akıl yürütme ve talimatları takip etme konusunda daha iyi hale geldikçe, diğer şirketlerde de darboğazın kod yazmaktan çok ajan tabanlı işi yönetmeye kayacağını düşünüyoruz. Heyecan verici kısım şu ki, bu kodlama ajan sistemiyle deneme yapmanın eşiği artık şaşırtıcı derecede düşük. Codex ile bir şeyler inşa etmeye başlayabilirsiniz.
Topluluktan öne çıkanlar
Yayımlanmasından sonraki haftalarda mühendislik topluluğunun Symphony'yi kullanıyor olmasını görmek bizi heyecanlandırıyor; 23 Nisan itibarıyla GitHub'da 15 binin üzerinde yıldız(yeni bir pencerede açılır) topladı.