Haziran 12 2026

Canlı Ortamda Kontrolden Çıkan Yapay Zeka Ajanları Nasıl Durdurulur? Agentic Rollback Stratejileri

Geleneksel mikroservisler çöktüğünde ne yapacağımızı çok iyi biliyoruz: OOMKilled logunu görürüz, Kubernetes pod’u yeniden başlatır, en kötü ihtimalle bir önceki kararlı imaja geri döneriz. Peki ya canlı ortamda kendi kendine tool çalıştıran, veritabanı şemalarını manipüle eden veya üçüncü parti API limitlerinizi saniyeler içinde eriten bir agentic ai sistemi kontrolden çıkarsa? LLM tabanlı otonom ajanların üretim ortamında yer aldığı bu yeni çağda, klasik incident response süreçleri yetersiz kalıyor. Bu yazıda, kontrolden çıkan otonom sistemleri anında dizginlemek için uygulayabileceğimiz pratik rollback strategies ve ai agent observability mimarilerini doğrudan kod ve konfigürasyon örnekleriyle ele alıyoruz.

Ajan Kaosu: Klasik Rollback Neden İşe Yaramaz?

Klasik bir deployment’ta rollback yaptığınızda, uygulamanın durumunu (state) değil, uygulamanın çalıştırdığı kodu geri alırsınız. Ancak ajanlarda durum farklıdır. Bir ajan kontrolden çıktığında sorun kodun kendisinde değil, ajanın o anki “çalışma belleğinde” (context/memory), aldığı otonom kararlarda ve bu kararlar doğrultusunda tetiklediği harici tool’lardadır.

Örneğin, bir müşteri ilişkileri ajanı düşünün. Bir prompt injection veya beklenmedik bir API yanıtı yüzünden sonsuz bir döngüye (hallucination cascade) girdi ve her döngüde veritabanına yeni kayıtlar ekleyip müşterilere SMS gönderiyor. Bu ajanın pod’unu restart etmek hiçbir işe yaramaz; çünkü ajan ayağa kalktığında veritabanındaki kirli state’i veya mesaj kuyruğundaki bekleyen görevleri okuyup kaldığı yerden çılgınlığına devam edecektir. Bize kod tabanlı değil, state ve ağ tabanlı müdahale mekanizmaları gerekiyor.

1. AI Agent Observability: Felaketi Erken Teşhis Etmek

Bir ajanın raydan çıktığını anlamak için geleneksel CPU/Memory metrikleri tek başına yetersizdir. CPU %10’dayken de bir ajan şirket kredi kartını limitsiz API çağrılarıyla eritiyor olabilir. İzlememiz gereken metrikler ajana özel olmalıdır:

  • Token Velocity (Saniyede Tüketilen Token): Beklenmedik bir şekilde tavan yapan token tüketimi, ajanın bir döngüye girdiğinin en net göstergesidir.
  • Tool Execution Depth (Araç Çağrı Derinliği): Bir ajanın tek bir kullanıcı isteğini çözmek için ardışık olarak çağırdığı araç (tool) sayısı sınırı aşmalıdır.
  • Semantic Drift (Anlamsal Sapma): Ajanın LLM’e gönderdiği sistem prompt’u ile LLM’den dönen yanıtların anlamsal benzerliğinin (cosine similarity) hızla düşmesi.

Aşağıdaki Prometheus metrik tanımı ve bir Python middleware örneğiyle, ajanın her tool çağrısını nasıl takip edebileceğimizi ve limiti aşanları nasıl engelleyeceğimizi görelim:

# Prometheus metriklerini expose etmek için örnek bir Python izleme katmanı
from prometheus_client import Counter, Histogram, Gauge
import time

# Metriklerin tanımlanması
AGENT_TOOL_CALLS = Counter('agent_tool_calls_total', 'Total number of tool executions', ['agent_id', 'tool_name'])
AGENT_LOOP_DEPTH = Gauge('agent_loop_depth', 'Current execution steps for a single task', ['agent_id', 'session_id'])
LLM_TOKEN_USAGE = Counter('llm_token_usage_total', 'Total tokens consumed', ['agent_id', 'token_type'])

class AgentSupervisor:
    def __init__(self, agent_id: str, max_allowed_steps: int = 10):
        self.agent_id = agent_id
        self.max_allowed_steps = max_allowed_steps

    def verify_step(self, session_id: str, current_step: int, tool_name: str):
        # Derinlik kontrolü
        AGENT_LOOP_DEPTH.labels(agent_id=self.agent_id, session_id=session_id).set(current_step)
        AGENT_TOOL_CALLS.labels(agent_id=self.agent_id, tool_name=tool_name).inc()
        
        if current_step > self.max_allowed_steps:
            # Kritik eşik aşıldı, alarm üret ve akışı kes
            raise RuntimeError(f"LIMIT_EXCEEDED: Agent {self.agent_id} exceeded maximum step depth of {self.max_allowed_steps} in session {session_id}!")

2. Acil Müdahale: Network Isolation ve Kill-Switch

Eğer bir ajan döngüye girdiyse ve veritabanını bozuyorsa, ilk yapılması gereken şey ajanın dış dünya ve LLM sağlayıcıları (OpenAI, Anthropic vb.) ile olan bağını kesmektir. SRE ekipleri için en hızlı aksiyon, Kubernetes seviyesinde uygulanacak dinamik bir acil durum ağ politikasıdır (NetworkPolicy).

Aşağıdaki Kubernetes NetworkPolicy örneği, etiketlenmiş ajan pod’larının dış dünyadaki LLM API’lerine (Egress) erişimini saniyeler içinde engellemek için kullanılabilir:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: isolate-rogue-agent
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: agentic-worker
      status: quarantine # Acil durumda bu etiketi set edeceğiz
  policyTypes:
  - Egress
  egress:
  # Sadece cluster içi DNS çözümlemesine izin ver, dış dünyaya giden tüm HTTP/HTTPS trafiğini engelle
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

Bir olay anında (incident response sırasında), SRE mühendisi tek bir komutla ajanı karantinaya alabilir:

kubectl label pods -l app=agentic-worker status=quarantine --overwrite -n production

Bu komut çalıştırıldığı an, kural devreye girer. Ajanın LLM API’leri ile olan iletişimi kesilir. Ajan artık yeni kararlar alamayacağı için güvenli bir şekilde durma noktasına (halt state) gelir.

3. State Rollback: Event Sourcing Yaklaşımı

Ajanı durdurduk. Peki ya ajanın veritabanında yaptığı tahribat ne olacak? Örneğin, son 5 dakika içinde 100 farklı kullanıcının yetki tablosunu güncellediyse?

İşte bu yüzden, otonom kararlar alan ajan sistemlerinde doğrudan “State Mutation” yapmak yerine Event Sourcing kullanılması şarttır. Ajan doğrudan veritabanına yazmamalı; bunun yerine yapmak istediği eylemleri birer “Event” olarak fırlatmalıdır. Bu mimari bize olay anında Saga Pattern veya Compensating Transactions (Telafi Edici İşlemler) uygulama şansı verir.

Örnek bir Redis tabanlı event loglama ve geri alma mekanizması kurgulayalım:

import redis
import json

r = redis.Redis(host='localhost', port=6379, db=0)

def execute_agent_action(session_id: str, action_type: str, payload: dict):
    # Ajanın yaptığı her işlemi logla (Saga Log)
    event_id = r.incr(f"session:{session_id}:event_counter")
    event_data = {
        "event_id": event_id,
        "action_type": action_type,
        "payload": payload,
        "status": "executed"
    }
    # Event listesine ekle
    r.rpush(f"session:{session_id}:events", json.dumps(event_data))
    
    # Gerçek işlemi simüle et
    print(f"Executing: {action_type} with {payload}")

def rollback_session(session_id: str):
    # Geriye doğru telafi işlemlerini çalıştır (LIFO order)
    events = r.lrange(f"session:{session_id}:events", 0, -1)
    
    for event_raw in reversed(events):
        event = json.loads(event_raw)
        action_type = event["action_type"]
        payload = event["payload"]
        
        print(f"CRITICAL ROLLBACK: Reversing {action_type} for payload {payload}")
        if action_type == "CREATE_USER":
            # Kullanıcıyı sil veya pasife al
            print(f"Compensating: Deleting user {payload['user_id']}")
        elif action_type == "UPDATE_BALANCE":
            # Bakiyeyi eski haline getir
            print(f"Compensating: Restoring balance for account {payload['account_id']} by -{payload['amount']}")
            
    # Temizlik
    r.delete(f"session:{session_id}:events")

4. Dynamic Prompt Rollback (Sıcak Prompt Değişimi)

Bazen sorun sistem altyapısında değil, ajanın LLM’e gönderdiği “Sistem Prompt’u” üzerindeki mantık hatasıdır. Canlı ortamda ajanın kodunu yeniden deploy etmek (CI/CD pipeline beklemek) yerine, prompt’ları dinamik bir konfigürasyon deposundan (örneğin Consul, Spring Cloud Config veya Redis) beslemek gerekir.

Kritik bir hata anında, prompt versiyonunu saniyeler içinde eski haline (rollback) getirebilmeliyiz:

# Consul veya benzeri bir K/V store üzerinden prompt versiyonunu rollback etme
curl --request PUT \
  --data '{"version": "v1.2.0", "prompt": "You are a helpful assistant. Do NOT execute any DB mutations without direct human approval."}' \
  http://localhost:8500/v1/kv/agents/customer-support/system-prompt

Ajan kodunuz her yeni oturum açılışında bu dinamik değeri okuyacak şekilde tasarlanmalıdır. Böylece tek bir API çağrısıyla tüm ajanın davranış şemasını anında değiştirebilirsiniz.

Özet ve SRE Yol Haritası

Geleceğin DevOps dünyası, sadece statik kodların değil, kendi kararlarını veren dinamik ajanların yönetimi üzerine kuruluyor. Canlı ortamda huzurlu uyumak istiyorsanız, şu adımları üretim mimarinize şimdiden dahil edin:

  1. Ajanlarınızı izole namespace’lerde çalıştırın ve acil durumlar için ağ seviyesinde NetworkPolicy hazır bulundurun.
  2. Ajanların veritabanlarına doğrudan SQL çalıştırmasına asla izin vermeyin; bunun yerine gated tool calling (onay mekanizmaları) ve event-driven mimariler kullanın.
  3. Token-rate limits uygulayarak bütçenizi ve altyapınızı sonsuz döngülerden koruyun.
  4. Prometheus üzerinde agent_loop_depth metriği için acil durum alarmları kurun.
Category: Genel | LEAVE A COMMENT
Temmuz 18 2025

Mühendis Yakılmasına Son: Sağlıklı ve Sürdürülebilir Bir On-Call Kültürü Nasıl Kurulur?

Gece saat 03:00. Slack veya PagerDuty’den gelen o tanıdık siren sesiyle uyanıyorsunuz. Eğer modern bir devops kültürü yerine “kim ayaktaysa baksın” kaosunu yaşıyorsanız, ekibinizde tükenmişlik sendromu (burnout) çanları çoktan çalmaya başlamış demektir. Doğru yapılandırılmamış bir on-call yönetimi, sadece sistemlerin değil, en yetenekli mühendislerinizin de sessizce istifa etmesine (veya daha kötüsü, sistemin ortasına çökmesine) neden olur. Bu yazıda, incident response süreçlerini nasıl insani, sürdürülebilir ve otomatize hale getireceğimizi inceliyoruz. Sıkıcı teorileri bir kenara bırakıp doğrudan production ortamında can kurtaracak pratiklere odaklanıyoruz.

Alert Fatigue ile Savaş: Sadece “Aksiyon Alınabilir” Alarmlar

Alert fatigue (alarm yorgunluğu), on-call mühendislerinin en büyük düşmanıdır. CPU kullanımının %85’e çıkması tek başına bir alarm sebebi olmamalıdır. Eğer alarm çaldığında mühendisin yapabileceği net, manuel bir aksiyon yoksa (örneğin sistem kendi kendine auto-scale oluyorsa), o alarm çöp gürültüdür. Sadece kullanıcı deneyimini doğrudan etkileyen (SLO/SLI ihlalleri) veya sistemin tamamen durma noktasına geldiğini gösteren durumlar pager seviyesinde olmalıdır.

Gürültüyü azaltmak için Prometheus Alertmanager üzerinde akıllı gruplama (grouping) ve engelleme (inhibition) kuralları uygulamalısınız. Örneğin, tüm veri merkezi down olmuşken her bir pod için ayrı ayrı 500 tane “PodDown” alarmı almak yerine, tek bir “DatacenterDown” alarmı tetiklenmeli ve alt alarmlar susturulmalıdır.

Aşağıdaki Alertmanager konfigürasyon bloğu, benzer alarmları nasıl gruplayıp birbirini ezmesini (inhibit) sağlayabileceğinizi gösterir:

# alertmanager.yml
route:
  group_by: ['alertname', 'cluster', 'service']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'pagerduty-high-priority'
  routes:
    - match:
        severity: warning
      receiver: 'slack-low-priority'

inhibit_rules:
  - source_match:
      alertname: 'NodeNetworkDown'
    target_match_re:
      alertname: 'InstanceDown|TargetDown'
    equal: ['node', 'instance']

Neden böyle yapıyoruz? Çünkü NodeNetworkDown olduğunda, o node üzerindeki tüm container’ların erişilemez olması kaçınılmazdır. Bu engelleme kuralı sayesinde, gece yarısı telefonunuza 50 farklı push bildirimi gelmez; sorunun kök nedenine odaklanan tek bir kritik alarm alırsınız.

Rotasyon ve Eskalasyon Politikalarında Matematiksel Adalet

Adil bir on-call rotasyonu oluşturmak, excel tablolarından fazlasını gerektirir. Tek bir birincil (Primary) nöbetçi koyup tüm yükü ona yıkmak, tek hata noktası (SPOF) yaratmaktır. Sürdürülebilir bir sistemde her zaman Primary ve Secondary (Shadow/Backup) rollerinin tanımlanması gerekir.

Eğer global bir ekipseniz, “Follow-the-Sun” modelini uygulamak hayat kurtarır. Bu modelde nöbetler, coğrafi olarak gündüz vaktinde olan bölgeye devredilir. Eğer lokal bir ekipseniz, haftalık rotasyonların cuma günü saat 17:00’de devredilmesi yerine salı günü öğleden sonra devredilmesi daha sağlıklıdır. Böylece yeni nöbetçi, haftalık iş yoğunluğunun ortasında sisteme ısınır ve olası devir-teslim sorunlarını mesai saatleri içinde çözer.

Bu yapıyı kod olarak yönetmek (Infrastructure as Code) esnekliği artırır. Aşağıdaki Terraform konfigürasyonu, PagerDuty üzerinde adil bir eskalasyon politikasını tanımlar:

# pagerduty.tf
resource "pagerduty_escalation_policy" "production_policy" {
  name      = "Production Escalation Policy"
  num_loops = 2

  rule {
    escalation_delay_in_minutes = 10
    target {
      id   = pagerduty_schedule.primary_schedule.id
      type = "schedule_reference"
    }
  }

  rule {
    escalation_delay_in_minutes = 15
    target {
      id   = pagerduty_schedule.secondary_schedule.id
      type = "schedule_reference"
    }
  }

  rule {
    escalation_delay_in_minutes = 20
    target {
      id   = pagerduty_user.engineering_lead.id
      type = "user_reference"
    }
  }
}

Buradaki felsefe şudur: Primary nöbetçi 10 dakika içinde alarmı ack’lemezse (onaylamazsa), alarm otomatik olarak Secondary nöbetçiye geçer. O da 15 dakika içinde yanıt vermezse, engineering lead seviyesine eskalasyon gerçekleşir. Bu hiyerarşi, nöbetteki mühendisin üzerindeki psikolojik baskıyı azaltır; arkasında her zaman bir güvence olduğunu bilir.

Incident Response Otomasyonu: Self-Healing ve ChatOps

Bir alarm çaldığında mühendisin yaptığı ilk iş genellikle terminali açıp df -h yazmak veya ilgili servisi restart etmekse, burada ciddi bir otomasyon eksiği var demektir. Tekrarlanan runbook adımları, insan müdahalesine gerek kalmadan otomatik olarak çalıştırılmalıdır.

Örneğin, disk doluluk alarmı tetiklendiğinde otomatik olarak geçici cache dosyalarını temizleyen veya log rotasyonunu tetikleyen bir Kubernetes DaemonSet veya serverless fonksiyon yazabilirsiniz. İnsan faktörünü sadece “otomasyonun çözemediği” durumlarda devreye sokmalıyız.

Eğer manuel müdahale şartsa, bunu Slack/MS Teams üzerinden ChatOps ile yapmak hızı katlar. Aşağıdaki basit bash script’i, Alertmanager webhook’undan gelen disk alarmını yakalayıp, AWS API’si üzerinden EBS hacmini otomatik olarak genişleten bir self-healing mekanizmasının mantığını göstermektedir:

#!/usr/bin/env bash
# auto_expand_disk.sh
set -euo pipefail

ALERT_PAYLOAD=$(cat)
VOLUME_ID=$(echo "$ALERT_PAYLOAD" | jq -r '.alerts[0].labels.volume_id')
REGION=$(echo "$ALERT_PAYLOAD" | jq -r '.alerts[0].labels.region')

echo "Kritik disk alarmı alındı: $VOLUME_ID. Disk boyutu %10 artırılıyor..."

# Mevcut boyutu al
CURRENT_SIZE=$(aws ec2 describe-volumes \
  --volume-ids "$VOLUME_ID" \
  --region "$REGION" \
  --query "Volumes[0].Size" --output text)

NEW_SIZE=$(( CURRENT_SIZE + (CURRENT_SIZE * 10 / 100) ))

# AWS üzerinde diski genişlet
aws ec2 modify-volume \
  --volume-id "$VOLUME_ID" \
  --region "$REGION" \
  --size "$NEW_SIZE"

echo "Disk başarıyla $NEW_SIZE GB değerine genişletildi."

Neden böyle bir otomasyon kuruyoruz? Çünkü gece 04:00’te bir mühendisi sadece disk genişletmek için uyandırmak, operasyonel verimliliği baltalamaktan başka bir işe yaramaz. Bırakın otomasyon diski genişletsin, mühendis sabah kahvesini içerken slack kanalındaki log’lardan olayı takip etsin.

Suçsuz (Blameless) Post-Mortem Kültürü

Sürdürülebilir on-call kültürünün teknik olmayan en kritik ayağı, olay sonrası analizlerdir. Bir incident bittiğinde her şey bitmiş sayılmaz. Amaç “Hatayı kim yaptı?” sorusunu sormak değil, “Sistemimiz bu hatanın yapılmasına nasıl izin verdi?” sorusuna yanıt aramaktır.

Blameless post-mortem süreçlerinde şu üç kuralı asla esnetmeyin:

  • İnsanlar hata yapabilir: Süreçleriniz ve tool’larınız bu hataları tolere edebilecek şekilde tasarlanmalıdır.
  • Zaman çizelgesi çıkarın: Alarmın çalma anından, ilk müdahaleye ve nihai çözüme (mitigation) kadar geçen süreci kronolojik olarak dökün.
  • Aksiyon maddeleri (Action Items) üretin: Her post-mortem belgesinden, gelecekte benzer hatanın tekrarlanmasını önleyecek en az 2 adet Jira task’i çıkmalı ve bunlar sonraki sprint’e dahil edilmelidir.

Sonuç: Mühendisleri Yakmadan Sistemleri Ayakta Tutmak

Sağlıklı bir on-call sistemi kurmak, teknik bir zorunluluk olduğu kadar etik bir sorumluluktur. Ekibinizi sürekli yangın söndüren itfaiyecilere dönüştürmek yerine, yangının hiç çıkmamasını sağlayan sistem mimarları haline getirmelisiniz. Alarmlarınızı sadeleştirin, rotasyonlarınızı adilleştirin, otomasyona yatırım yapın ve her hatayı sisteminizi güçlendirmek için bir fırsat olarak görün. Unutmayın; iyi bir SRE, uykusunu en iyi almış SRE’dir.

Category: Genel | LEAVE A COMMENT