Kalite, Test ve Operasyon
Karanlık Kodu Çalıştırın: Agent'ınızın Error Handling'i Neden Hiç Çalışmadı ve Onu Bilerek Nasıl Çalıştırırsınız?
Run the Code in the Dark: Why Your Agent's Error Handling Never Worked
Agent'ın retry, fallback ve cleanup kodu hiç tetiklenmediği için test edilmemiş koddur; gerçek hatayı SDK/API sınırında bilerek enjekte etmeden ona güvenemezsiniz.
Agent'ın hata yönetimi kodu hiç tetiklenmediği için test edilmemiş koddur; gerçek hatayı SDK/API sınırında bilerek enjekte etmeden ona güvenemezsin.
Hata yönetiminin felaketlerin ana kaynağı olduğu 2014'ten beri kabul görüyor; Agent'lara özgü fault injection araç ve araştırmaları ise 2026'da çıkmaya başladı.
Zihinsel model
Yangın tatbikatı gibi: alarmın çaldığını görmeden yangın merdiveninin açıldığına güvenmezsin, tatbikatı da alarm gerçekten çaldıysa sayarsın.
Neden
- Geliştirme ortamında kota dolmaz, akış kesilmez, tool ölmez; bu yüzden retry ve fallback kodu üretime kadar hiç koşmaz.
- Mock yalnızca mock'un fırlattığı exception'ı test eder; gerçek SDK'nın retry, timeout ve streaming davranışını hiç görmez.
- Agent hataları HTTP, stdio ve syscall katmanlarında oluşur; pod seviyesindeki kaos bu hataları doğru biçimde üretmez.
Kanıt
Dağıtık veri sistemlerinde felaket boyutundaki hataların yüzde 92'si ölümcül olmayan bir hatanın yanlış ele alınmasından çıktı.
Yuan vd., OSDI 2014LLM API yanıtına enjekte edilen hatalarla en sağlam çok-Agent'lı sistem bile HumanEval'de yaklaşık 19 puan kaybetti.
AgentChaos, arXiv 2026Production benzeri stres altında Agent başarısını en çok rate limiting hataları düşürdü.
ReliabilityBench, arXiv 2026Karşı görüş
Gerçek sağlayıcıya giden fault testleri pahalı ve yavaştır; araçlar Ekim 2026'da erken aşamada. Ayrıca fault injection yalnızca altyapı hatasını ölçer, makul görünen ama yanlış çıktı için ayrıca eval gerekir.
Kavramlar
Pratikte
- Hatayı mock yerine gerçek SDK'nın göreceği biçimde HTTP proxy ya da syscall seviyesinde üret.
- Her fault senaryosunda enjeksiyon sayısını say; sıfırsa testi başarısız say.
- Geçmiş incident'ları fault kataloğuna çevir ve gece CI işinde düzenli koştur.
Bir Agent tek bir isteği yerine getirirken LLM çağrısı, tool subprocess'i, RAG araması ve HTTP isteğinden oluşan bir zincir kurar. Geliştirici her halka için hata kodu yazar: 429 gelince bekle, tool öldürülünce temizle, vektör veritabanı saçma dönerse fallback'e geç. Bu kodun büyük kısmı normal çalışmada hiç koşmaz; unit test yalnızca mock'u, Kubernetes seviyesindeki kaos araçları da yanlış katmanı test eder. Sorun yeni değil: dağıtık sistemlerde felaket boyutundaki hataların yüzde 92'sinin ölümcül olmayan hataların yanlış ele alınmasından çıktığı 2014'te ölçüldü. Ekim 2026 itibarıyla Agent'lar için fault injection kendi araç ve araştırma alanına dönüştü: Ağustos 2026'daki AgentChaos çalışması, LLM API yanıtına enjekte edilen hatalarla çok-Agent'lı sistemlerde pass@1'in 50 puana yakın düşebildiğini gösterdi; HTTP proxy ve eBPF tabanlı açık kaynak araçlar da hata yolunu CI'da bilerek çalıştırmayı mümkün kılıyor.
Çıkarımlar
- Hiç çalışmamış catch bloğu test edilmiş kod değildir; Agent'taki retry, fallback ve cleanup kodu için bu varsayılan durumdur.
- Mock yalnızca mock'u test eder, pod öldürmek de yanlış katmanı; hatayı gerçek SDK'nın göreceği biçimde HTTP, stdio ya da syscall sınırında üretin.
- Kesilmiş streaming yanıt geçerli metin gibi görünür; her çağrıda stop_reason ve yanıt uzunluğunu kontrol edin.
- Fault'un ateşlendiğini ayrı bir koşul olarak doğrulayın; ateşlenmeyen fault ile yeşil yanan test, kırmızı testten daha tehlikelidir.
- İç içe retry katmanlarını sayın: SDK, uygulama ve orchestration retry'ları tek bir 429'u retry fırtınasına çevirebilir.
- Geçmiş incident'ları fault kataloğuna çevirin; her senaryo önce kırmızı yanmalı, guard aynı Pull Request'te gelmeli.
Alt başlıklar
Karanlık kod: hiç çalışmamış hata yolu
Bir Agent kod tabanında `except RateLimitError`, `finally: cleanup()` ya da 'RAG boş dönerse genel cevaba geç' gibi bloklar bolca bulunur. Bunların ortak özelliği, geliştirme sırasında neredeyse hiç çalışmamalarıdır. Laptop'ta API kotası dolmaz, tool subprocess'i OOM ile öldürülmez, disk dolmaz. Kod review'dan geçer, coverage raporunda kırmızı satır olarak kalır ve ilk kez üretimde, en kötü anda koşar.
Bu durumun bedeli ölçülmüş bir şey. Toronto Üniversitesi'nin OSDI 2014'te yayımlanan çalışması Cassandra, HBase, HDFS, MapReduce ve Redis'teki 198 kullanıcı raporlu hatayı inceledi ve felaket boyutundaki hataların yüzde 92'sinin ölümcül olmayan bir hatanın yanlış ele alınmasından doğduğunu buldu. Bunların yaklaşık üçte biri basit kalıplardı: hatayı yalnızca loglayan handler, içinde TODO kalmış catch bloğu, çok geniş bir exception yakalayıp sert bir aksiyon alan kod. Agent'lar bu tabloyu büyütür, çünkü bir istekte onlarca dış çağrı ve dolayısıyla onlarca hata yolu vardır.
Ekim 2026 itibarıyla durum
Son on iki ayda Agent'lar için fault injection, genel kaos mühendisliğinin bir alt başlığı olmaktan çıkıp kendi araştırma ve araç alanına dönüştü. Ocak 2026'da yayımlanan ReliabilityBench, 1.280 epizotluk deneyde altyapı hataları arasında en büyük etkiyi rate limiting'in yaptığını raporladı. 7 Ağustos 2026'da arXiv'e konan ve ASE 2026'ya kabul edilen AgentChaos, LLM API yanıtındaki `content` ve `tool_calls` alanlarına altı tip hata enjekte etti; beş çok-Agent'lı sistemin hepsi bozuldu, pass@1 düşüşü 50 puana yaklaştı. En sağlam sistem olan AutoGen bile HumanEval'de yüzde 98,61'den 79,17'ye indi ve görev başına LLM çağrısı 1,72'den 7,3'e çıktı.
Araç tarafında küçük ve yeni açık kaynak projeler var: per-run CA ile HTTPS proxy ve eBPF kullanan faultkit Eylül 2026'daki v0.1.3 ile 14 senaryoya ulaştı; agentic-chaos çağrı noktasını saran bir Python kütüphanesi olarak tool ve handoff hataları ekledi. Klasik kaos tarafında Gremlin Ekim 2026'da deney üretimine AI eklediğini duyurdu. SDK'lar ise kendi katmanında hata yutmaya devam ediyor: Anthropic Python SDK'sı bağlantı hatası, 408, 409, 429 ve 5xx'i varsayılan olarak iki kez yeniden deniyor, varsayılan timeout 10 dakika.
Mock ve pod seviyesi kaos neden yetmiyor
Hata yolunu test etmenin en yaygın yolu mock'tur: `client.messages.create` yerine `RateLimitError` fırlatan bir sahte nesne koyarsınız, test geçer. Ama bu test yalnızca mock'un davranışını doğrular. Gerçek SDK'nın kendi retry döngüsünü, `retry-after` başlığını nasıl okuduğunu, streaming yanıt ortasında bağlantı koptuğunda hangi exception'ı fırlattığını hiç görmez. Mock'ta fırlattığınız exception tipi gerçekte hiç gelmeyebilir; handler'ınız yanlış tipi yakalıyor olabilir.
Kubernetes seviyesindeki kaos araçları ise ters yönden ıskalar. Pod öldürmek, ağ gecikmesi eklemek ya da node düşürmek altyapının dayanıklılığını ölçer, ama Agent'ın karşılaştığı tipik hata pod ölümü değildir. Agent'ın hatası sağlayıcının döndürdüğü 429, yarıda kesilen bir SSE akışı, şeması bozuk bir `tool_calls` JSON'u ya da MCP stdio sunucusunun sessizce ölmesidir. Bunlar uygulamanın HTTP, stdio ve syscall katmanlarında oluşur; pod ölümü bu hataların hiçbirini doğru biçimde üretmez. Doğru test, hatayı gerçek SDK'nın göreceği biçimde, gerçek bağlantı üzerinden üretmelidir.
Hata taksonomisi: crash, omission, value
Agent hatalarını düşünmek için dağıtık sistemlerin güvenilirlik teorisinden gelen basit bir sınıflandırma iş görüyor. Crash hataları sistemin açıkça hata verdiği durumlardır: HTTP 5xx, 429, timeout. Omission hataları yanıtın eksik gelmesidir: boş `content`, yarıda kesilmiş streaming yanıt. Value hataları ise en sinsi olanlardır: yanıt geliyor, biçimi geçerli JSON, ama alan adı yanlış ya da değer bozuk.
Bu sınıflar tespit zorluğu bakımından çok farklıdır. AgentChaos verisine dayanan bir derlemede kural tabanlı teşhis, boş yanıtı yaklaşık yüzde 97 oranında tanırken yarıda kesilmiş yanıtı yalnızca yüzde 4,3 oranında yakalayabildi; çünkü kesilmiş metin geçerli metin gibi görünür. Pratik sonuç: her LLM çağrısında `stop_reason` ve yanıt uzunluğunu loglayın, `max_tokens` ya da beklenmeyen bir durma nedeniyle biten yanıtı başarılı saymayın. Tool tarafında da aynı mantık geçerli: tool çıktısının şemasını doğrulamayan Agent, bozuk veriyi gerçek kabul edip bir sonraki adıma taşır ve hata zincirin üç adım ilerisinde, bambaşka bir yerde görünür.
Enjeksiyonu doğru sınırda yapmak: proxy, base URL, eBPF
Hatayı gerçek SDK'ya gerçek biçimde ulaştırmanın birkaç yolu var ve her birinin bedeli farklı. HTTPS proxy yaklaşımında test, her çalıştırma için geçici bir CA üretir, TLS'i sonlandırır ve sağlayıcının gerçek yanıtını yolda değiştirir: 429 sentezler, akışı belirli bir token sayısından sonra keser. SDK gerçek TLS bağlantısı üzerinden üretimdekiyle aynı byte'ları görür. Sınırları var: certificate pinning yapan istemciler yakalanmaz, HTTP/2 desteği araçtan araca değişir. `HTTPS_PROXY`'yi yok sayan istemciler için `OPENAI_BASE_URL` gibi base URL değişkenleriyle trafiği yönlendirmek ikinci bir yol.
Daha alt katmanda eBPF var. Kernel'deki kprobe'lara bağlanan bir program, `recvmsg` ya da `openat` gibi çağrıların dönüş değerini değiştirerek süreçe simüle değil gerçek bir `ECONNRESET` ya da `EACCES` verir. Bu yaklaşım Linux'a ve kernel'in error injection altyapısına (`CONFIG_BPF_KPROBE_OVERRIDE`) bağlıdır; Trail of Bits'in ebpfault aracı aynı fikrin genel amaçlı bir örneği. Üçüncü yol süreç içi sarmalamadır: AgentChaos `httpx.AsyncClient`'ı yamalar, agentic-chaos çağrı noktasını sarar. Kurulumu kolaydır ama SDK'nın altındaki taşıma katmanını atlar.
Ateşlenmeyen fault: yeşil testin en tehlikeli hali
Fault injection testlerinin kendine özgü bir tuzağı var: test geçer, ama enjekte edilecek hata hiç tetiklenmemiştir. Proxy'yi yok sayan bir istemci, değişen bir endpoint adı ya da yanlış eşleşen bir kural hatayı devre dışı bırakır; Agent normal yoldan çalışır, test yeşil yanar. Ekip hata yolunun doğrulandığını sanır. Bu, kırmızı yanan bir testten daha tehlikelidir, çünkü yanlış bir güven üretir ve kimse ona bir daha bakmaz.
Çözüm, fault'un ateşlendiğini ayrı bir koşul olarak doğrulamaktır. faultkit bunu çıkış koduna gömüyor: 0 'hata altında geçti', 1 'hata bir bug buldu', 3 ise 'fault hiç ateşlenmedi, test o yolu çalıştırmadı' anlamına geliyor. AgentChaos da analizlerinde hatanın gerçekten tetiklenmediği görevleri sonuçlardan çıkarıyor. Hangi aracı kullanırsanız kullanın kural aynı: her senaryo için kaç kez enjeksiyon yapıldığını sayın ve sıfırsa testi başarısız sayın. CI'da 'fault fired: 0' satırı, 'tests passed' satırından daha önemli bir sinyaldir.
Neye assert edilir: retry katmanları ve sessiz uydurma
Hata altında 'Agent çökmedi' demek yetmez; neyin doğru davranış olduğunu baştan yazmak gerekir. İlk kontrol retry katmanlarıdır. SDK zaten iki kez yeniden deniyorsa ve siz üstüne üç denemelik bir döngü, orchestration katmanı da kendi retry'ını ekliyorsa, tek bir 429 sağlayıcıya on sekiz isteğe dönüşebilir. Bu, rate limit'i büyüten bir retry fırtınasıdır. Testte istek sayısını sayıp bir üst sınıra assert etmek bunu yakalar.
İkinci kontrol uydurmadır. Tool hata döndürdüğünde Agent ya hatayı kullanıcıya söylemeli ya da alternatif bir yol denemeli; olmayan veriyle cevap üretmemeli. Yedi adımlık bir planın dördüncü adımında gelen 429, Agent'ın baştan başlayıp ilk üç adımın yan etkilerini tekrarlamasına yol açmamalı; bu yüzden tool çağrıları idempotent olmalı. Üçüncü kontrol telemetridir: timeout, rate limit ve bağlantı hatası aynı `outcome=error` etiketiyle loglanıyorsa üretimde hangisinin yaşandığını ayıramazsınız. Hata sınıfını ayrı bir alanda tutmak, Trace'te hatanın kökünü bulmayı mümkün kılar.
Pratik: incident'tan fault kataloğuna
Hata yolunu bilerek çalıştırmanın sürdürülebilir hali bir katalogdur. Başlangıç noktası geçmiş incident'lardır: sağlayıcının yoğunluk nedeniyle 529 döndürdüğü gün, MCP sunucusunun stdio'da takılı kaldığı deploy, vektör veritabanının boş sonuç döndüğü index yenilemesi. Her biri bir senaryoya dönüşür: hangi katmanda, hangi hata, planın hangi adımında, kaç kez.
Sıra şöyle işler: senaryoyu yazın, mevcut kodla testin kırmızı yandığını görün, en küçük guard'ı aynı Pull Request'te ekleyin, testin yeşile döndüğünü ve fault'un gerçekten ateşlendiğini doğrulayın. Bu senaryolar her PR'da değil, gece çalışan ayrı bir CI işinde koşabilir; çünkü gerçek sağlayıcıya giden testler hem maliyetli hem yavaştır. Kaos mühendisliğinin klasik ilkesi burada da geçerli: blast radius'u küçük tutun. Önce staging'de, tek bir senaryo ve tek bir sağlayıcıyla başlayın; üretim trafiğine enjeksiyon ancak geri alma mekanizması ve net bir durdurma eşiği olduğunda gündeme gelsin.
Son gelişmeler
Ekim 2026 itibarıyla
Önce kendi cevabını düşün, sonra aç.
SDK zaten retry yapıyor, ayrıca hata yolunu test etmeye neden gerek olsun?
SDK'nın retry'ı yalnızca geçici hataları ve yalnızca kendi katmanında ele alır; iki deneme sonrası pes ettiğinde exception sizin koda gelir ve asıl karar orada verilir. Ayrıca SDK'nın retry'ı ile sizin retry'ınız üst üste binerse istek sayısı katlanır. Bu iki davranışı da ancak gerçek SDK'ya gerçek hata vererek görebilirsiniz.
Üretimde kaos deneyi yapmadan bu iş olur mu?
Olur ve çoğu ekip için doğru başlangıç budur. Agent hatalarının büyük kısmı tek süreçte, tek bir dış çağrıyla tekrarlanabilir; 2014'teki dağıtık sistem çalışması bile üretim hatalarının yüzde 77'sinin bir unit test ile yeniden üretilebildiğini buldu. Staging'de ve CI'da başlayıp üretime ancak geri alma ve durdurma eşiği hazır olduğunda geçmek makul.
eBPF gerçekten gerekli mi, HTTP proxy yetmez mi?
LLM ve HTTP tool çağrılarının çoğu için proxy yeterlidir. eBPF, hatanın HTTP'nin altında oluştuğu durumlar için gerekir: bağlantı resetlenmesi, dosya izni hatası, disk dolması gibi syscall seviyesindeki hatalar. Linux ve kernel ayarı gerektirdiği için CI ortamınız destekliyorsa ikinci aşama olarak eklemek mantıklı.
Hata altında Agent'ın doğru davranıp davranmadığını nasıl ölçeriz?
Önceden yazılmış beklentilerle: istek sayısı belirli bir sınırı aşmamalı, Agent hatayı kullanıcıya açıkça söylemeli ya da alternatif yol denemeli, olmayan veriyle cevap üretmemeli, tekrarlanan tool çağrıları yan etkiyi çoğaltmamalı. Bunların bir kısmı kural tabanlı kontrolle, uydurma gibi anlamsal olanlar LLM-as-judge ya da ground truth karşılaştırmasıyla ölçülür.
Bu araçlar çok yeni ve küçük projeler; bunlara bağımlı olmak riskli değil mi?
Evet, Ekim 2026 itibarıyla alanın araçları erken aşamada ve az kullanıcılı. Ama asıl değer araçta değil yöntemde: hatayı doğru katmanda üretmek, ateşlendiğini doğrulamak ve davranışa assert etmek. Bu üç ilkeyi Toxiproxy, kendi yazdığınız bir HTTP wrapper ya da test backend'i ile de uygulayabilirsiniz.
Notun kaynakları
- Simple Testing Can Prevent Most Critical Failures (Yuan vd., OSDI 2014)
- AgentChaos: Chaos Engineering for Agent Systems via Programmatic Fault Injection (arXiv, Ağustos 2026)
- ReliabilityBench: Evaluating LLM Agent Reliability Under Production-Like Stress Conditions (arXiv, Ocak 2026)
- Anthropic Python SDK dokümantasyonu (retry ve timeout varsayılanları)
- LLM API Fault Injection at the HTTP Layer (AgentPatterns.ai, Ağustos 2026)
Sunum stili
12 slayt. Tıklarsan sunum o slayttan başlar.
Slayt notları
Retry, fallback, cleanup: hepsi yazılmış, hiçbiri koşmamış. Bu kodun ilk çalıştığı yer genelde üretim.
Geliştirme sırasında kota dolmaz, akış kesilmez, disk dolmaz. Bu satırlar ilk kez üretimde, en kötü anda çalışır.
Cassandra, HBase, HDFS, MapReduce ve Redis'te 198 hata incelendi. Agent'larda bir istekte onlarca dış çağrı, yani onlarca hata yolu var.
Pod öldürmek bu katmanların hiçbirini doğru biçimde üretmez. Doğru test, hatayı oluştuğu katmanda üretir.
Mock yalnızca mock'u test eder. Hatayı gerçek SDK'nın göreceği biçimde üretmek gerekiyor.
Dördüncü adım çoğu ekipte eksik. Fault ateşlenmeden geçen test hiçbir şey kanıtlamaz.
Agent'ın çökmemesi yetmez. Hata altında doğru davranışı önceden yazmak gerekiyor.
AgentChaos'un bulgusu: en zararlı hatalar aynı zamanda teşhisi en zor olanlar. Kesilmiş yanıtı kural tabanlı teşhis yalnızca yüzde 4,3 oranında yakaladı.
Proxy'yi yok sayan istemci, değişen endpoint, eşleşmeyen kural. Test geçer, hata yolu hâlâ karanlıkta.
AgentChaos, Ağustos 2026, HumanEval. Görev başına LLM çağrısı da 1,72'den 7,3'e çıktı. Diğer sistemlerde düşüş 50 puana yaklaştı.
Guard aynı Pull Request'te gelsin. Gerçek sağlayıcıya giden senaryolar pahalı ve yavaş, her PR'da değil gece işinde koşabilir.
Soru olarak bırak: Agent'ınızın retry kodu en son ne zaman gerçekten çalıştı?