Ali Gündoğdu

engineering

Dayanıklı Sistemler Çağında Ajan: Hasar Nerede Durur?

3 Kasım 2026 · 7 dk okuma

Dayanıklı Sistemler Çağında Ajan: Hasar Nerede Durur?

Dayanıklı Sistemler Çağında Ajan: Hasar Nerede Durur?

Ajan Sisteme Yeni Bir İstemci Olarak Girer

Anthropic, 19 Aralık 2024’te yayımladığı Building effective agents yazısında bir çizgi çekti. İş akışlarında model ve araçlar önceden yazılmış kod yollarıyla yönlendirilir. Ajanlarda model kendi sürecini ve araç kullanımını kendisi yönetir.

Bu çizginin mimari karşılığı şu: ajan, servislerin içinde çalışan bizim kodumuz sayılamaz. Sınırdan giren bir istemcidir ve kararını kendisi verir. Servisler arası güvende karşı taraf deterministiktir, aynı girdiye aynı tepkiyi verir, hata yaptığında da çoğunlukla aynı şekilde yapar. Ajan aynı görevi iki kez aldığında iki farklı yol seçebilir ve seçtiği yol her seferinde makul görünür. Bu yüzden onu kullanıcı girdisi gibi ele almak gerekir: yetkisi sınırda sorgulanır, ürettiği her çağrı “bu isteği kim, neye dayanarak yapıyor” sorusundan geçer. “Bizim kodumuz, güvenebiliriz” varsayımı burada çöker.

Klasik dayanıklılık sorusu servisin düşmesi üzerine kuruludur. Ödeme servisi yanıt vermezse ne olur? Michael Nygard’ın Release It! kitabı (ilk baskı 2007, ikinci baskı 2018) timeout, circuit breaker ve bulkhead kalıplarını bu soruya cevap olarak anlatır. Servis düştüğünde alarm çalar, grafik kırmızıya döner.

Ajanla birlikte ikinci bir soru çıkar: yanlış ama makul görünen bir eylem yapılırsa ne olur?

Bir düşünce deneyi kuralım, yaşanmış bir olay değil. Bir ajana “müşterinin mükerrer faturasını düzelt” görevi verilmiş. Ajan iki faturayı inceliyor, tutarların aynı olduğunu görüyor ve birini iptal ediyor. Çağrı geçerli, yetki yeterli, servis sağlıklı, yanıt 200. İptal edilen fatura başka bir siparişe aitti ve tutarların aynı olması tesadüftü. Servis düşmedi, timeout tetiklenmedi, alarm çalmadı. Sistem tam kapasiteyle çalışırken yanlış iş yaptı.

Bu örnek dayanıklılığın tanımını genişletir. “Sistem ayakta mı” sorusuna “ayakta olan sistem doğru işi mi yapıyor” sorusu eklenir. Düşme tek bir kapıdan girerdi. Yanlış ama makul eylem, ajanın erişebildiği her kapıdan girebilir. Sonraki bölümler yetkinin nasıl daraltılacağını, hasarın nerede durdurulacağını ve yanlışlığı yakalayacak yeni frenleri ele alıyor.

Yetki Göreve Daraltılır, Kontrol Akışı İskelette Kalır

OWASP’ın büyük dil modeli uygulamaları için yayımladığı 2025 listesinde LLM06 numarasıyla Excessive Agency başlığı yer alıyor. Konusu, ajana gereğinden fazla işlev, izin ve özerklik verilmesi. Ajanı kullanıcının oturumuyla çalıştırmak bu hatanın en kolay yolu, çünkü token zaten elde ve entegrasyon bir günde biter.

Bedeli hesaplamak için kullanıcının yetkisine bakmak yeterli. Bir destek çalışanı müşteri kayıtlarını okuyabilir, iade başlatabilir ve hesap notunu silebilir. Ajan bu çalışanın token’ıyla çalışırsa hepsini taşır, oysa elindeki iş “bu talebin durumunu özetle” olabilir. Ajan bir yanlış anlamayla ya da metne gömülmüş bir talimatla yanlış araca uzandığında sınırı çizen tek şey kullanıcının rolü olur. O rolü ise kimse ajan düşünülerek tasarlamamıştır.

Çözüm yetkiyi görevde başlatıp görevde bitirmek. Ajan çalışmaya başlarken tek bir iş için, tek bir kayıt kümesi üzerinde, kısa ömürlü bir kimlik alır. Özet çıkaran görev okuma yetkisiyle gelir ve yazma aracı ona hiç gösterilmez. Kimliğin ömrünü yarım saatle sınırlarsan sızan token yarım saat sonra işe yaramaz. Araç listesini kısaltmak da yetki kısıtının parçasıdır, çünkü ajan listede olmayan aracı çağıramaz.

Kontrol akışında aynı mantık işler. Başta andığım ayrıma göre iş akışında adımların sırasını sen yazarsın, ajanda sırayı model her turda yeniden kurar. Ödeme ile stok düşümü gibi adımların sırası, yeniden denemesi ve telafisi belli olur. Bunları saga ya da iş akışı motoru gibi deterministik bir iskelete bağlarsan hata anında hangi adımda olduğunu, neyin geri alınacağını ve neyin tekrarlanabileceğini bilirsin. Saga fikri 1987’de Hector Garcia-Molina ve Kenneth Salem’in aynı adlı makalesine dayanır ve uzun süren işlemleri geri alınabilir adımlara bölmek için yazılmıştı. Modelin kendi planına bırakılan akışta bu bilgiyi ancak izleri okuyarak geri kurarsın.

Ajan bu iskeletin içinde belirli noktalarda çalışır. Bunlar girdisi yapısız, doğru cevabı kurala dökülemeyen yerlerdir: gelen talebi hangi kategoriye atayacağı ya da üç aday kayıttan hangisinin eşleştiği. Ajan her karar noktasında dar bir çıktı döndürür. İskelet bu çıktıyı doğrular, izin verilen değerlerden biri değilse reddeder ve sonraki adımı kendisi seçer. Ajanın “iadeyi başlat” demesi ile sistemin iadeyi başlatması arasında bu doğrulama durur.

Kendi sistemlerinde şu soruyu sorabilirsin: bu akışta hangi adımın sırası modele bırakılmış ve o adım neden kod olmasın?

Hasar Alanı Yazma Türüne Göre Basamaklanır

Yetki göreve daraltılsa bile görevin içinde yazma varsa hasar mümkündür. Ajanın zarar verebileceği alanı yazma yetkisinin türüne göre dört basamakta ölçebilirsin.

Birinci basamak salt okunur. Ajan sorgular, okur, özetler. Yanlış yaparsa yanlış cevap üretir ve bedelini o cevaba güvenen kişi öder. İkinci basamak onaylı yazma: ajan değişikliği taslak olarak hazırlar, bir insan ya da kural motoru onaylayınca uygulanır. Üçüncü basamak geri alınabilir yazma. Kayıt silinmez, durumu değişir, eski değer saklanır ve işlemi tersine çeviren bir yol vardır. Dördüncü basamak geri alınamaz yazma, örneğin gönderilmiş bir e-posta ya da çekilmiş bir ödeme. Burada ajana tek başına yetki verilmez. En azından tutar ve adım sınırı konur, çoğu zaman onay şarttır. Basamak yükseldikçe onay maliyeti de artar ve bu bilinçli bir tercihtir: insan zamanı en pahalı olduğu yere harcanır.

Üçüncü ve dördüncü basamakta idempotency zorunlu hale gelir. Ajan zaman aşımına uğrayan çağrıyı yeniden dener, model aynı planı iki kez üretip aynı iade isteğini iki kez gönderebilir. Çağrıyı alan servis bunu ayırt edemez. Çözüm eski bir dağıtık sistem dersi: her eylem, ajanın değil sistemin ürettiği bir idempotency anahtarı taşır ve alıcı aynı anahtarı ikinci kez görünce ilk sonucu döndürür. Anahtarı görev kimliğinden ve adım numarasından türetirsen yeniden deneme aynı anahtarı üretir.

Eski veri ayrı bir risk. Ajanın okuduğu görünüm bayatsa, doğru çalışan ajan yanlış karar verir. Sipariş iptal edilmiş ama okuma kopyası henüz güncellenmemişse ajan müşteriye kargo bilgisi verir ya da ikinci bir iade başlatır. CDC ile veritabanı değişiklik günlüğünü akıtmak ajanın görünümünü kaynağa bağlar. Ajan kararına en son işlediği olayın sürümünü ekler, yazarken de servis bu sürümün hala güncel olup olmadığını kontrol eder. Outbox yazma tarafını korur: iş kaydı ile “bu olay yayınlanacak” kaydı aynı transaction’da düşer, böylece ajanın tetiklediği değişiklik ya hem veritabanında hem akışta vardır ya da hiçbirinde. Debezium bu akışı okumanın bilinen yollarından biri.

Servis sınırları hasarı bu basamakların dışında da daraltır. Ajanın yazma yetkisi tek bir servisin API’siyle sınırlıysa o servisin kendi kuralları son savunma hattı olur. Sipariş servisi negatif tutarlı iadeyi reddediyorsa ajan da bunu gönderemez. Sınırı bulanık servislerde ajan, kimsenin tasarlamadığı bir yoldan birden fazla tabloya yazabilir. Release It! kitabındaki bulkhead kalıbı, yani arızayı bir bölmeye hapsetmek, ajan için de geçerli.

Elindeki her ajan aracını bu dört basamaktan birine yaz. Hangisine yazamıyorsan o aracın yetkisini kapat.

Sessiz Yanlışlık ve Döngü Maliyeti Yeni Fren İster

Yetkiyi daraltmak ve hasarı basamaklamak ajanın ne yapabileceğini sınırlar, ama yaptığı şeyin yanlış olduğunu fark etmeyi sağlamaz. Bunun için eldeki frenlere bakmak gerekir.

Circuit breaker, bir bağımlılık hata vermeye başladığında çağrıyı keser. Timeout, cevap gelmeyen çağrıyı sonsuza kadar bekletmez. İkisi de Release It! kalıplarıdır ve aynı varsayımla çalışır: bozulan şey kendini hata olarak gösterir. Ajan bu varsayımı bozuyor.

Yanlış ama makul görünen sonuç HTTP 200 ile döner. Ajan müşteriye yanlış iade tutarını yazar, bir kaydı mükerrer sanıp siler, eksik bir özeti tam diye sonraki adıma geçirir. Hiçbir eşik aşılmadığı için devre açılmaz, alarm çalmaz. Her adım bir öncekinin çıktısını girdi olarak aldığından küçük bir sapma birkaç adım sonra büyür ve kaynağını bulmak zorlaşır.

Maliyet başka bir yoldan patlar. Ajan başarısız olan bir aracı farklı argümanlarla yeniden denemeye karar verirse her deneme başarılı bir çağrıdır. Timeout’a takılmaz, hata sayacı artmaz. Fatura her turda token ve araç çağrısı olarak birikir. Klasik frenler süreye ve hata oranına bakar, döngüye giren ajan ikisine de uymaz.

Bu yüzden iki yeni sınır gerekir. Biri bir görev için atılabilecek en fazla adım sayısı, öbürü o görev için harcanabilecek en fazla tutar. Sınır aşıldığında ajan devam etmez, görevi durdurur ve bulunduğu durumu bırakır. Sayıları kendi iş yükünün ölçümünden almak gerekir. Kaynağını gösteremeyeceğim bir rakam yazmıyorum.

Sessiz yanlışlığı yakalamak için sonradan okunabilir bir iz gerekir. ADR bir mimari kararı, neden öyle verildiğiyle birlikte yazıya döker. Çalışma zamanındaki karşılığı karar kaydı ve trace’tir: ajan her adımda hangi girdiyi gördü, hangi aracı hangi argümanla çağırdı, hangi seçeneği neden seçti. Kayıt yoksa yanlış sonuç bulunduğunda “ajan bunu neden yaptı” sorusunu tahminle cevaplarsın.

İnsan onayını da aynı çerçevede tasarlamak gerekir. Her adıma onay koyarsan ajanın hızından geriye bir şey kalmaz. Hiç koymazsan hasar denetimsiz akar. Onayı iki noktaya bağlamak daha sağlam çalışır: bütçenin belli bir oranı harcandığında ve geri alınamaz bir yazma sırası geldiğinde. İlki maliyeti, ikincisi hasarı sınırlar. Onaylayan kişi karar anında ajanın izini görebiliyorsa onay gerçek bir karara dönüşür. Göremiyorsa kişi formdaki kutucuğu işaretler ve geçer.

Kendi sisteminde başlamak için bir ajan görevi seç, adım ve harcama tavanını yaz, aşıldığında ne olacağını tek cümleyle belirle.