Eylem Değil Öneri: Otonom Altyapı Agent'larının Arkasındaki Kontrol Düzlemi
C.E.O. Bee Mühendislik11 dk okuma
Yıkıcı bir değişikliği halüsine eden bir LLM agent'ı bunu tam bir akıcılıkla ve hiç duraksamadan yapar; filo ölçeğinde bu bir anekdot olmaktan çıkıp hesaplanabilir bir orana dönüşür. Çok kiracılı bir agentic altyapı platformu için kurduğumuz kontrol düzlemini anlatıyoruz: deterministik politika kapıları, blast radius skorlaması, DAG kapsamlı kilitleme, karar provenance'ı ve just-in-time kimlik bilgileri.
Agentic bir altyapı platformunun hayatında, soyutlamanın sevimli olmaktan çıktığı çok belirli bir an vardır. Model bir plan döndürür. Plan iyi biçimlenmiştir, kendi içinde tutarlıdır, gerekçesini gayet düzgün anlatır ve on dört başka şeyin bağımlı olduğu stateful bir kaynağı siler. Aynı değişikliği öneren bir insan mühendis mutlaka bir yerden sinyal sızdırırdı: PR açıklamasındaki temkinli dil, "bunu hâlâ kullanan var mı" diye atılmış bir mesaj, kaynak adını yazmadan önceki yarım saniyelik duraksama. Agent'lar duraksamaz. Sonucun ağırlığına dair hiçbir propriyosepsiyonları yoktur ve yanılırken tam olarak haklıyken oldukları kadar akıcıdırlar. Otonom yazılıma production altyapısını işlettirmenin asıl mühendislik problemi bu asimetri; model kalitesiyle, prompt mühendisliğiyle ya da tool tasarımıyla sanıldığı kadar ilgisi yok.
Platform çok kiracılı bir agentic altyapı ürünü. Müşteri niyetini doğal dille tarif ediyor; uzmanlaşmış bir agent filosu (provisioning, maliyet optimizasyonu, güvenlik duruşu, incident response) ortaya çıkacak bulut varlığını planlıyor, kuruyor, deploy ediyor ve sonrasında sürekli işletiyor. Buna "tek seferlik üretici" demek işin zor kısmını atlamak olur: bu, süresiz ve gözetimsiz çalışan bir kontrol döngüsü. Yazının anlattığı noktada yaklaşık 3.400 eşzamanlı müşteri ortamı ve bir milyonun biraz üzerinde yönetilen kaynak var. Bu ölçekte "agent arada bir felaket bir şey yapıyor" cümlesi anekdot olmaktan çıkar, hesaplayabildiğiniz bir orana dönüşür. Oran haline geldiği andan itibaren de ya bütçesini ayırırsınız ya da tasarımla ortadan kaldırırsınız. Bizi ikincisi için çağırdılar.
Agent önerir. Kararı kontrol düzlemi verir.
İlk karar, geri kalan her şeyin üzerine asıldığı karar. Bir agent'ın cloud API'sine giden hiçbir ağ yolu yok. Rate limit'lenmiş biri değil, daraltılmış biri değil — hiçbiri. Bir agent'ın üretebileceği tek çıktı bir doküman.
O doküman bir plan IR'ı, yani niyetin sağlayıcıdan bağımsız ara temsili. Sağlayıcının plan çıktısını tipli bir mutasyon kümesine normalize ediyoruz: kanonik kaynak URN'i, operasyon (create / update / replace / destroy), alan yolu (field path) granülerliğinde before/after diff'i ve mutasyonun ima ettiği bağımlılık kenarları. Politika değerlendirme, risk skorlama, kilitleme, kimlik bilgisi üretimi, denetim; aşağıdaki her şey yalnızca IR'ı okuyor, başka hiçbir şeyi değil.
Bunun bedeli vardı ve baştan sorgulandı. İtiraz edenlere hak vermemek de zor: sağlayıcı zaten makine tarafından okunabilir bir plan üretiyorken ayrıca IR yazmak beyaz tahtada fazladan tören gibi görünüyor. Üç farklı bulutta aynı anlama gelen tek bir politika yazmanız gerektiği, onaylanan şeyin bit bit uygulanan şey olduğunu ispat etmek için planı hash'lemeniz gerektiği ya da bir öneriyi altı hafta önceki onay zarfıyla diff'lemeniz gerektiği ilk anda o görüntü dağılıyor. IR sonunda tüm sistemin taşıyıcı soyutlaması oldu; aşağıdaki mekanizmaların neredeyse hepsi onun üzerinde saf birer fonksiyon.
Akıl yürütmeyen kapı
Öneri ile uygulama arasında deterministik bir değerlendirici duruyor: Rego tarzı policy-as-code, organizasyon bazında derleniyor, zorlama (enforcement) yolunda hiçbir yerde model yok. Bu konuda dogmatiktik ve bugün de aynı yerde duruyorum. Bir model politikayı yazmaya yardım edebilir, bir politikayı açıklayabilir; ama politikanın geçip geçmediğine karar veren bileşen asla olamaz. Zorlama yoluna olasılıksal bir bileşen koyduğunuz anda elinizdeki şey sessizce çok pahalı bir tavsiyeye dönüşüyor.
Politika "buna izin var mı" sorusunu yanıtlıyor. "Bu ne kadar önemli" sorusuna söyleyecek bir şeyi yok; oysa bir insanın bakması gerekip gerekmediğine karar veren soru tam olarak bu. Onun için planı bir risk vektörüne indirgeyen bir blast radius tahmincisi yazdık.
# blast_radius.py — deterministik, bu yolda model yok.
# Girdi normalize edilmiş plan IR. Çıktı hem 0-100 skaler hem de onu üreten vektör.
# İnsan vektörü okur, yönlendirici skaleri okur.
def assess(plan: PlanIR, graph: StateDAG, envelope: ApprovalEnvelope) -> RiskVector:
writes = plan.mutations
# 1. Doğrudan ayak izi, log ölçekli: 3 kaynak ile 300 kaynak arasındaki
# fark derece farkı değil, tür farkıdır.
footprint = 12.0 * log10(1 + len(writes))
# 2. Geçişli fan-out: bu öneri yanlışsa ne kırılır? State DAG üzerinde
# yürünür, asla planın kendisi üzerinde değil — plan neye dokunduğunu
# bilir, kimin ona bağlı olduğunu bilmez.
downstream = graph.downstream_closure(writes.urns(), max_depth=4)
fanout = 18.0 * log10(1 + len(downstream))
# 3. Yenilik: bu ŞEKİLDE bir plan bu kiracı için daha önce onaylandı mı?
# Şekil = (kaynak tipleri, operasyonlar, alan yolları) — değerler değil.
novelty = 0.0 if envelope.contains(plan.shape_hash) else 25.0
# 4. Kiracı kritiklik seviyesi; bizim çıkarımımız değil, müşterinin beyanı.
tier = TIER_WEIGHT[graph.tenant.tier] # prod-critical 1.4 … sandbox 0.6
# 5. Geri alınabilirlik toplamın bir terimi değildir. Bir override'dır.
irreversible = any(
(m.op is DESTROY and graph.node(m.urn).is_stateful)
or m.forces_replacement_of_stateful()
or m.crosses(DATA_DELETION_BOUNDARY)
or m.revokes(LAST_ADMIN_PATH)
for m in writes
)
raw = (footprint + fanout + novelty) * tier
return RiskVector(
score=100.0 if irreversible else min(raw, 99.0),
fanout=len(downstream), novelty=novelty,
irreversible=irreversible, rules_fired=plan.policy_trace.rule_ids,
)
Bunda bize tur kaybettiren üç ayrıntı var. Geri alınamazlık ağırlıklı bir terim değil, sert bir override; çünkü "ama sadece iki kaynak" hiçbir koşulda veri silen bir operasyonu toplaya toplaya eşiğin altına indirebilmemeli. Fan-out planın değil bağımlılık grafının üzerinden hesaplanıyor, zira kendi kapsamını beyan etmek bir agent'ın yapısal olarak dürüst olamayacağı tek şey. Ve ortaya çıkan asıl ürün skaler değil vektör: inceleyen kişi 78 sayısını değil, fanout=214, novelty=25, irreversible=true, rules_fired=[data.infra.pci.tenancy] satırını görüyor.
Açık konuşayım, bu yaklaşımın gerçek trafiğe dayanacağından pek emin değildim. Korkum şuydu: inceleyenler bir süre sonra skor dağılımını öğrenip eşiği bulacak ve altında kalan her şeyi baştan onaylanmış gürültü gibi okumaya başlayacak. Skaleri hiçbir yerde tek başına göstermememizin sebebi tam olarak bu korku.
Eşiğin altında planlar otomatik uygulanıyor: %91,4'ü. Üstünde ise override yolu olmayan sert bir insan kapısı var; tahmincinin geri alınamaz işaretlediği bir plan için "yine de onayla" düğmesi yok. O düğmeyi kaldırmak tartışma oldu, hem de kısa ve nazik olmayan cinsten bir tartışma. Kalsın diyenlerin gerekçesi de havada değildi: gece üçte, gerçek bir incident'ın ortasında birileri o düğmeyi mutlaka arayacak. Meseleyi bitiren soru şu oldu: düğmenin açacağı planlar zaten geri alamayacağınız planlarsa, o düğme tam olarak ne işe yarayacak?
Bir risk skoru kimsenin ilgisini çekmediği sürece işini yapıyor demektir. İnsanlar arkasındaki vektörü okumak yerine sayıyla pazarlığa oturmaya başladıysa, kapı diye bir kumar makinesi kurmuşsunuz demektir.
İki agent, tek kaynak, sıradan bir salı
Buraya kadar anlatılan her şey sessizce tek agent varsayıyor ve o varsayım tam olarak ikinci agent devreye girene kadar ayakta kalıyor. Sonrasında cost agent'ı ile security agent'ı aynı node group üzerinde aynı anda akıl yürütüyor ve "ikisi de haklıysa ne olacak" sorusu taşıyıcı hale geliyor.
Bariz cevap kiracı başına tek kilit. Çalışıyor, ama kullanılamaz. Bir müşterinin tüm altyapısını oraya ilk varan agent'ın arkasında sıraya diziyor; 90 saniyelik bir maliyet taramasının arkasında bekleyen bir incident-response agent'ı ise artık throughput problemi olmaktan çıkıp doğrudan availability problemine dönüşüyor.
Bu yüzden yalnızca planın gerçekten dokunduğu yazma kümesinin alt grafını kilitliyoruz. Kilitler, deadlock'u ihtimal dışı değil yapısal olarak imkânsız kılmak için kanonik URN sırasıyla alınıyor; takılan bir agent süreci lease'i dolduktan sonra apply edemesin diye de fencing token'lı lease olarak tutuluyor. Üstüne dağıtık transaction tasarımından neredeyse birebir alınmış bir optimistic concurrency control geliyor: her plan okuduğu kümenin generation sayaçlarını kaydediyor, apply anında bunlar yeniden doğrulanıyor. Bir şey oynadıysa plan geçersizleşiyor ve agent taze state üzerinden yeniden planlıyor.
Planların yaklaşık %3,1'i bu şekilde geçersizleşiyor. Bu ucuz, çünkü yeniden planlama playbook seviyesinde bir karar; alternatifin yanında ise iyice ucuz, zira alternatif iki doğru planın birleşip tek bir yanlış sonuç üretmesi. p95 plan kuyruk beklemesi global kilitli prototipteki 4dk 12sn'den 840ms'ye indi, filo dakikada yaklaşık 600 apply'ı sürdürülebilir şekilde taşıyor.
Hiç alarm çalmayan fırtına
Kontrol döngüsü, agent'ların yazdığı desired state ile gözlenen bulut state'ini sürekli, Kubernetes operator tarzında karşılaştırıyor ve drift'i kimseye sormadan onarıyor. Bu tasarımın gerçekten öğretici ilk production incident'ı ise hiç incident'a benzemiyordu.
Bir kiracının cost agent'ı node group'u sürekli daha ucuz bir instance ailesine taşıyordu. Aynı kiracının security agent'ının duruş temeli ise uyumluluk kapsamındaki bir iş yükü için belirli bir attestation yeteneğine sahip bir instance ailesi şart koşuyordu. İki agent da yerel olarak haklıydı. İkisi de aynı alan üzerinde yetkiliydi. Her reconcile turunda biri diğerinin yaptığını geri alıyordu.
Hiçbir şey down değildi, hiçbir SLO yanmadı, hiç alarm çalmadı. Dokuz gün ve 1.447 geçiş boyunca sürdü. Fark etmemizin sebebi bir bölgede bulut sağlayıcının API throttling alarmının tetiklenmesi ve birinin çağıranı merak etmesiydi; kiracının faturasındaki 9.400 dolarlık anomali de teyit olarak geldi. Hâlâ aklımda kalan kısım burası: bize bunu alarmlarımız söylemedi, dashboard'larımız söylemedi, epey gurur duyduğumuz gözlemlenebilirlik yığını hiç söylemedi. Bir fatura söyledi.
Çözümün iki yarısı var. Birincisi sahiplik: her (kaynak, alan yolu) çiftinin tam olarak tek bir sahip agent rolü var ve bu bir öncelik kafesiyle çözülüyor — güvenlik duruşu incident response'un, o provisioning'in, o da maliyetin üstünde. Sahibi olmayan bir rol, sahipli bir alanı değiştirmiyor; sahibine bir öneri açıyor, sahip de ya kabul ediyor ya da neden etmediğini yazıyor. Kubernetes aynı içgörüye server-side apply'daki field manager'larla varmıştı, biz pahalı yoldan vardık. İkinci yarı bir sönümleyici; çünkü sahiplik yalnızca beyan edilmiş çakışmaları çözüyor, kendiliğinden ortaya çıkanları değil.
// Reconciliation "daha çok yakınsa" demek değildir. Kendisiyle dövüşen
// bir döngü durmalı ve kiminle dövüştüğünü söyleyebilmelidir.
func (r *Reconciler) Admit(f FieldPath, want Value, by AgentRole) Decision {
if owner := r.ownership.Owner(f); owner != by {
return Propose{To: owner, Reason: ConflictingIntent} // sahip olmayan yazmaz, önerir
}
if br := r.breakers.Get(f); br.State() == Open {
return Hold{Until: br.ResetAt(), Reason: FlapSuppressed}
}
// "Revisit", alanın pencere içinde zaten aldığı bir değere geri dönüştür.
// Bu yakınsama değil, churn'dür.
win := r.history.Window(f, 30*time.Minute)
if win.Revisits(want) && r.breakers.Get(f).Trip(threshold: 5) {
// İki tarafın provenance izini yan yana koyarak yükselt ki insan
// tek bir muamma değil, iki gerekçe görsün.
r.escalate(f, win.Traces())
return Hold{Reason: FlapSuppressed}
}
return Apply{}
}
Otuz dakika içinde beş geri dönüş devreyi açıyor. O alan yolundaki reconciliation duruyor, kaynak mevcut değerinde sabitleniyor ve çakışma her iki agent'ın gerekçesiyle birlikte yükseltiliyor. İnsan çözdüğünde ya da kimse dokunmazsa 24 saat sonra half-open bir yoklama yapılıyor.
Agentic sistemlerde en uzun yaşayan hata modları, hataya benzemeyenler oluyor. Dokuz gün boyunca hiçbir şey down değildi; sadece bir değer sessiz sessiz ileri geri gidiyordu. Yalnızca kesintiye alarm kuruyorsanız bunu hiç göremezsiniz. Churn'e de kurun.
Düşünmenin faturası
Filo günde yaklaşık 2,3 milyon reconcile kararı veriyor. Her biri için tam bir agent akıl yürütme döngüsü çalıştırmak, cost agent'ının düşürmekle görevli olduğu bulut faturasından daha büyük bir inference faturası çıkarırdı; üstüne kontrol döngüsünü kovaladığı drift'ten yavaş yapan bir karar gecikmesi. İkisi de ince hesap isteyen problemler değildi, kabaca çarpınca ikisi de görünüyordu.
İşimize yarayan özellik şu: reconciliation kararları ezici çoğunlukla Zipf dağılımlı. Aynı avuç dolusu durum binlerce ortamda tekrar ediyor. Bu yüzden bir karar şekli istikrarlı bir politika sonucuyla tekrar ettiğinde onu parametreli bir playbook'a derliyoruz: plan IR şekli üzerinde deterministik bir eşleştirici ve sıfırdan akıl yürütmek yerine doldurulup doğrulanan slot'lar. Yönlendirme de doğal olarak buradan çıkıyor. Kararların %61,2'si hiç inference olmadan playbook isabetiyle çözülüyor, %33,0'ü hızlı ve ucuz bir modele gidiyor, %5,8'i şekil ıskası, düşük güven, politika sınırına yakınlık veya blast radius tabanı nedeniyle güçlü modele yükseliyor. Kiracının topoloji özetini ve derlenmiş politika özetini taşıyan prompt önekleri turlar arasında sabit kaldığı için %89 isabetle cache'leniyor, state generation arttığında geçersizleşiyor.
Ortam-ay başına inference maliyeti %71 düştü, p95 karar gecikmesi 6,4sn'den 410ms'ye indi. İkincil etki birincilden önemli çıktı: kararlar ucuzlayınca daha sık bir reconcile ritmi karşılanabilir hale geldi, bu da filo genelinde drift pencerelerini daralttı. Yükseltme oranı da en iyi öncü göstergelerimizden birine dönüştü; güçlü model payı tırmanan bir kiracı, ortamı daha önce gördüğümüz bütün şekillerin dışına çıkmış bir kiracı demek ve bu genelde incident'ından bir iki hafta önce oluyor.
"Bunu neden yaptı?"
Otonom yazılım bir müşterinin production altyapısını değiştirdiğinde "bunu neden yaptı" sorusunun cevabı omuz silkmek olamaz. Her karar bir provenance span'i üretiyor: model ve sürümü, içerik adresli render edilmiş prompt, getirilen her bağlam dokümanının ID'si ve içerik hash'i, tool çağrıları ve sonuçları, ortaya çıkan plan IR'ı ve hash'i, tetiklenen kural ID'lerine kadar politika karar günlüğü, risk vektörü ve varsa onaylayan insanın kimliği. Span'ler agent'lar arasında iç içe geçiyor; security agent'ının bulgusuna karşılık provisioning agent'ının yaptığı bir değişiklik tek bir nedensellik ağacı olarak okunuyor.
Kabaca biliş için dağıtık izleme, ve asıl parasını ters indeks kazandırıyor. Getirilen bir dokümanın bayat ya da yanlış olduğu anlaşıldığında, filo genelinde o dokümandan türeyen her eylemi tek tek sayabiliyorsunuz. Bu, kötü bir bilginin blast radius'u ve hiçbir bulut denetim günlüğünün bugüne dek cevaplayabildiği bir soru değil.
Hiç beklemediğim bir faydası da insan kapısını kurtarmak oldu. Provenance'tan önce kapıya takılan bir planı incelemek, agent'ın gerekçesini bir diff'ten yeniden inşa etmek demekti; incelemeler yavaştı ve yavaş incelemeler er geç lastik damgaya kayıyor. Bir güvenlik kontrolünü işe yaramazdan da beter yapan şey tam olarak budur, çünkü dışarıdan hâlâ çalışıyor görünür. İz eklendikten sonra onaya kadar geçen medyan süre 31 dakikadan 4 dakikaya indi, kuyrukta terk edilen veya süresi dolan kapılı planlar %11'den %1'in altına düştü.
Son metre: kalıcı kimlik bilgisi yok
Yukarıdakilerin tamamı bir agent'ın ne önerebileceğini kısıtlıyor. Hiçbiri, agent sürecinin elinde altyapı geneli kalıcı kimlik bilgisi varsa ne yapabileceğini kısıtlamıyor; bu da halüsinasyon probleminden kesinlikle daha kötü bir problem, çünkü modelin yanılmasını dahi gerektirmiyor. Geniş ve kalıcı erişimi olan, ele geçirilmiş ya da sadece hatalı bir agent, kusursuz davranırken bile tehlikelidir. Tehdit modelimize, bağlam olarak alınan kaynak etiketleri ve IAM politika açıklamaları üzerinden gelen prompt injection'ı da kattık; kulağa egzotik geliyor ama işlettiği varlığı okumak zaten agent'ın asli işi.
Dolayısıyla agent'lar hiçbir kalıcı production kimlik bilgisi tutmuyor. Apply anında bir credential broker onaylı plan ID'sini alıyor, plan IR hash'inin bir insanın ya da otomatik uygulama yönlendiricisinin onayladığı hash ile hâlâ eşleştiğini doğruluyor (onaylanan planın A, uygulanan planın B olduğu açık böyle kapanıyor) ve planın yazma kümesinden mekanik olarak en az yetkili bir oturum politikası türetiyor: tam olarak o kaynak kimlikleri, her operasyon tipinin gerektirdiği tam eylemler, bir tık fazlası değil. Kimlik bilgisi tek kullanımlık, workload kimliğine ve plan ID'sine bağlı, min(10 dakika, 3 × tahmini apply süresi) TTL'i ile veriliyor ve süresi dolmaya bırakılmak yerine apply biter bitmez iptal ediliyor. Planlama ise ayrı, salt okunur ve aynı ölçüde kısa ömürlü bir yoldan ilerliyor.
Bu politikaları hiçbir insan yazmıyor. Onaylanmış bir planın fonksiyonu olarak türüyorlar; IR yatırımının kendini üçüncü kez amorti ettiği yer de burası.
Bunun asıl getirisi
Guardrail ve kimlik bilgisi yeniden tasarımını izleyen iki çeyrekte agent kaynaklı Sev-2 ve üzeri incident'lar çeyrekte 23'ten 2'ye indi; yaklaşık 2,6 milyon apply boyunca bir agent'ın onaylı planın dışına çıkmasından kaynaklanan sıfır incident yaşandı. Filo ~3.400 eşzamanlı ortamı global kilit serileştirmesi olmadan reconcile ediyor, planların %91,4'ünü insan olmadan otomatik uyguluyor, kalan %8,6'yı da medyan 4 dakikada incelemeden geçiriyor.
Yönlendiriciyi ilk kez gözetimsiz bıraktığımız gece pek uyuyamadım; apply akışı telefonumda açıktı ve kaç kez baktığımı yazmak istemiyorum. O geceyi katlanılabilir kılan şey modele duyduğum güvenin artması değildi. Modelin bir hatasının cloud API'sine ulaşabilmesi için hangi bileşenin hangi sırayla çökmesi gerektiğini tek tek sayabiliyor olmamdı.
Asıl önemsediğimiz sayı sonuncusu, çünkü sistemin yalnızca güvenli değil, kullanılabilir de olduğunu gösteren tek sayı o. Otonomiyi yavaşlatan güvenlik mekanizmaları kapatılır. Bir kontrol düzlemi nadiren izin vermesi gereken şeyi engelleyerek başarısız olur; asıl başarısızlığı insanların sessizce onun etrafından dolaşmaya başlamasıdır. Bunu çalıştıran şey daha iyi bir model bulmamız olmadı; modelin yetkisinin akıl yürütemeyen bileşenlerle sınırlanması gerektiğini kabul etmemiz oldu: deterministik bir politika değerlendiricisi, geri alınamazlık için override'ı olan bir risk fonksiyonu, bir kilit yöneticisi, bir devre kesici ve izinleri güvenden değil onaylanmış bir artefakttan türeten bir credential broker. Otonomi agent'ın bir özelliği değildir. Agent'ın içinde çalışmasına izin verilen sistemin özelliğidir.