Ana sayfa → Teknik
Agent’ın İzi: Log Değil, Karar Zinciri
Mesaj kısaydı: “Agent dün geceki rakamı yanlış söyledi.” Log’u açtım: 400 satır JSON, hepsi zaman sıralı, hepsi doğru. Yanlışın hangi adımda doğduğunu bulmam 40 dakika sürdü. Sebep bir tool argümanındaki tarih aralığıydı ve satır 217’de duruyordu. Bugün aynı soruyu 12 saniyede cevaplıyorum; log’u değil, koşunun ağacını açıyorum.
- Log zaman sıralıdır, koşu ise ağaçtır. “Hangi adım bu kararı doğurdu” sorusunu düz satırlar cevaplamaz.
- Koşu = trace, adım = span, tool çağrısı = alt span. Mikroservislerdeki yapının aynısı; üzerine agent alanları eklenir: model, prompt sürümü, token, tool argüman özeti, fren.
- En değerli alan argüman özeti. Hatalarımızın çoğu modelin “yanlış düşünmesi” değil, tool’a yanlış argüman vermesiydi: 30 günün 3’ü.
- Müşteri verisi maskelenir. Ham cevap değil, ilk 500 karakter + hash. Hash iki koşunun aynı veriyi görüp görmediğini söyler.
- Yeniden oynatma, hatayı ikiye ayırır: model mi yanlış karar verdi, tool mu yanlış veri döndürdü? Bizde hatalı koşuların üçte ikisi ikinci gruptaydı.
- Kullanıcı geri bildirimi ize bağlanmalı. “Bu cevap yanlış” düğmesi trace kimliğini taşımıyorsa, geri bildirim bir duygudur; taşıyorsa bir hata kaydı.
Neden düz log yetmiyor?
Bir agent koşusunda aynı anda üç şey akıyor: modelin turları, tool çağrıları ve orchestrator’ın adımları. Düz log bunları tek bir şeride diziyor. Sorun, sorularımızın şerit değil ağaç sorusu olması:
- “Bu cevap hangi veriye dayanıyordu?” → cevabı üreten span’in çocuklarına bak.
- “Bu tool neden çağrıldı?” → span’in ebeveynine bak.
- “Süre nereye gitti?” → kardeş span’lerin sürelerini karşılaştır.
- “Dün ile bugün arasında ne değişti?” → iki ağacı yan yana koy.
Bunların hiçbiri “satır 217”yi okuyarak cevaplanmıyor. Altı log dosyası değil, tek ekran yazısındaki dert burada aynısıyla geçerli; tek fark, servis sınırlarının yerini adım sınırlarının alması.
Ne kaydediyoruz?
trace: rec-2026-09-21-01 (gece mutabakati, 38 sn)
├─ span: adim-1 veri_cek 6,1 sn
│ ├─ tool: banka_dosyasi_oku 2,2 sn arg#a91f cevap 480 B
│ └─ tool: islem_listesi 3,8 sn arg#7c02 cevap 512 B kayit=2300
├─ span: adim-2 eslestir 0,4 sn (kod, model yok)
├─ span: adim-3 siniflandir 21,3 sn
│ └─ model: qwen3:4b giris 4.812 tok cikis 233 tok tur 1
└─ span: adim-4 ozet_yaz 10,6 sn
└─ model: qwen3:4b giris 1.340 tok cikis 412 tok tur 1
Her span’de tutulan alanlar, işe yarar bulduğumuz sırayla:
| Alan | Neden |
|---|---|
| Tool argüman özeti | Hataların çoğu burada. Tarih aralığı, müşteri no, limit. Tam argüman değil, maskelenmiş özeti + hash |
| Model ve sürümü | Sürüm değişince eski koşularla karşılaştırma |
| Prompt sürümü | “Dün iyiydi bugün kötü”nün ilk şüphelisi |
| Giren / çıkan token | Maliyetin ve pencere doluluğunun girdisi |
| Cevap boyutu ve hash | İki koşu aynı veriyi mi gördü? |
| Fren bilgisi | Tur sınırı mı, bütçe mi, zaman aşımı mı devreye girdi? |
| Kullanıcı / koşu kimliği | Geri bildirimi ve denetimi bağlamak için |
Neyi kaydetmiyoruz
- Ham müşteri verisi. İsim, IBAN, kimlik numarası maskelenir. Kayıt numaraları açık kalır; onlarsız hata ayıklanmıyor.
- Tool cevabının tamamı. İlk 500 karakter + hash. Tamamı gerekirse veri zaten kaynağında duruyor.
- Modelin bütün ara metni. Karar ve gerekçenin ilk cümlesi yeter; gerisi 14 günde bir sorunu çözmüyor, sadece disk yiyor.
Saklama: ayrıntılı iz 14 gün, özet metrikler 13 ay. Denetim log’u ayrı ve daha uzun: yan etkili her çağrı tam argümanlarıyla, ayrı bir yerde, ayrı yetkiyle.
Sahadan: 40 dakika, sonra 12 saniye
İlk olayda şu sırayla ilerlemiştim: log’u indir, zaman damgasını bul, tool çağrılarını gözle ayıkla, argümanları elle karşılaştır, tarih aralığının bir gün kaydığını gör. 40 dakika.
İz kurulduktan sonra aynı şikâyet geldiğinde:
- Kullanıcının “yanlış” düğmesi trace kimliğini taşıyor; bağlantıyı açtım.
- Ağaçta
adim-1’in altındakiislem_listesispan’ine baktım: argüman özetibaslangic=2026-09-19, olması gereken2026-09-20. - Ebeveyn span’de tarih aralığını üreten kodun sürümü yazıyordu; o gün bir düzeltme çıkmıştı.
12 saniye. Asıl kazanç, hatanın modelde olmadığını saniyeler içinde görebilmekti. İz olmadan geçen 40 dakikanın yarısını modelin cevabını okuyup “acaba anlamadı mı” diye düşünerek harcamıştım.
Yeniden oynatma
İzde tool cevaplarının hash’i ve ilk 500 karakteri var; ayrıca hatalı koşularda cevabın tamamını 48 saat saklıyoruz. Bu, koşuyu yeniden oynatmayı mümkün kılıyor: aynı girdi, kayıtlı tool cevapları, gerçek tool çağrısı yok.
$ agent replay rec-2026-09-21-01 --model qwen3:4b
adim-3 siniflandir: 13 kayit -> 11 dogru (onceki kosu: 11)
sonuc: ayni
$ agent replay rec-2026-09-21-01 --model qwen3:8b --prompt v7
adim-3 siniflandir: 13 kayit -> 13 dogru
sonuc: farkli (2 kayit duzeldi)
Faydaları:
- Hatayı ikiye ayırır. Kayıtlı cevaplarla aynı hata çıkıyorsa suç modelde; çıkmıyorsa tool ya da veri değişmiş.
- Sürüm karşılaştırmasının en ucuz yolu. Gerçek sistemleri hiç çağırmadan, gerçek bir koşu üzerinde.
- Yan etki yok. Replay modunda yazma tool’ları kapalı; para hareketi olan bir adımı kazara tekrar çalıştırmazsın.
- Eval setinin kaynağı. Gerçek hatalı koşular, en değerli test verisidir.
Geri bildirimi ize bağlamak
Chat ekranındaki “bu cevap yanlış” düğmesi ilk hâlinde sadece bir sayaç artırıyordu. Ayda 20–30 tıklama geliyordu ve hiçbirini inceleyemiyorduk, çünkü hangi koşu olduğunu bilmiyorduk. Düğmeye trace kimliğini ekledikten sonra:
| Önce | Sonra | |
|---|---|---|
| Geri bildirim | Sayaç: “bu ay 24 olumsuz” | 24 koşu, tıklanabilir |
| İncelenen | 0 | 24’ün 24’ü (ortalama 3 dk) |
| Kök sebep | Bilinmiyor | 9 tool argümanı, 6 eksik veri, 5 model, 4 kullanıcı beklentisi |
| Aksiyon | “Model kötü” | 2 tool düzeltmesi, 1 prompt, 1 eval maddesi |
Son satır önemli: geri bildirimlerin yarısından fazlası modelle ilgili değildi. “Model kötü” cümlesi, iz olmayan ekiplerin varsayılan teşhisi.
- Koşuya kimlik ver, kullanıcıya kadar taşı.
- Tool argümanlarını maskeleyip kaydet.
- Model, prompt ve tool sürümlerini span’e yaz.
- Hatalı koşuların %100’ünü, başarılıların örneklemini sakla.
- Replay’i günlük iş akışının parçası yap.
- Denetim log’unu izden ayrı tut.
- Ham müşteri verisini ize yazmak.
- Her koşuyu tam ayrıntıyla sonsuza kadar saklamak.
- Geri bildirimi koşudan kopuk bir sayaç olarak tutmak.
- Modelin bütün ara metnini kaydedip “sonra bakarız” demek.
- Replay’i yazma tool’ları açıkken çalıştırmak.
Ne izlemeli?
- Koşu başına adım ve tur sayısı. Akışın yazılı olup olmadığını söyler.
- Adım bazında süre p50/p95. Yavaşlığın hangi adımda olduğunu gösterir; model her zaman suçlu değil.
- Tool argüman hatası oranı. Bizim en büyük kalemimiz; ayrı bir grafik hak ediyor.
- Fren tetiklenmeleri, türe göre. Hangi fren kaç kez?
- Geri bildirim → kök sebep dağılımı. Aylık; aksiyonun nereye gideceğini bu söyler.
- Örnekleme oranı ve saklama boyutu. İzleme maliyeti de bir maliyettir; bizde koşu başına ~11 KB.
Kontrol listesi
- Her koşunun bir kimliği var mı? Kullanıcı arayüzüne kadar gidiyor mu?
- Adımlar ve tool çağrıları ağaç olarak mı duruyor, satır olarak mı?
- Tool argümanları kaydediliyor mu? Maskeleme kuralı ne?
- Model, prompt ve tool sürümleri her span’de var mı?
- Hangi frenin tetiklendiği yazılıyor mu?
- Hatalı koşular tam, başarılılar örneklem olarak mı saklanıyor?
- Saklama süresi ne? Ayrıntı ve özet için ayrı mı?
- Yeniden oynatma var mı? Replay’de yazma tool’ları kapalı mı?
- Kullanıcı geri bildirimi koşuya bağlı mı?
- Denetim log’u ayrı mı, kimler erişiyor?
- Bir şikâyet geldiğinde kök sebebe kaç dakikada iniyorsun? Ölçtün mü?
Sonuç
O gün 400 satır log’un içinde 40 dakika geçirdim ve sonunda bulduğum şey bir tarih aralığıydı. Modelin bununla ilgisi yoktu; ben onun ilgisi olup olmadığını bilmediğim için yarım saatimi ona harcadım. Gözlemlenebilirliğin değeri tam olarak burada: suçlunun kim olmadığını hızlıca söylemek.
Kurduğumuz şey yeni bir teknoloji değil; mikroservislerde yıllardır kullandığımız trace–span yapısının agent’a uyarlanmışı. Eklediğimiz tek şey, agent’a özgü alanlar: argüman özeti, token, prompt sürümü, fren. Bir de replay, ki en çok onu kullanıyoruz.
Akılda kalacak cümle: agent’ın izi, kararlarının zinciridir. Zinciri kaydetmiyorsan elinde yalnızca sonuç kalır; sonuca bakarak neyi düzelteceğini bilemezsin.