Codex CLI(yeni bir pencerede açılır), makinenizde güvenli ve verimli bir şekilde çalışarak yüksek kaliteli ve güvenilir yazılım değişiklikleri üreten, platformlar arası otonom ajanımızdır. Dünya standartlarında bir otonom ajan nasıl inşa edilir konusunda, Nisan ayında CLI'yı ilk kez kullanıma sunduğumuzdan beri çok şey öğrendik. Bu analizleri daha derinlemesine ele almak için, Codex'in nasıl çalıştığının farklı yönlerini ve deneyimle kazanılmış önemli dersleri inceleyeceğimiz devam eden bir serinin ilk yazısıyla başlıyoruz. (Codex CLI'nın nasıl oluşturulduğuna dair daha ayrıntılı bilgi için https://github.com/openai/codex(yeni bir pencerede açılır) adresindeki açık kaynak depomuzu inceleyin. Tasarım kararlarımızın daha ince ayrıntılarının çoğu, daha fazla bilgi edinmek isterseniz GitHub işlem öğeleri ve pull request'lerinde kayıt altına alınmıştır.)
Başlangıç olarak, kullanıcı, model ve modelin çağırdığı araçlar arasındaki etkileşimi düzenlemekten sorumlu olan Codex CLI'daki temel mantık olan otonom ajan döngüsüne odaklanacağız. Bu yazının, bir LLM'den yararlanırken otonom ajanımızın (veya donanımın) oynadığı rolü size iyi bir şekilde gösterdiğini umuyoruz.
Başlamadan önce, terminoloji hakkında kısa bir not: OpenAI'da "Codex"; Codex CLI, Codex Cloud ve Codex VS Code uzantısı gibi otonom ajan çözümlerini kapsar. Bu yazı, Codex CLI aracılığıyla sunulan ve tüm Codex deneyimlerinin temelini oluşturan ana otonom ajan döngüsü ve yürütme mantığını sağlayan Codex donanımına odaklanmaktadır. Burada kolaylık sağlamak amacıyla "Codex" ve "Codex CLI" terimlerini birbirinin yerine kullanacağız.
Her yapay zeka otonom ajanının merkezinde "otonom ajan döngüsü" adı verilen bir yapı bulunur. Otonom ajan döngüsünün basitleştirilmiş bir gösterimi şu şekildedir:
Başlamak için otonom ajan, model için hazırladığı ve komut olarak bilinen metinsel talimatlar kümesine dahil etmek üzere kullanıcıdan girdi alır.
Bir sonraki adım, modele talimatlarımızı göndererek ve ondan bir yanıt üretmesini isteyerek modeli sorgulamaktır; bu süreç çıkarım olarak bilinir. Çıkarım sırasında, metin komutu önce bir dizi girdi token'ına(yeni bir pencerede açılır) (modelin kelime dağarcığını indeksleyen tamsayılar) çevrilir. Bu token'lar daha sonra modelden örnekleme yapmak için kullanılır ve yeni bir çıktı token dizisi oluşturur.
Çıktı token'ları tekrar metne çevrilir ve bu metin modelin yanıtı olur. Token'lar artımlı olarak üretildiğinden bu çeviri, model çalışırken gerçekleşebilir; bu nedenle birçok LLM tabanlı uygulama, akış halinde çıktı gösterir. Uygulamada, çıkarım genellikle metin üzerinde çalışan bir API'nin arkasında kapsüllenerek, tokenizasyon ayrıntılarını soyutlar.
Çıkarım adımının sonucunda, model ya (1) kullanıcının orijinal girdisine nihai bir yanıt üretir ya da (2) otonom ajanın gerçekleştirmesi beklenen bir araç çağrısı talep eder (örn. "ls komutunu çalıştır ve çıktıyı bildir"). (2) olması durumunda otonom ajan, araç çağrısını gerçekleştirir ve çıktısını orijinal komuta ekler. Bu çıktı, modeli yeniden sorgulamak için yeni bir girdi oluşturmak amacıyla kullanılır; otonom ajan bu yeni bilgiyi dikkate alarak tekrar deneyebilir.
Bu süreç, model araç çağrıları üretmeyi bırakıp bunun yerine kullanıcıya bir mesaj oluşturana kadar (OpenAI modellerinde asistan mesajı olarak adlandırılır) tekrarlanır. Çoğu durumda bu mesaj, kullanıcının ilk talebine doğrudan yanıt verir, ancak aynı zamanda bir takip sorusu da olabilir.
Otonom ajan, yerel ortamı değiştirebilen araç çağrılarını gerçekleştirebildiği için "çıktısı" sadece asistan mesajıyla sınırlı kalmaz. Çoğu durumda, bir yazılım otonom ajanının birincil çıktısı, makinenizde yazdığı veya düzenlediği koddur. Bununla birlikte, her tur, "İstediğiniz architecture.md dosyasını ekledim" gibi bir asistan mesajıyla sona erer ve bu, otonom ajan döngüsünde bir sonlandırma durumunu belirtir. Otonom ajanın bakış açısından, işi tamamlanmıştır ve kontrol kullanıcıya geri döner.
Diyagramda gösterilen kullanıcı girdisi ile otonom ajan yanıtı arasındaki yolculuk, bir konuşmanın bir turu (Codex'te bir mesaj dizisi ) olarak adlandırılır. Bu konuşma turu; model çıkarımı ve araç çağrıları arasında birçok yineleme içerebilir. Mevcut bir sohbete yeni bir mesaj gönderdiğinizde, sohbet geçmişi yeni tur için istemlerin bir parçası olarak dahil edilir. Bu istemler, önceki turlardan gelen mesajları ve araç çağrılarını içerir:
Bu, konuşma büyüdükçe modeli örneklemek için kullanılan komutun uzunluğunun da arttığı anlamına gelir. Bu uzunluk önemlidir çünkü her modelin bir bağlam penceresi vardır ve bu, tek bir çıkarım çağrısında kullanabileceği maksimum token sayısını belirler. Bu pencerenin hem girdi hem de çıktı token'larını içerdiğini unutmayın. Tahmin edebileceğiniz gibi, bir otonom ajan tek bir turda yüzlerce araç çağrısı yapmaya karar verebilir ve bu da bağlam penceresini potansiyel olarak tüketebilir. Bu nedenle bağlam penceresi yönetimi, otonom ajanın birçok sorumluluğundan biridir. Şimdi, Codex'in otonom ajan döngüsünü nasıl çalıştırdığını görmek için derinlemesine inceleyelim.
Codex CLI, model çıkarımı gerçekleştirmek için Responses API(yeni bir pencerede açılır)'ye HTTP istekleri gönderir. Bilginin Codex üzerinden nasıl aktığını inceleyeceğiz; Codex, otonom ajan döngüsünü çalıştırmak için Responses API'yi kullanır.
Codex CLI'nin kullandığı Responses API uç noktası yapılandırılabilir(yeni bir pencerede açılır), bu nedenle Responses API'yi uygulayan(yeni bir pencerede açılır) herhangi bir uç nokta ile kullanılabilir:
- Codex CLI ile ChatGPT oturumu açarken(yeni bir pencerede açılır), uç nokta olarak
https://chatgpt.com/backend-api/codex/responseskullanılır. - OpenAI tarafından barındırılan modellerle API anahtarı kimlik doğrulaması kullanırken uç nokta olarak (yeni bir pencerede açılır)
https://api.openai.com/v1/responseskullanılır. - Codex CLI'yı
--ossile çalıştırdığınızda, gpt-oss'u ollama 0.13.4+(yeni bir pencerede açılır) veya LM Studio 0.3.39+(yeni bir pencerede açılır) ile kullandığınızda, varsayılan olarak bilgisayarınızda yerel olarak çalışanhttp://localhost:11434/v1/responseskullanılır. - Codex CLI, Azure gibi bir bulut sağlayıcısının barındırdığı Responses API ile kullanılabilir
Bir konuşmada ilk çıkarım çağrısı için Codex'in komutunu nasıl oluşturduğunu inceleyelim.
Bir son kullanıcı olarak, Responses API'yi sorguladığınızda modeli örneklemek için kullanılan komutu tam olarak belirtmezsiniz. Bunun yerine, sorgunuzun bir parçası olarak çeşitli girdi türleri belirtirsiniz ve Responses API sunucusu, bu bilgileri modelin tüketmesi için tasarlanmış bir komuta nasıl yapılandıracağına karar verir. Komutu bir "öğe listesi" olarak düşünebilirsiniz; bu bölüm, komutunuzun bu listeye nasıl dönüştüğünü açıklayacaktır.
Başlangıç komutunda, listedeki her öğe bir rolle ilişkilendirilmiştir. role, ilişkili içeriğin ne kadar önemli olduğunu belirtir ve öncelik sırasına göre azalan şu değerlerden biridir: system, developer, user, assistant.
Responses API(yeni bir pencerede açılır), birçok parametre içeren bir JSON yükünü alır. Biz şu üçüne odaklanacağız:
instructions(yeni bir pencerede açılır): Modelin bağlamına eklenen sistem veya geliştirici mesajıtools(yeni bir pencerede açılır): Modelin yanıt oluştururken çağırabileceği araçlar listesiinput(yeni bir pencerede açılır): Modele metin, görsel veya dosya formatında girilen verilerin listesi
Codex'te instructions alanı, belirtilmişse ~/.codex/config.toml içindeki model_instructions_file(yeni bir pencerede açılır) dosyasından okunur; aksi takdirde, model ile ilişkili base_instructions kullanılır(yeni bir pencerede açılır). Modele özgü talimatlar Codex deposunda yer alır ve CLI'ya dahil edilir (örn. gpt-5.2-codex_prompt.md(yeni bir pencerede açılır)).
tools alanı, Responses API tarafından tanımlanan bir şemaya uygun araç tanımlarının listesidir. Codex için, Codex CLI tarafından sağlanan araçlar, Codex'e sunulması gereken Responses API araçları ve genellikle MCP sunucuları aracılığıyla kullanıcı tarafından sağlanan araçlar dahildir:
Son olarak, JSON yükünün input alanı, öğelerden oluşan bir listedir. Codex aşağıdaki öğeleri(yeni bir pencerede açılır) input içine ekler ve ardından kullanıcı mesajını ekler:
1. role=developer içeren ve yalnızca Codex tarafından sağlanan shell aracına uygulanan sandbox ortamını, araçlar bölümünde tanımlayan bir mesaj. Yani, MCP sunucularından sağlanan diğer araçlar Codex tarafından sandbox edilmez ve kendi koruma önlemlerini uygulamaktan sorumludur.
Mesaj, temel içerik parçalarının Codex CLI ile birlikte paketlenmiş Markdown parçacıklarından alındığı bir şablondan oluşturulur; örneğin, workspace_write.md(yeni bir pencerede açılır) ve on_request.md(yeni bir pencerede açılır):
2. (İsteğe bağlı) Kullanıcının config.toml dosyasından okunan developer_instructions değerini içeren role=developer rolüne sahip bir mesaj.
3. (İsteğe bağlı) İçeriği "kullanıcı talimatları" olan role=user içeren bir mesaj; bu talimatlar tek bir dosyadan alınmaz, birden çok kaynaktan bir araya getirilir(yeni bir pencerede açılır). Genel olarak, daha ayrıntılı talimatlar daha sonra görünür:
$CODEX_HOMEiçindekiAGENTS.override.mdveAGENTS.mddosyalarının içerikleri- Bir sınıra tabi olarak (varsayılan olarak 32 KiB),
cwd'nin Git/proje kökünden (varsa)cwd'ye kadar her klasörü inceleyin:AGENTS.override.md,AGENTS.mdveyaconfig.tomliçindeki project_doc_fallback_filenames tarafından belirtilen herhangi bir dosya adının içeriğini ekleyin. - Herhangi bir yetenek(yeni bir pencerede açılır) yapılandırıldıysa:
- beceriler hakkında kısa bir önsöz
- her bir beceri için beceri meta verisi(yeni bir pencerede açılır)
- becerilerin nasıl kullanılacağına(yeni bir pencerede açılır) dair bir bölüm
4. role=user içeren ve otonom ajanın şu anda çalıştığı yerel ortamı tanımlayan bir mesaj. Bu, geçerli çalışma dizinini ve kullanıcının kabuğunu belirtir(yeni bir pencerede açılır):
Codex, input'u başlatmak için yukarıdaki tüm hesaplamaları yaptıktan sonra kullanıcı mesajını ekler ve konuşmayı başlatır.
Önceki örnekler her bir mesajın içeriğine odaklanıyordu, ancak input içindeki her bir öğenin type, role(yeni bir pencerede açılır) ve content içeren bir JSON nesnesi olduğunu unutmayın:
Codex, Responses API'ye göndermek üzere tam JSON yükünü oluşturduktan sonra, ~/.codex/config.toml dosyasında Responses API uç noktasının nasıl yapılandırıldığına bağlı olarak bir Yetkilendirme başlığı ile HTTP POST isteği yapar (belirtilmişse ek HTTP başlıkları ve sorgu parametreleri eklenir).
OpenAI Responses API sunucusu isteği aldığında, JSON'ı kullanarak model için komutu aşağıdaki şekilde türetir (emin olmak gerekirse, Responses API'nin özel bir uygulaması farklı bir seçim yapabilir):
Gördüğünüz gibi, komuttaki ilk üç öğenin sırası istemci tarafından değil, sunucu tarafından belirlenir. Bununla birlikte, bu üç öğeden yalnızca system message içeriği sunucu tarafından kontrol edilir; çünkü tools ve instructions istemci tarafından belirlenir. Bunları, komutu tamamlamak için JSON yükünden gelen input takip eder.
Artık komutumuza sahip olduğumuza göre, modeli çalıştırmaya hazırız.
Responses API'ye yapılan bu HTTP isteği, Codex'te bir konuşmanın ilk "aşamasını" başlatır. Sunucu, Sunucu Tarafından Gönderilen Olaylar (SSE(yeni bir pencerede açılır)) akışı ile yanıt verir. Her etkinliğin veri alanı, "response" ile başlayan bir "type" içeren bir JSON yüküdür; bu, örneğin şöyle bir şey olabilir (etkinliklerin tam listesi API belgelerimizde(yeni bir pencerede açılır) bulunabilir):
Codex olay akışını işler(yeni bir pencerede açılır) ve bunları bir istemci tarafından kullanılabilecek dahili olay nesneleri olarak yeniden yayımlar. response.output_text.delta gibi olaylar, kullanıcı arayüzünde akışı desteklemek için kullanılırken, response.output_item.added gibi diğer olaylar, sonraki Responses API çağrıları için input'a eklenmek üzere nesnelere dönüştürülür.
Responses API'ye yapılan ilk isteğin iki response.output_item.done olayı içerdiğini varsayalım: biri type=reasoning ve diğeri type=function_call. Bu olaylar, araç çağrısına verilen yanıtla modeli yeniden sorguladığımızda JSON'ın input alanında yer almalıdır:
Sonraki sorgunun bir parçası olarak modeli örneklemek için kullanılan komut şu şekilde olurdu:
Özellikle, eski komutun yeni komutun tam bir ön eki olduğuna dikkat edin. Bu kasıtlıdır; çünkü bu, komut önbelleğe alma özelliğinden yararlanmamızı sağladığı için sonraki istekleri çok daha verimli hale getirir (bunu performansla ilgili bir sonraki bölümde ele alacağız).
Otonom ajanın döngüsünün ilk diyagramına dönüp baktığımızda, çıkarım ile araç çağırma arasında birçok yineleme olabileceğini görüyoruz. Komut, sonunda bir asistan mesajı alana kadar büyümeye devam edebilir; bu da turun sonunu belirtir:
Codex CLI'da, kullanıcıya yardımcı mesajını sunar ve kullanıcıya konuşmaya devam etme "sırasının" kendisinde olduğunu belirtmek için yazıcıya odaklanırız. Kullanıcı yanıt verirse, hem önceki turdaki asistan mesajı hem de kullanıcının yeni mesajı, yeni turu başlatmak için Responses API isteğindeki input alanına eklenmelidir:
Bir kez daha, bir konuşmayı sürdürdüğümüz için Responses API'ye gönderdiğimiz input uzunluğu artmaya devam ediyor:
Bu sürekli büyüyen komutun performans açısından ne anlama geldiğini inceleyelim.
Kendinize şu soruyu soruyor olabilirsiniz: "Bir dakika, ajan döngüsü, konuşma süresince Responses API'ye gönderilen JSON miktarı açısından ikinci dereceden değil mi?" Ve haklı olurdunuz. Responses API, bu sorunu hafifletmek için isteğe bağlı bir previous_response_id(yeni bir pencerede açılır) parametresini desteklese de Codex bunu bugün kullanmıyor; bunun başlıca nedeni, istekleri tamamen durumsuz tutmak ve Sıfır Veri Saklama (ZDR) yapılandırmalarını desteklemektir.
previous_response_id kullanmaktan kaçınmak, Responses API sağlayıcısı için işleri basitleştirir çünkü her isteğin durumsuz olmasını garanti eder. Bu durum, Sıfır Veri Saklama (ZDR)(yeni bir pencerede açılır) seçeneğini tercih eden müşterileri desteklemeyi kolaylaştırır; çünkü previous_response_id desteği için gereken verilerin saklanması ZDR ile çelişir. ZDR müşterilerinin, sunucuda çözülebilen ilgili encrypted_content sayesinde, önceki turlardan gelen tescilli akıl yürütme mesajlarından faydalanma yeteneklerinden vazgeçmediklerini unutmayın. (OpenAI, bir ZDR müşterisinin şifre çözme anahtarını saklar, ancak verilerini saklamaz.) ZDR'yi desteklemek için Codex'teki ilgili değişiklikleri görmek amacıyla #642(yeni bir pencerede açılır) ve #1641(yeni bir pencerede açılır) numaralı PR'lere (pull request'lere) bakın.
Genel olarak, modelin örnekleme maliyeti ağ trafiği maliyetine baskın gelir ve bu da örneklemeyi verimlilik çabalarımızın ana hedefi yapar. Bu nedenle komut önbelleğe alma çok önemlidir; çünkü önceki bir çıkarım çağrısından yapılan hesaplamayı yeniden kullanmamıza olanak tanır. Önbellek isabetleri aldığımızda, modeli örneklemek doğrusal olur, ikinci dereceden değil. Komut önbelleğe alma (yeni bir pencerede açılır)belgelerimizde bu daha ayrıntılı olarak açıklanmaktadır:
Önbellek isabetleri yalnızca bir komut içinde tam önek eşleşmeleriyle mümkündür. Önbelleğe alma avantajlarından yararlanmak için talimatlar ve örnekler gibi statik içeriği komutun başına yerleştirin ve kullanıcıya özgü bilgiler gibi değişken içeriği sona koyun. Bu durum, istekler arasında aynı olması gereken görseller ve araçlar için de geçerlidir.
Bunu akılda tutarak, Codex'te hangi tür işlemlerin bir "önbellek kaçırma"ya yol açabileceğini düşünelim:
- Konuşmanın ortasında modele sunulan
toolsseçeneklerini değiştirmek. - Responses API isteğinin hedefi olan
model'i değiştirmek (pratikte bu, orijinal komuttaki üçüncü öğeyi değiştirir; çünkü model'e özgü talimatlar içerir). - Sandbox yapılandırmasını, onay modunu veya geçerli çalışma dizinini değiştirmek.
Codex ekibi, komut önbelleğe almayı tehlikeye atabilecek yeni özellikleri Codex CLI'ye eklerken dikkatli olmalıdır. Örneğin, MCP araçlarına yönelik ilk desteğimiz, araçları tutarlı bir sırayla listeleyemediğimiz bir hataya(yeni bir pencerede açılır) yol açtı ve bu da önbellek kaçırmalarına neden oldu. MCP araçlarının özellikle zorlayıcı olabileceğini unutmayın; çünkü MCP sunucuları, notifications/tools/list_changed(yeni bir pencerede açılır) bildirimi aracılığıyla sağladıkları araçların listesini anında değiştirebilir. Uzun bir konuşmanın ortasında bu bildirimi dikkate almak, maliyetli bir önbellek hatasına yol açabilir.
Mümkün olduğunda, konuşma sırasında meydana gelen yapılandırma değişikliklerini, önceki bir mesajı değiştirmek yerine, değişikliği yansıtmak için input'a yeni bir mesaj ekleyerek ele alırız:
- Sandbox yapılandırması veya onay modu değişirse, orijinal
<permissions instructions>öğesiyle aynı formatta yeni birrole=developermesajı ekleriz(yeni bir pencerede açılır). - Mevcut çalışma dizini değişirse, orijinal
<environment_context>ile aynı biçimde yeni birrole=usermesajı ekleriz(yeni bir pencerede açılır).
Performansı artırmak için önbellek isabetlerini sağlamak adına büyük çaba gösteriyoruz. Yönetmemiz gereken başka bir önemli kaynak daha var: bağlam penceresi.
Bağlam penceresinin dolmasını önlemek için genel stratejimiz, token sayısı belirli bir eşiği aştığında konuşmayı daraltmaktır. Özellikle, girdi öğesini, konuşmayı temsil eden yeni ve daha küçük bir öğe listesiyle değiştiririz; bu, otonom ajanın şimdiye kadar olanları anlayarak devam etmesini sağlar. Sıkıştırmanın erken bir uygulaması(yeni bir pencerede açılır), kullanıcının /compact komutunu manuel olarak çalıştırmasını gerektiriyordu; bu komut, mevcut konuşmayı ve özetleme(yeni bir pencerede açılır) için özel talimatları kullanarak Responses API'sini sorgulardı. Codex, özet içeren ortaya çıkan asistan mesajını sonraki konuşma turları için yeni girdi(yeni bir pencerede açılır) olarak kullandı.
O zamandan beri Responses API, sıkıştırmayı daha verimli gerçekleştiren özel bir /responses/compact uç noktasını(yeni bir pencerede açılır) destekleyecek şekilde gelişti. Önceki girdi yerine kullanılabilecek öğelerin bir listesini(yeni bir pencerede açılır) döndürür ve bu sayede bağlam penceresinde yer açılırken konuşmanın devam etmesine olanak tanır. Bu liste, modelin orijinal konuşmayı örtük bir şekilde anlamasını koruyan opak bir encrypted_content öğesi içeren özel bir type=compaction öğesini içerir. Artık Codex, auto_compact_limit(yeni bir pencerede açılır) aşıldığında konuşmayı sıkıştırmak amacıyla bu uç noktayı otomatik olarak kullanır.
Codex otonom ajan döngüsünü tanıttık ve bir modeli sorgularken Codex'in bağlamını nasıl oluşturup yönettiğini adım adım açıkladık. Bu süreçte, Responses API'nin üzerine bir otonom ajan döngüsü kuran herkes için geçerli olan pratik hususları ve en iyi uygulamaları vurguladık.
Otonom ajan döngüsü Codex için bir temel sağlasa da, bu sadece bir başlangıçtır. Gelecek yazılarda CLI'nin mimarisini derinlemesine inceleyecek, araç kullanımının nasıl uygulandığını keşfedecek ve Codex'in sandboxing modeline daha yakından bakacağız.


