24  API Tasarımı Olarak Araç Tasarımı

Bölüm durumu: çevrildi. Kaynak metin: İngilizce 24. bölüm. Ölçümlerde qwen3.5:9b, ollama 0.24.0 üzerinden sıcaklık 0’da, koşul başına tek geçişle ve hücre başına n = 60 ile çalıştırıldı. ollama, bir araç tanımındaki enum (izin verilen değerlerin açık listesi) değerlerini gramerle kısıtlamıyor (gramerle kısıtlı kod çözmede model her adımda yalnızca şemaya uyan token’ları seçebilir; Bölüm 18). Dolayısıyla aşağıda ölçülen enum, modelin okuduğu bir ipucu — bir kod çözme (decoding) kısıtı değil. Bu, sonucun anlamını değiştiriyor ve önemli olduğu yerde açıkça yazılı. Şema deneyinde hiçbir şey yürütülmüyor; deney yalnızca modelin ürettiği çağrıyı puanlıyor, böylece modelin aritmetiği şemalarla ilgili bir sonucu kirletemiyor. Bölüm 23 ajan döngüsünü ele aldı; bu bölüm ise döngünün kullandığı araçların arayüzünü ele alıyor. Yazılım: NumPy 2.5.2, Python 3.14.5.

Öğrenme hedefleri. Bu bölümün sonunda:

24.1 Açıklama prompt metnidir

Bir araç şeması dokümantasyona benzer ama prompt (istem) gibi davranır.

Araç şeması (tool schema) — modelin bir çağrı seçmeden önce gördüğü ad, açıklama, tipler ve enum’lar. Dokümantasyon değil prompt metnidir, çünkü model ondan tek bir şans alır ve bir tahmini kontrol edemez. ↩︎

Bu tek cümle bölümün özüdür; aşağıdaki her şey ondan çıkar.

Ayrım önemlidir, çünkü ikisi farklı içgüdülerle yazılır. Dokümantasyon, bir meslektaşına sorabilen, kaynağı okuyabilen ya da deneyip görebilen bir okur için yazılır.

Modelin ise tek şansı vardır: yalnızca şemaya bakar ve tahminini kontrol edemez. Kod tabanınızı açamaz. Örnek bir çağrı göremez. Şemanın söylemediği ne varsa model onu tahmin eder — ve tip denetiminden geçen bir tahmin, gerçekten anlamış olmaktan ayırt edilemez.

Yani şema dört ayrı iş görür ve o an hangisi üzerinde çalıştığınızı adlandırabilmek işe yarar:

Dört iş, tek nesne
alan yaptığı iş
ad modele bu aracın ne zaman geçerli olduğunu, başka bir şey okumadan önce söyler
açıklama adın belirsiz bıraktığı durumları çözer ve kullanılmaması gereken durumları eler
parametre tipleri ve enum’lar API’nizin kendi sözcük dağarcığını modelin önüne koyar — ve çalışma zamanınız (runtime) kod çözmeyi kısıtlıyorsa kümenin dışındaki değerleri yalnızca caydırmakla kalmaz, hiç üretilemez kılar. Hangisini elde ettiğiniz şemanıza değil kullandığınız altyapıya bağlı — Bölüm 18
parametre açıklamaları bir kullanıcının bir şeyi nasıl ifade ettiğinden API’nizin ona ne dediğine giden eşlemeyi taşır

İnsanların atladığı satır sonuncusudur ve yanlış kullanımların çoğu buradan gelir. Kullanıcılarınız buna ne kadar para ayrıldı der; API’niz ona budget_allocated der. Aradaki köprüyü bir şeyin kurması gerekir; şema kurmazsa model kendisi bir köprü uydurur.

Neye bakacağız. Önce şemanın hangi kısmının başarıya gerçekten katkı sağladığının ölçümü; cevap, bir araç açıklamasını cilalamaya bir öğleden sonra harcamış herkes için rahatsız edici. Sonra aynı yaklaşımın hata dizgilerine uygulanması; bu bölümde ölçülen en büyük tekil etki orada çıkıyor — ve çoğu aracın varsayılan olarak döndürdüğü ham istisna, yarısı yazılmış bir hata mesajı olarak ortaya çıkıyor. Sonra bir aracın ne geri vermesi gerektiği; bu, çıktıyla değil ajanın belleğiyle ilgili bir soru. Sonra listelenemeyecek kadar çok araç olduğunda ne yapılacağı. Son olarak da bir aracın iyi olup olmadığını nasıl anlayacağımız; bu soruyu bir modele sormadan cevaplayamazsınız.

24.1.1 Ölçüldü: şemanın hangi kısmı işi yapıyor?

Tek bir aracın, yalnızca nasıl tarif edildiğiyle ayrışan dört sürümü. Görev, bir proje (ör. ZRG-14 kodlu uydurma bir proje) hakkında tek bir sayısal alanı getirmek ve sorular alanı asla birebir adlandırmıyor: ne kadar para ayrıldı sorusu alan="butce" çağrısına dönüşmeli. Dolayısıyla eşlemeyi taşıyabilecek tek şey şema. Hiçbir şey yürütülmüyor; puanlanan şey modelin ürettiği çağrı.

Dördünden ikisi yalnızca dört sözcükle ayrışıyor. İşte ikisinin tam hâli; önce varyant B (adlandırılmış, serbest dizgi):

{"name": "veri_getir",
 "description": "Fetch one field of one project.",
 "input_schema": {"type": "object",
   "properties": {"proje": {"type": "string"},
                  "alan":  {"type": "string"}},
   "required": ["proje", "alan"],
   "additionalProperties": false}}

Sonra varyant C; tek değişiklik enum:

{"name": "veri_getir",
 "description": "Fetch one field of one project.",
 "input_schema": {"type": "object",
   "properties": {"proje": {"type": "string"},
                  "alan":  {"type": "string",
                            "enum": ["butce", "personel", "sure"]}},
   "required": ["proje", "alan"],
   "additionalProperties": false}}

Varyant A her adı f1, a, b ile değiştiriyor ve açıklamayı boşaltıyor; varyant D ise C’ye ek olarak her parametreye açık bir description yazıyor.

qwen3.5:9b, 60 questions, one tool, four descriptions
95% intervals are Wilson on n = 60

 variant         called a tool  project right  field right   95% CI          fully correct
 A. opaque               58.3%           0.0%         0.0%   [ 0.0,   6.0]            0.0%
 B. named               100.0%         100.0%        25.0%   [15.8,  37.2]           25.0%
 C. enum                100.0%         100.0%       100.0%   [94.0, 100.0]          100.0%
 D. described           100.0%         100.0%       100.0%   [94.0, 100.0]          100.0%

Ölçülebilir etkinin tamamı, kabul edilen değerleri listelemekten geldi. Serbest dizgilerden izin verilen değerleri açıkça listeleyen bir enum’a geçmek alan doğruluğunu %25’ten %100’e taşıdı: aynı 60 istekte 15/60’a karşı 60/60. Yani veriler eşleştirilmiş, uygun test de McNemar testi: aynı 60 soru iki koşulda da sorulduğu için yalnızca sonucu değişen sorular sayılır (bkz. Bölüm 4). C varyantı her isteği doğru bildiği için eşleşmenin yönü de belli: 45 istek iyileşti, hiçbiri kötüleşmedi ve kesin McNemar testi \(p = 2 \times 2^{-45} \approx 5{,}7 \times 10^{-14}\) veriyor. Enum’un üstüne eklenen özenli düzyazı açıklamalar gözlenebilir hiçbir şey katmadı — gerçi C zaten 60/60’ta olduğundan artışa yer kalmamıştı. Bu, emeğin çoğunun harcandığı yerin tam tersi: insanlar açıklamayı yazar, parametreyi ise serbest dizgi olarak bırakır. Bölümün ilerisindeki başa baş karşılaştırmalarda gereken ve kendi aracınızda çalıştırmanız gereken test de bu eşleştirilmiş testtir.

Enum’un burada ne yaptığı ve ne yapmadığı. ollama, bir araç tanımındaki enum değerlerini gramerle kısıtlamıyor; dolayısıyla varyant C’nin %100’ü, kod çözücünün mali buyukluk üretmeyi reddetmesinden gelmiyor. Modelin şemada butce, personel, sure değerlerini okuyup kullanmasından geliyor. Bu önemli, çünkü bu bulguyu bölümün ilerisindeki hata mesajı bulgusuyla aynı bulgu hâline getiriyor: ikisini de düzelten şey, API’nin sözcük dağarcığını modelin görebileceği yere koymaktı. Sizin çalışma zamanınız kod çözmeyi gerçekten kısıtlıyorsa — barındırılan API’ler buna şema zorlamalı (schema-enforced) ya da strict kip der (Bölüm 18) — enum bir garanti olur ve bu deney model hakkında hiçbir şey söylemez. Genellemeden önce hangi durumda olduğunuzu söyleyin.

Ve bir hücre eksik — üstelik sonucun ne kadar genellenebileceğini belirleyen hücre. Dört varyant faktöriyel bir tasarım değil, bir merdiven: hiçbir şey → isimler → isimler + enum → isimler + enum + düzyazı. Sınanmayan basamak isimler + düzyazı, enum yok. O basamak olmadan doğru ifade “düzyazı hiçbir şey yapmıyor” değil, “enum sözcük dağarcığınızı modelin önüne zaten koyduktan sonra düzyazı bir şey eklemiyor”. Değerlerini listeleyemeyeceğiniz bir parametre için — serbest metin sorgusu, tarih, kimlik, açık uçlu filtre — elinizdeki tek köprü açıklamadır ve bu deney onun hakkında hiçbir şey söylemiyor. Aşağıdaki 3. kuralı bir ölçüm değil bir sav olarak okuyun.

Tablodaki iki satır ayrıca açıklanmayı hak ediyor, çünkü her biri toplamların gizlediği bir şey öğretiyor.

Opak şema yanlış çağrılar yapmadı. Hiç çağrı yapmadı. a ve b parametrelerini alan f1 adlı aracı model soruların yalnızca %58,3’ünde çağırdı; çağırmadığında ise parametrik bellekten (eğitim sırasında edindiği bilgiden) cevap verdi — ZRG-14’ün sözde ne olduğu hakkında bir paragraf uydurarak. Bu, bozuk bir çağrıdan çok daha kötü bir kusurdur: yanlış bir çağrı hata verir, uydurulmuş bir cevap ise cevaba benzer.

Enum olmadan model, kullanıcının sözcük dağarcığını API’nize yansıtır. İşte B varyantının tüm ifadeleri, her biri için bir satır (satırlar ifade düzeyinde bir özet; soru düzeyindeki oran tablodaki 15/60’tır):

  MISS  wanted butce     got "bütçe"           ← "ne kadar para ayrildi?"
  MISS  wanted butce     got "mali buyukluk"   ← "mali buyuklugu nedir?"
  OK    wanted personel  got "personel"        ← "kac kisi calisiyor?"
  MISS  wanted personel  got "ekip mevcudu"    ← "ekip mevcudu nedir?"
  OK    wanted sure      got "sure"            ← "kac ay suruyor?"
  MISS  wanted sure      got "takvim"          ← "takvimi ne kadar?"

Doğru bildiği iki soru API’nin kelimesini içermiyor: kac kisi calisiyor içinde personel, kac ay suruyor içinde sure geçmiyor. Model burada anlamı — kaç kişi, kaç ay — bir alan adına eşledi ve seçtiği ad API’nin kendi kelimesiydi. Kalan dört durumun üçünde sorudaki kelimeleri olduğu gibi aktardı — mali buyukluk, ekip mevcudu, takvim; dördüncüsünde (ilk satır) ise API’nin kelimesinin Türkçe yazımını, bütçe’yi üretti. Model kötü tahmin etmiyor; API’nizin butce dediğini bilmesinin bir yolu yok, o yüzden kullanıcının dediğini söylüyor.

İlk satıra ayrıca dikkat edin; burada Bölüm 16’nın konusu beklenmedik bir yerde karşımıza çıkıyor: model, API’nin butce beklediği yere bütçe yazdı. Doğru Türkçe, yanlış tanımlayıcı. Parametre değerleri gerçek kelimelerin ASCII’ye katlanmış (diyakritikleri atılıp ç → c, ş → s gibi düz harflere indirgenmiş) hâlleri olan her API’de bu kusur pusuda bekler; burada onu enum ortadan kaldırıyor.

Ama her yerde değil; bu farkı net koymak gerekir. Şemadaki bir enum, modelinizin genellikle uyduğu bir ipucudur; araç sınırında normalleştirme ise sizin kontrol ettiğiniz bir garantidir. İkisini de yapın: NFC (Unicode normalleştirmesi) uygulayın, sonra diyakritikleri açık bir eşleme tablosuyla katlayın (bütçe → butce) — hem de doğrulamadan önce. Katlamayı Python’un .lower()/.casefold() yöntemlerine de bırakmayın: bunlar yerel ayar (locale) parametresi almaz ve Türkçe kurallarını bilmez. "IŞIK".lower(), Türkçedeki ışık yerine işik verir; "İSTANBUL".lower() ise fazladan bir birleştirici nokta işareti kazanır. Türkçe harfleri açık bir eşlemeyle (str.translate) dönüştürün; Türkçe kurallı büyük/küçük harf dönüşümü gerekiyorsa ICU’ya (Python’da PyICU) başvurun. Modelin makul biçimde gönderdiğini kabul edin; API’nizin ihtiyaç duyduğunu saklayın. Tuzakların gerisi Bölüm 16’da; bu ise işlev imzanıza kadar uzanan tuzak.

Şema, iki sözcük dağarcığı arasındaki tek köprüdür
KULLANICI NE SORDU SERBEST DİZGİ → MODEL NE GÖNDERDİ ENUM → MODEL NE GÖNDERDİ "ne kadar para ayrildi?" bütçe butce "mali buyuklugu nedir?" mali buyukluk butce "ekip mevcudu nedir?" ekip mevcudu personel "takvimi ne kadar?" takvim sure 60 SORUNUN TAMAMINDA yalnızca yukarıdaki dördü değil alan doğru, B varyantı %25,0 alan doğru, C varyantı %100,0 ENUM'UN ÜSTÜNE DÜZYAZI GÖZLENEBİLİR HİÇBİR ŞEY EKLEMEDİ D varyantı da %100,0 aldı — C tavana zaten ulaşmıştı

B varyantının yanlış bildiği dört ifade. Her birinde model kullanıcının kendi kelimesini parametreye geçirdi, çünkü şemada hiçbir şey ona API’nin o alana ne dediğini söylemiyordu. İlk satır en keskin durum: bütçe doğru Türkçedir ama yanlış bir tanımlayıcıdır.

Kapsamı açıkça söyleyelim: tek model, tek araç, üç alan. Merdivenin neyi kanıtlayıp neyi kanıtlamadığına da dikkat: API’nin sözcük dağarcığını şemaya koymanın, onu üstüne düzyazıyla anlatmaktan çok daha değerli olduğunu gösteriyor. Kısıtları düzyazıya karşı genel olarak sıralamıyor, çünkü yalnızca düzyazı içeren basamak hiç çalıştırılmadı. Genellenebilecek olan, sözcük dağarcığının modele bir yolla ulaşması gerektiğidir; kesin sayılar değil, deney tasarımının göremediği bir sıralama hiç değil. Daha büyük bir model butce’yi bağlamdan çıkarabilir; on iki alanlı bir şema enum’u daha da önemli kılar, daha az değil. Varyant taramasını kendi araçlarınızda çalıştırın; bir öğleden sonra sürer ve bu bölümün önerebileceği en verimli öğleden sonradır.

Hangi değişiklik neyi kazandırıyor — şema varyantları ve hata biçimleri

24.1.2 Yani şemaları şu sırayla yazın

Ölçüm bir öncelik sırası veriyor; bu sıra, çoğu kişinin izlediğinin kabaca tersi.

  1. Listelenebilen her şeyi enum ile listeleyin. Sabit değer kümesi olan her parametre bir enum olur. Etkisi ölçülen değişiklik budur.
  2. Aracı ne zaman kullanılacağına göre adlandırın, neyi sardığına göre değil. db_query_orders yerine find_orders.
  3. Parametre açıklamasını bir eşleme olarak yazın; kullanıcıların kullandığı kelimelerden API’nizin istediği değere: butce = ayrılan para.
  4. Sonra araç açıklamasını yazın; adın açık bıraktığı durumlar için — aracın ne için olmadığı dâhil; modelin araca yanlışlıkla başvurmasını önleyen kısım budur.
  5. İsteğe bağlı parametreleri nadir tutun. Her isteğe bağlı parametre, modelin hiçbir bilgi olmadan vermesi gereken bir karardır ve belgelemediğiniz bir varsayılan, modelin her seferinde farklı yapacağı bir tahmindir.

24.2 Hata mesajları prompt’tur

Bölüm 23’teki döngüde 6 ile işaretlenen satır bir istisnayı (exception) bir gözleme çeviriyordu. Bu da hata dizgisini prompt metnine dönüştürür: model onu okur ve sonra ne yapacağına karar verir. Ama hata dizgileri çoğu zaman böyle yazılmaz, çünkü hata mesajları kayıtları (log) okuyacak bir insan için yazılır.

İddia sınanabilir. Diğer her şeyi sabit tutun ve yalnızca aracın bozulduğunda ne döndürdüğünü değiştirin. Her koşulun aynı kusurla karşılaşması için ilk araç çağrısı, model ne isterse istesin koşulsuz reddediliyor; puanlanan ikinci çağrı. Dizgiyi sabit tutmanın bir yan etkisi var: butce’yi doğru gönderen bir modele de 'bütçe'’nin geçersiz olduğu söyleniyor. Bu, dört koşulu karşılaştırılabilir tutuyor — amaç da bu — ama her koşuldaki hata, gerçek bir hataya göre modelin gönderdiğiyle biraz daha az örtüşüyor. Değeri alıntılayan stack trace (yığın izi; tablodaki traceback satırı) koşulu bundan en çok etkileniyor.

qwen3.5:9b, 60 tasks, first call always rejected, four error styles
95% intervals are Wilson on n = 60

 error style     retried        right field              gave up
 bare          14/60  23.3%   1/60   1.7% [ 0.3,  8.9]  46/60  76.7% [64.6, 85.6]
 traceback      9/60  15.0%   7/60  11.7% [ 5.8, 22.2]  49/60  81.7% [70.1, 89.4]
 vague         22/60  36.7%   2/60   3.3% [ 0.9, 11.4]  38/60  63.3% [50.7, 74.4]
 actionable    60/60 100.0%  60/60 100.0% [94.0,100.0]   0/60   0.0% [ 0.0,  6.0]

Sütunlar: retried yeniden deneyen, right field doğru alanı bulan, gave up vazgeçen görevler. Ayrı bir valid field (geçerli alan) sütunu gösterilmiyor, çünkü dört koşulda da right field ile aynıydı: model üç geçerli değerden birini üretecek kadar toparlandığında her seferinde doğru olanı üretti. Toparlanma burada ya hep ya hiç.

traceback satırı tutmuyor: 9 yeniden deneme artı 49 vazgeçme 60 değil 58 ediyor. O koşulun iki görevi kayıp; yani üç sayısından biri en fazla iki görev kadar hatalı. Bu, sessizce düzeltilmek yerine burada işaretleniyor; aşağıda o satıra dayanan her karşılaştırmayı bu belirsizlikle birlikte okuyun.

Dört dizgi şunlardı:

 bare        "Error"

 traceback   Traceback (most recent call last):
               File "server.py", line 118, in veri_getir
                 return RECORDS[proje][alan]
             KeyError: 'bütçe'

 vague       "HATA: gecersiz alan adi."

 actionable  "HATA: 'bütçe' gecerli bir alan degil.
              Gecerli alanlar sunlardir: butce, personel, sure."

O %100’ün kapsamını belirtelim: buradaki geçerli küme üç elemanlı; dolayısıyla actionable hata (modele nasıl toparlanacağını söyleyen hata) kümenin tamamını listeleyebiliyor ve model bunu okuduktan sonra bu kadar yüksek bir tavan neredeyse garanti. Ölçülen şey, bir toparlanma talimatının varlığı; onun nasıl ölçeklendiği değil. İlginç olan sınanmamış durum, yalnızca en yakın birkaçını sunabileceğiniz iki yüz elemanlı bir küme — aynı sıçramayı varsaymadan önce onu kendi aracınızda ölçün.

Tek bir cümle toparlanmayı %1,7’den %100’e taşıdı. Sistem prompt’u ve model değişmedi; tek fark, aracın hata durumunda döndürdüğü metindi. Bu, bu alt bölümün tezine bir istisna değil, tezin ta kendisi: aracın döndürdüğü o dizgi, prompt yazarının değil araç yazarının yazdığı bir prompt’tur.

O tablodaki üç şey ayrıca önemli.

Stack trace dördün en kötüsü değil, en ilginci. Ayrıca kimse özel bir hata mesajı yazmadıysa araçlarınızın bugün döndürdüğü şeye en yakın olan da bu: ham bir istisna. (Bölüm 23’teki döngü ERROR: {e} döndürür; bu hatada bu yalnızca ERROR: 'bütçe' olur — stack trace’in son satırı, aynı eksik yarıyla.) Yeniden denemeyi en seyrek o üretti — çıplak bir "Error"’ın %23,3’üne karşı %15,0 — ama ürettiği denemeler çoğunlukla işe yarayanlardı: 9 denemesinin 7’si doğru alanı buldu; çıplak hatanın 14 denemesinin 1’i, belirsiz olanın 22 denemesinin 2’si. Bu oranları betimleyici olarak okuyun: hangi isteklerin yeniden denendiği hata mesajına bağlıydı. Dolayısıyla yeniden deneyen üç altküme kendi kendini seçmiş gruplar; eşit zorlukta olmaları gerekmiyor ve koşullu oranlar üzerinde yapılacak her test bu sorunu devralır. Sağlam kalan karşılaştırma, 60 isteğin tamamı üzerinde yapılan eşleştirilmiş karşılaştırmadır. Bir stack trace neyin başarısız olduğunu söyler — KeyError: 'bütçe' sorunlu değeri adlandırır — ama neyin işe yarayacağı hakkında hiçbir şey söylemez; yani yarısı yazılmış bir hata mesajıdır. Buradaki örüntü bu okumayla uyumlu: modeli daha seyrek harekete geçirmiş, geçirdiğinde yol göstermiş görünüyor. Ama bunu bir bulgu değil bir hipotez olarak okuyun.

Çünkü 60 isteğin tamamı üzerindeki karşılaştırma bu hipotezi doğrulamıyor. Yeniden deneme ve vazgeçme aynı madalyonun iki yüzü (bir görev ya yeniden denenir ya bırakılır), dolayısıyla “en az yeniden deneme” ile “en çok vazgeçme” aynı karşılaştırmadır (traceback satırındaki iki eksik görev dışında). Çıplak "Error"’a karşı fark yeniden denemede 14’e karşı 9, vazgeçmede 46’ya karşı 49 görev; vazgeçme aralıkları [64,6; 85,6] ve [70,1; 89,4]. Aynı 60 istekte doğru test eşleştirilmiş testtir ve en elverişli eşleşmede bile — değişen isteklerin hepsi aynı yöndeyse — kesin McNemar yeniden denemede \(p \approx 0{,}06\), vazgeçmede \(p = 0{,}25\) verir. Doğru alandaki 7’ye karşı 1 fark da sınırda: eşleşmeye bağlı olarak \(p\) 0,03 ile 0,07 arasında. Yani bu veride stack trace çıplak "Error"’dan güvenilir biçimde ayırt edilemiyor; hiçbir şeyden kötü olduğu söylenemez. Dört satırın kesin biçimde ayırdığı şey, actionable hata dizgisinin diğer üçünden farkı.

Bu sonuç Huang vd. (2024) ile uyumlu ve onu tamamlıyor. Huang vd., modellerin kendi akıl yürütmelerini içsel geri bildirimle (dışarıdan yeni bilgi gelmeden) güvenilir biçimde düzeltemediğini buldu — “tekrar dene” demek işe yaramıyor. Bu deneyin eklediği, sınırın nerede olduğu: aynı model, hiçbir içerik taşımayan geri bildirimden sonra vakaların %1,7’sinde, cevap kümesini adlandıran geri bildirimden sonra ise %100’ünde toparlanıyor. Belirleyici olan, modelin kendini düzeltme kapasitesi değil; geri bildirimin bilgi içerip içermediği.

Baskın kusur döngüye girmek değil vazgeçmektir. Dört biçimden üçü vakaların çoğunda vazgeçmeyle sonuçlandı: model araç çağırmayı bıraktı ve veriyi almadan cevap verdi. Bu, en azından kendini transkriptte belli eden bir yeniden deneme döngüsünden daha kötüdür. Bölüm 23 bunun tersi olan kusuru, durmak bilmeyen bir ajanı bulmuştu; burada aynı mimari devam etmiyor ve belirleyici etken tek bir cümle.

“Geçersiz” demek, hiç yoktan pek farklı değildir. vague (belirsiz) biçim sorunu sözcüklerle adlandırıyor, yine de model vakaların yalnızca %3,3’ünde toparlandı (çıplak hatada %1,7; bu fark ayırt edilemeyecek kadar küçük). İşe yarayan, bir şeyin yanlış olduğunu söylemek değil; neyin doğru olacağını söylemektir.

24.2.1 Buradan çıkan kural

Bir modelin kullanabileceği bir hata mesajının üç parçası vardır ve önemli olan sonuncusudur:

  1. ne bozuldu        'bütçe' geçerli bir alan değil
  2. neden             (isteğe bağlı; çoğu zaman gereksiz)
  3. ne işe yarardı    geçerli alanlar: butce, personel, sure

Üçüncü kısmı yazın, gerisi isteğe bağlı. Onu atlarsanız bir hata mesajı değil, bir log satırı yazmış olursunuz.

Araçlarınıza baştan yerleştirmeniz gereken iki sonuç:

  • Geçerli seçenekleri hatada listeleyin, bir enum’da yapacağınız gibi. Küme listelenemeyecek kadar büyükse en yakın birkaçını listeleyin — butce'yi mi kastettiniz? eksiksiz bir toparlanma talimatıdır.
  • Asla ham bir istisna döndürmeyin. Yakalayın ve çevirin. Çeviri tek satırlık bir işlevdir ve eldeki kanıta göre bu bölümde ölçülen en büyük tekil iyileşmeyi sağladı.

Bu bölümün iki önerisini — araç sınırında normalleştirme ve istisnayı çevirme — birleştiren küçük bir sarmalayıcı şöyle görünür (RECORDS deneydeki gibi uydurma bir kayıt tablosu):

import unicodedata

RECORDS = {"ZRG-14": {"butce": 1_200_000, "personel": 14, "sure": 18}}
ALANLAR = ("butce", "personel", "sure")
KATLA = str.maketrans("çğıöşüÇĞİÖŞÜ", "cgiosuCGIOSU")

def alan_normallestir(deger: str) -> str:
    # önce NFC, sonra Türkçe harfleri açık tabloyla katla; .lower() en sonda
    return unicodedata.normalize("NFC", deger).strip().translate(KATLA).lower()

def veri_getir(proje: str, alan: str) -> str:
    try:
        return str(RECORDS[proje][alan_normallestir(alan)])
    except KeyError:               # ham istisnayı modele göndermeyin; çevirin
        if proje not in RECORDS:
            return (f"HATA: '{proje}' adlı bir proje yok. "
                    f"Mevcut projeler: {', '.join(RECORDS)}.")
        return (f"HATA: '{alan}' geçerli bir alan değil. "
                f"Geçerli alanlar şunlardır: {', '.join(ALANLAR)}.")

Burada veri_getir("ZRG-14", "bütçe") hata değil 1200000 döndürür; veri_getir("ZRG-14", "takvim") ise deneydeki actionable dizginin karşılığını.

24.3 Bir aracın döndürdüğü şey tasarımının parçasıdır

Bir aracın dönüş değeri doğrudan transkripte gider ve Bölüm 23’ün ortaya koyduğu gibi transkript ajanın durumunun kendisidir. Yani bir dönüş değeri çıktı değildir — sonraki her adımın okuyacağı ve bedelini ödeyeceği paylaşılan belleğe yapılan bir yazma işlemidir.

Buradan üç kural çıkıyor; öncelikle insanlar düşünülerek yazılmış araçlar üçünü de düzenli olarak çiğniyor.

50.000 token döndüren bir araç, bağlam bütçesinin büyük bir kısmını tek bir çağrıda harcamıştır. Bunun ajanı bozup bozmadığı bütçeye ve göreve bağlı — 50.000 token küçük bir bağlam penceresinin çoğu, milyon token’lık bir pencerenin ise %5’idir ve sonraki her çağrıda yeniden gönderilir — ama bedel iki durumda da aynı türdendir: sonraki adımların ihtiyaç duyacağı bağlam alanı harcanır, önceki gözlemler modelin onları daha az iyi kullandığı ortaya doğru itilir (Bölüm 25 bunu ölçüyor) ve kalan her model çağrısı daha pahalıya gelir. Görevin ihtiyaç duyduğunu döndürün: bütün kaydı değil üç alanı; bütün tabloyu değil eşleşen satırları.

Sayfalayın ve bunu sonuçta söyleyin. "247 eşleşmenin 10'u gösteriliyor; devamı için offset=10 ile yeniden çağırın", modelin harekete geçebileceği somut bir cümledir. Sonucu sessizce on satıra kırpan bir araç ise yalan söyler ve modelin bunu anlamasının hiçbir yolu yoktur.

Ham biçim kullanılamaz olduğunda araç tarafında özetleyin. 40 sayfalık bir PDF’i saran bir araç 40 sayfa döndürmemeli. Aracın ne döndüreceği, ajanın ne işe yaradığına dair bir tasarım kararıdır; bu kararı aracın içinde vermek, onu aracı kullanan her prompt’a ayrı ayrı yazma zorunluluğunu ortadan kaldırır.

Bir aracın asla döndürmemesi gereken şeyler de var. Bir aracın döndürdüğü her şeyi model okur ve çoğu üründe bu metin kullanıcının önüne de çıkabilir. Dolayısıyla bir araç sırları — API anahtarlarını, parolaları, erişim token’larını, iç bağlantı dizgilerini — asla döndürmez; o anki kullanıcının görmeye yetkili olmadığı kayıtları da döndürmez. Yetki filtrelemesini metin transkripte ulaşmadan aracın içinde yapın, çünkü okuduğu bir sırrı modelin saklayacağına güvenilemez. Ters yön de önemli: bir aracın dışarıdan getirdiği metin — bir web sayfası, bir e-posta, bir destek talebi (ticket) — talimat değil veridir ve model bu ikisini güvenilir biçimde ayırt edemez. Bölüm 36 bunu dolaylı prompt enjeksiyonu olarak ele alıyor; araç yazarına düşen, getirilen metnin nerede başlayıp bittiğini işaretlemek ve onu asla sistemin kendi sözü gibi sunmamaktır.

24.3.1 Eylemler, aramalardan farklı semantik ister

Yukarıdakilerin hepsi okumakla ilgili. Eylem yapan araçların üç özelliğe ihtiyacı var ve bunları eklemenin en ucuz zamanı ilk olaydan öncedir. Bu özellikler asıl olarak yan etkisi olan araçlar için önemlidir; tablodan sonraki iki istisna, bir aracın “salt okunur” olmasının onları atlamak için neden her zaman yetmediğini gösteriyor.

Yazma işlemi yapan bir aracın ihtiyaç duyduğu üç özellik
özellik bir ajanın buna neden özellikle ihtiyacı var
Idempotent (aynı istek tekrarlandığında ek etki oluşturmayan) aynı çağrı iki kez gelecektir. Eylem aslında başarıyla tamamlandıktan sonra dolan bir zaman aşımı, adım sınırına takıldıktan sonra yeniden başlatılan bir çalıştırma ya da sonucu görmemiş bir model ikinci bir çağrı üretir. “Faturayı oluştur” isteği iki kez gelirse ikinci bir fatura oluşmamalı
Dry run kipi (değişikliği uygulamadan etkisini gösteren deneme) değişiklik uygulanmadan önce etkisini ajana ya da size gösterir. Arayüzde doğrudan yer alan (birinci sınıf) bir dry_run: true parametresi, ne kadar prompt talimatı yazarsanız yazın ondan daha değerlidir
Onay kapılı (insan onayı gerektiren) bazı eylemler yalnızca modelin sözüyle hiç yürütülmemeli. O kapı prompt’ta değil çalışma zamanında durur — konu Bölüm 37’de başlı başına bir bölüm olur

İlk satırdaki özelliğin bilinmesi gereken bir adı var: idempotency. Bir çağrıyı iki kez yapmak bir kez yapmakla aynı etkiyi doğuruyorsa çağrı idempotent’tir. Okumalar doğası gereği idempotent’tir; “durumu ödendi yap” da öyledir; “bakiyeye 100 TL ekle” değildir. Yazma işlemi yapan bir çağrıyı idempotent kılmanın standart yolu bir idempotency anahtarıdır: çalışma zamanı her planlanan eyleme benzersiz bir kimlik iliştirir, araç da hangi kimlikleri zaten yürüttüğünü hatırlar; böylece tekrarlanan bir çağrı eylemi yeniden yapmak yerine ilk sonucu döndürür.

idempotency — etkisini tekrarlamadan yinelenebilen bir çağrı; yeniden denenen bir ajan adımını güvenli kılan şey. Etkisiz demek değildir: çağrının etkisi bir kez gerçekleşir, tekrarı yeni etki eklemez. ↩︎

Salt okunur bir araç genellikle üçünü de atlayabilir; iki istisnayla: çağrı başına gerçek para harcayan bir okuma yine de bir dry run ister ve kullanıcının yetkili olmayabileceği veri üzerindeki bir okuma yine bir kapı ister. “Salt okunur” hasarı sınırlar; çağrıyı her zaman bedava ya da zararsız yapmaz.

Genel ilke Bölüm 23’te gördüğümüz ilkedir; araç yazarı için yeniden söylersek: model argümanları üretir, kararı çalışma zamanı verir. İncelenmemiş bir pull request’in otomatik yapmasına izin vermeyeceğiniz hiçbir şeyi bir araç çağrısının otomatik yapmasına izin vermeyin.

24.4 Elli aracın ötesine ölçeklenmek

Önceki alt bölüm, bir aracın çağrıldığında bağlama ne koyduğuyla ilgiliydi. Bu alt bölüm ise araçların, herhangi biri çağrılmadan önce neye mal olduğuyla ilgili.

Her araç tanımı her çağrının bağlamında durur, dolayısıyla elli araçlık düz bir liste, herhangi biri ilgili olsun olmasın her adımda ödenen büyük ve sabit bir vergidir. Yayımlanmış rakamlar çoğu kişinin beklediğinden büyük: Anthropic (2025), 50’yi aşkın araçtan oluşan ve tek bir çağrıdan önce yalnızca tanımları yaklaşık 72.000 token — başlangıç bağlamının geri kalanıyla birlikte yaklaşık 77.000 — tutan bir katalog raporluyor; tanımları talep üzerine yüklemek bunu %85 azaltıyor. Araçlarınız kendi kod tabanınızdan değil bir protokol üzerinden geldiğinde aynı verginin neye benzediğini Bölüm 27 ölçüyor.

Düz liste büyüdükçe doğruluk da düşer — birbirine benzeyen seçenek arttıkça yanlışlıkla komşusunu seçme şansı da artar — ve aynı rapor buna da sayı koyuyor: geniş bir yüzeyde araç seçme doğruluğu, kataloğu bağlama yapıştırmak yerine içinde arama yaparak bir modelde %49’dan %74’e, daha güçlü bir modelde %79,5’ten %88,1’e çıkıyor. Ucuz çözümle doğruluğu artıran çözümün aynı çözüm olduğu ender durumlardan biri.

Mimarinizi ne kadar değiştirdiklerine göre artan sırada üç çıkış yolu:

  • Ad alanlarına (namespace) ayırın ve budayın. Geniş araç yüzeyleri çoğu zaman tarihsel nedenlerle aynı şeyi yapan iki üç araç içerir. Onları birleştirmek bedavaya doğruluk kazandırır. Aynı içgüdü aracın ayrıntı düzeyini de belirler: API’nizin her uç noktası için değil, kullanıcının her görevi için bir araç kurun — modelin kendi başına doğru sırayla zincirlemesi gereken list_users, list_events ve create_event yerine tek bir schedule_meeting.
  • Ara, sonra yükle — kademeli açılım. Tek bir find_tools(query) aracı sunun ve o adım için yalnızca eşleşen tanımları yükleyin. Bu, Bölüm 19’un kendi API yüzeyinize uygulanmış hâlidir ve Anthropic’in (2025) birinci sınıf bir API özelliği olarak sunduğu şeydir. Bu yola ne zaman başvurulacağı sabit bir sayı değil. Anthropic’in belgeleri, model yaklaşık 30–50’den fazla araç gördüğünde seçim doğruluğunun düştüğünü söylüyor ve aramayı araç sayısı 10’a ya da tanımlar 10.000 token’a ulaştığında bile öneriyor; ayrıntılı tanımlar bu eşiğe daha erken ulaşır. Bir sayı seçmeden önce kendi tanım verginizi ölçün.
  • Bunun yerine ona bir yorumlayıcı verin. Araçlarınız çoğunlukla küçük dönüşümlerse, bir sandbox (kum havuzu: kodun erişimini ve etkilerini sınırlayan yalıtılmış çalıştırma ortamı) içinde çalışan tek bir kod aracı elli tanımın yerini alır — model bir menüden seçmek yerine ihtiyacı olanı küçük işlemleri birleştirerek kurar.

Kademeli açılım (progressive disclosure) — hepsi yerine yalnızca mevcut adımla ilgili araç tanımlarını yüklemek; böylece geniş bir yüzey her çağrıyı vergilendirmez. ↩︎

24.4.1 Kod kipi ve bedeli

Üçüncü seçenek — kod kipi — net biçimde adlandırılmayı hak ediyor, çünkü sağlayıcılar artık onu sunuyor: Cloudflare’in Code Mode’u (Cloudflare 2025) ve Anthropic’in programatik araç çağırma özelliği (Anthropic 2025), modelin araçları her biri için ayrı bir gidiş-dönüşle tek tek çağırmak yerine, onları çağıran kodu yazmasına izin veriyor.

Burada iki biçimi ayırmak gerekir. İlkinde araçlar yerinde kalır, yalnızca sandbox içinde tipli bir kod API’si olarak sunulur; bu iki ürünün yaptığı budur ve sandbox’ın erişebildiği bağlamalar (bindings) hâlâ bir izin listesidir. İkincisinde araçların yerini genel bir yorumlayıcı alır; izin listesi asıl bu uçta kaybolur.

Kod kipi (code mode) — modelin araçları tek tek çağırmak yerine, sandbox içinde çalışan ve onları çağıran kodu yazması; en uç biçiminde araç listesinin yerini genel bir yorumlayıcı alır. İşlemleri birleştirme, döngüler ve ara değişkenler bedavaya gelir; karşılığında okunabilir bir izin listesinin bir kısmından ya da tamamından vazgeçilir. ↩︎

İkinci uçta filter_rows, sum_column ve join_tables yerine modele bir sandbox sunar ve bu işlemleri birleştiren kodu ona yazdırırsınız. Bu yaklaşımın ifade gücü gerçekten daha yüksektir: küçük işlemleri birleştirme (composition), döngüler ve ara değişkenler bedavaya gelir; bunlar da sabit bir araç listesinin zorlaştırdığı şeylerdir.

Bu ucun bedeli, bir izin listesinin yerine bir yorumlayıcı koymuş olmanızdır. Bir araç listesi okuyabildiğiniz bir güvenlik sınırıdır; bir sandbox ise kurmanız ve güvenmeye devam edebilmeniz gereken bir güvenlik sınırıdır. Bu gerçek bir ödünleşimdir (trade-off) ve buradaki bir paragrafa değil Bölüm 36’ya aittir — ama tasarım kararı bu bölümde, modele hangi yüzeyi sunacağınızı seçtiğiniz anda verilir.

24.5 Bir aracı değerlendirmek

Bir araç çalışıyor diye doğru değildir. İki ayrı açıdan doğru olması gerekir: model onu doğru çağırmalı (bu, model–araç çiftinin bir özelliğidir ve ancak modele sorarak ölçülebilir) ve araç doğru çağrıldığında doğru şeyi yapmalı: doğru sonucu döndürmeli ve kimsenin istemediği bir yan etki üretmemeli. Bu alt bölüm birincisini ele alıyor, çünkü araç yazarlarının atladığı odur; ama bu, her işlev için yazacağınız sıradan testlerin yerini tutmaz.

Değerlendirme bir öğleden sonrada kurulacak kadar küçüktür ve bu bölümün iki deneyiyle aynı biçimdedir:

  1. Bu araca ulaşması gereken yirmi gerçek istek toplayın; API’nizdeki adlarıyla değil, kullanıcıların ifade ettiği gibi. Yanlış kullanım burada gizlenir.
  2. Sonucu değil çağrıyı puanlayın. Doğru araç seçildi mi; argümanlar doğru mu? Çağrıyı yürütürseniz şema sorunu, sonraki aşamalardaki her şeyle karışır — yukarıdaki şema deneyi bilerek hiçbir şey yürütmedi.
  3. Üç kusur türünü ayrı sayın, çünkü her birinin düzeltmesi farklıdır:
Üç kusur türü, üç farklı düzeltme
kusur ne demek ne düzeltir
Çağrılmadı model araçsız cevapladı ya da komşusunu seçti ad ve açıklamanın “şu durumda kullan” kısmı
Yanlış çağrıldı doğru araç, yanlış argümanlar tipler ve enum’lar, sonra parametre açıklamaları
Toparlanamadı modelin nasıl düzelteceğini çıkaramadığı başarısız bir çağrı hata dizgisi
  1. Yirmi isteği regresyon kümenize ekleyin. Bir araç açıklaması prompt metnidir, dolayısıyla onu değiştirmek sistem davranışında bir değişikliktir ve bir prompt’u değiştirmekle aynı özeni hak eder — bir farkın anlamlı sayılması için kaç örneğe ihtiyaç olduğunu Bölüm 22 hesaplamıştı.

Üretimde izlenmeye en çok değer olan satır “Çağrılmadı” satırıdır, çünkü başka türlü görünmez. Hiç seçilmeyen bir araç ne hata ne log kaydı üretir; yalnızca sessizce devre dışı kalır, model de bellekten cevap verir. Opak şemanın vakaların %41,7’sinde, cevaba benzeyen bir düzyazıyla yaptığı da buydu.

24.6 Sezgi kontrolleri

Her birini açmadan önce cevaplayın. Dördü bu bölümün tartışmayla değil ölçümle çözdüğü sorular; diğer ikisi savunduğu ve ölçemediği tasarım kararları.

Düzyazıdan önce enum’lara. Burada ölçüldü: bir parametreyi serbest dizgiden enum’a taşımak doğru çağrıları %25’ten %100’e çıkardı ve üstüne özenli açıklamalar eklemek gözlenebilir bir katkı sağlamadı. Nedeni konusunda kesin olun: buradaki çalışma zamanı enum’u zorlamadı, yani değerleri listelemek modelin izlediği sözcük dağarcığını sağladı ve deney enum’suz düzyazıyı hiç sınamadı. Enum’u zorlayan bir kod çözücü yalnızca değerin küme içinde olmasını garanti eder — doğru değer olmasını değil.

Genellikle yanlış bir çağrı değil — hiç çağrı olmaması. Opak bir şemayla model burada aracı soruların yalnızca %58,3’ünde çağırdı, diğerlerinde parametrik bellekten cevap verdi; bilemeyeceği bir şey hakkında kendinden emin bir paragraf üreterek. Yanlış bir çağrı görebileceğiniz bir hata verir; kullanılmayan bir araç ise makul görünen bir cevap üretir ve hiçbir sinyal vermez.

Çünkü ona aksini söyleyen bir şey yok, o yüzden kullanıcının sözcük dağarcığını parametrenize yansıtıyor. Bu bölümün ölçümünde yalnızca iki ifade işe yaradı ve ikisi de API’nin kelimesini içermiyor. Model onların anlamını bir alan adına eşledi ve API’nin kendi kelimesine ulaştı. Bir durum özellikle dikkat çekici: model, API’nin butce beklediği yere bütçe yazdı — doğru Türkçe, yanlış tanımlayıcı ve değerleri ASCII’ye katlanmış kelimeler olan her API’nin içinde bekleyen bir kusur.

Neyin işe yarayacağını. Dört biçim üzerinden ölçüldü: toparlanma, yalnızca geçersiz değeri adlandırıp geçerlileri listeleyerek %1,7’den %100’e çıktı. Stack trace ise başarısız olan değeri adlandırıyor ama neyin işe yarayacağını hiç söylemiyor: yarısı yazılmış bir hata mesajı. Bu veride çıplak bir "Error"’dan ayırt edilemedi (yeniden deneme ve vazgeçme farkları istatistiksel bir testten geçmiyor); hiçbir şeyden kötü değil, yalnızca eksik. Yakalayın ve eksik cümleyi ekleyin.

Evet ve o adım için değil bütün çalıştırma için bir problem. Dönüş değeri transkripte gider; Bölüm 23’ün gösterdiği gibi transkript ajanın durumunun kendisidir, dolayısıyla sonraki her model çağrısında yeniden gönderilir ve sonraki adımların ihtiyaç duyduğu şeyi dışarı iter. Görevin ihtiyaç duyduğu alanları döndürün, sayfalamayı sonuçta belirterek sayfalayın ve ham biçim kullanılamaz olduğunda araç tarafında özetleyin.

Araçlar çoğunlukla kullanıcıların bir araya getirmek istediği küçük dönüşümlerse — süz, sonra topla, sonra tabloları birleştir — çünkü bu tür bir birleştirme sabit bir listenin zorlaştırdığı ve kodun bedava kıldığı şeydir. Bedeli açıkça söyleyin: okuyabildiğiniz bir izin listesinin yerine, kurmanız ve güvenmeye devam edebilmeniz gereken bir sandbox koydunuz. Bu, bu bölümde verilen ve bedeli Bölüm 36’da ödenen bir güvenlik kararıdır.

24.7 Mülakat soruları

Kaynak konusunda — Bölüm 2’deki çekincenin aynısı. Bu sorular, kitabın kullandığı iki güvenilir açık kaynakta (Chip Huyen’in Introduction to Machine Learning Interviews kitabı ve Machine Learning Interviews deposu) tekrar tekrar karşımıza çıkıyor; bunlara bu bölümün ölçümleriyle cevaplanabilen sorular eklendi.

24.7.1 Mekanizmayı anlayıp anlamadığınızı sınayanlar

S: İyi bir araç şemasını iyi yapan nedir?

Diğer her şeyi belirleyen çerçeveden başlayın: şema dokümantasyon değil prompt metnidir, çünkü model ondan tek bir şans alır ve kontrol edemez. Sonra işi etkiye göre sıralayın. Önce enum’lar — burada ölçüldü, tek bir parametrenin değerlerini enum ile listelemek doğru çağrıları %25’ten %100’e çıkardı; üstüne eklenen düzyazı açıklamalar ise hiçbir şey katmadı. Sonra aracın ne zaman geçerli olduğunu söyleyen bir ad. Sonra kullanıcıların kelimelerinden API’nizin kelimelerine bir eşleme olarak yazılmış parametre açıklamaları, çünkü aksi hâlde model kullanıcının sözcük dağarcığını doğrudan geçirir.

S: Ajanınız soruyu cevaplayacak bir aracı yok sayıyor. Neden?

Büyük olasılıkla ad ve açıklama aracın ne zaman kullanılacağını söylemiyor, dolayısıyla model içinde bulunduğu durumu bu aracın kullanım durumu olarak tanımıyor. Cevabın önemli yarısı o kusurun neye benzediğidir: bir hata değil, parametrik bellekten bir cevap. Bu bölümün ölçümünde opak şemalı araç vakaların %41,7’sinde çağrılmadı ve model bunun yerine kendinden emin, uydurulmuş bir düzyazı üretti. Yani yalnızca kusurları değil seçimi de ölçün.

S: Bir araç hata durumunda ne döndürmeli?

Neyin işe yarayacağını söyleyen bir cümle, geçerli seçenekler tek tek listelenmiş olarak. Dört biçim üzerinden ölçüldü; yalnızca geçersiz değeri adlandırıp geçerlileri listelemek toparlanmayı %1,7’den %100’e taşıdı. Ham bir stack trace ise başarısız olan değeri adlandırır ama neyin işe yarayacağını söylemez; yarısı yazılmış bir hata mesajıdır ve bu ölçümde çıplak bir "Error"’dan ayırt edilemedi. İstisnayı yakalayın ve eksik cümleyi ekleyin.

24.7.2 Gerçekten araç yayına alıp almadığınızı sınayanlar

S: Bir aracı nasıl değerlendirirsiniz?

Modelin onu doğru çağırıp çağırmadığına bakarak; bu, model–araç çiftinin bir özelliğidir. Kullanıcıların ifadesiyle yirmi istek toplayın. Sonucu değil üretilen çağrıyı puanlayın; böylece bir şema sorunu sonraki aşamalardaki her şeyle karışmaz. Kusurları çağrılmadı / yanlış çağrıldı / toparlanamadı sınıflarına ayırın, çünkü bunların üç farklı düzeltmesi var. Sonra yirmiyi regresyon kümesinde tutun, çünkü bir açıklama değişikliği bir davranış değişikliğidir. Bunun neyi kapsamadığını da söyleyin: ölçtüğü şey model–araç arayüzü; aracın kendi uygulaması ve yan etkileri, diğer her işlev gibi ayrıca sınanmalı.

S: Seksen aracınız var ve doğruluk düşüyor. Ne yaparsınız?

Önce birleştirin ve budayın, çünkü geniş yüzeyler birbirine çok benzeyen araçlar biriktirir ve her fazladan komşu, yanlış aracı seçmek için bir şans daha demektir. Sonra düz bir listeden ara-sonra-yükle’ye geçin, böylece bağlamı yalnızca ilgili tanımlar işgal eder — Bölüm 19’un kendi API’nize uygulanmış hâli. Araçlar çoğunlukla küçük ve birleştirilebilir dönüşümlerse onları sandbox içinde çalışan bir yorumlayıcıyla değiştirmeyi düşünün ve okunabilir bir izin listesini, artık sürdürmeniz gereken bir güvenlik sınırıyla değiş tokuş ettiğinizi açıkça söyleyin.

24.8 2026 alet çantası

Bu bölümdeki her şey aşağıdaki sürümlerle yerel olarak çalıştırıldı; şema deneyi hiçbir şey yürütmedi, yalnızca çağrıları puanladı.

Bu sayıların elde edildiği yazılım yığını
kütüphane kullanılan sürüm burada ne işe yarıyor
ollama 0.24.0 qwen3.5:9b’yi araç çağırma desteğiyle sunmak
numpy 2.5.2 görev üretimi ve puanlama

Yukarıda kullanılmayan ama bilmeye değer kütüphaneler:

Daha geniş ekosistem, yazıldığı andaki sürümler
kütüphane güncel sürüm ne zaman kullanılır
pydantic-ai 2.35.3 doğrulama hatasının zaten iyi bir hata mesajı olduğu tipli araçlar
outlines 1.3.3 şemaya uyulmasını ummak yerine onu kod çözme anında zorlamak
jsonschema 4.26.0 yürütmeden önce argümanları doğrulamak; çalışma zamanı sınırının durduğu yer
openai-agents 0.22.0 korkulukları (guardrail) iliştirilmiş araç tanımları
smolagents 1.26.0 aynı görevde bir araç listesini kod kipiyle karşılaştırmak
mcp 2.1.1 araçları standart bir protokol üzerinden sunmak — Bölüm 27

24.9 Lab: bir aracı ölçerek düzeltin

Altı adım, bir öğleden sonra. Adımlar, her seferinde tek bir şeyi değiştirmeniz için sıralandı; böylece sonunda hangi değişikliğin neyi kazandırdığını söyleyebilirsiniz.

24.9.1 Adım 1 — modelin yanlış kullandığı bir araç seçin

Hangisi olduğunu bilmiyorsanız ilk görevi bulmuşsunuzdur: bir gün boyunca araç çağrılarını argümanlarıyla kaydedin.

24.9.2 Adım 2 — kullanıcıların kelimeleriyle yirmi istek yazın

API’nizin kelimeleriyle değil. İkisi arasındaki boşluk ölçülen şeydir.

24.9.3 Adım 3 — hiçbir şey yürütmeden çağrıyı puanlayın

Doğru araç, doğru argümanlar, ikisi ya da hiçbiri. Baseline’ı (taban ölçümü) kaydedin.

24.9.4 Adım 4 — tek bir şeyi değiştirin: enum ekleyin

Sabit değer kümesi olan her parametreye. Yeniden ölçün. Bu bölümün aracında o tek değişiklik 75 yüzde puanlık fark yarattı (%25’ten %100’e).

24.9.5 Adım 5 — şimdi açıklamaları yeniden yazın

Yeniden ölçün. Farkı olduğu gibi raporlayın; buradaki gibi sıfırsa bile.

24.9.6 Adım 6 — bilerek bozun ve hata dizgisini düzeltin

Başarısız olan bir çağrı zorlayın. Önce çıplak hatayı, sonra actionable olanı deneyin. Modelin ne sıklıkla toparlandığını sayın.

24.9.7 Neyi teslim edeceksiniz

Kendinize ait dört satırlık tabloyu — baseline, enum’lar, açıklamalar, hata dizgisi — ve hangi değişikliğin en büyük etkiyi yapacağını önceden tahmin ettiğinizi ve tahmininizin tutup tutmadığını söyleyen bir cümleyi.

24.10 Alıştırmalar

  1. Enum taraması. Değerleri sabit bir kümeden gelen ama serbest dizgi olarak tanımlanmış bir parametresi olan bir araç seçin. Doğru çağrıları ölçün, enum’u ekleyin, yeniden ölçün. İki sayıyı da raporlayın.
  2. Sizin değil kullanıcıların kelimeleri. Araçlarınızdan biri için, kullanıcılarınızın gerçekten kullandığı sözcük dağarcığıyla yirmi istek yazın. Kaçının doğru argümanlar ürettiğini sayın. Aradaki açığı kapatmak parametre açıklamalarınızın işidir.
  3. En kötü hatayı yeniden yazın. Araçlarınızdan birinin döndürebileceği en çirkin hata dizgisini bulun. Üç parçalı biçimde yeniden yazın. Toparlanmayı öncesi ve sonrasıyla ölçün.
  4. Sessiz aracı bulun. Hangi araçların hiç seçilmediğini ölçün. Her biri için gereksiz mi, yoksa kötü mü adlandırılmış olduğuna karar verin — ikisi de düzeltilebilir ve ikisi de ölçüm olmadan görünmez.
  5. Bir dönüş değerini bütçeleyin. Bütün bir kaydı döndüren bir araç alın ve on adımlık bir çalıştırmada neye mal olduğunu hesaplayın. Sonra bunun yerine ne döndürmesi gerektiğine karar verin.
  6. Dry run. Bir şey yazan bir araca dry_run parametresi ekleyin. Dikkatli olması istendiğinde ajanın onu kullanıp kullanmadığını ve parametre varken böyle bir talimata gerek kalıp kalmadığını ölçün.
  7. ASCII tuzağı. API’niz diyakritik işaret kullanan bir dildeki kelimelerden türetilmiş ASCII’ye katlanmış tanımlayıcılar kullanıyorsa, bütçe/butce karışıklığını bir kullanıcıdan önce yakalayan testi yazın.

24.11 Daha derine

Herhangi bir şey okumadan önce şunu yapın: bir araç alın, sabit değer kümesi olan her parametreye enum ekleyin ve değişimi ölçün. Tam varyant taraması bir öğleden sonra sürer; bu tek adım yirmi dakika.

Makalelerin ötesi
kaynak ne olduğu
Writing tools for agents — Anthropic bu bölümün konusu için bir şartnameye en yakın metin; araçların yanlış kullanımını büyük ölçekte gözlemleyen bir ekipten
Building effective agents — Anthropic genel çerçeve: araçlara ihtiyaç duymadan önce ne kurmalı
pydantic-ai tipli işlevler olarak araçlar; doğrulama hatalarını model zaten okuyabilir — hata mesajı bulgusu yerleşik hâlde
outlines Bölüm 18’in kısıtlı üretimi; bir enum’u öneri değil garanti yapan mekanizma
smolagents kod kipli ajanlar içerir, böylece iki yüzeyi kendi görevinizde karşılaştırabilirsiniz
JSON Schema belgeleri şema yazarken aslında kullandığınız kısıt dili; çoğu kişi bunun ancak onda birini kullanıyor
Birincil kaynaklar
konu kaynak
modellerin işlev çağırmayı öğrenmesi Schick vd. (2023)
araç kullanımıyla iç içe geçmiş akıl yürütme Yao vd. (2023)
şemayı katı bir kısıt yapmak Willard ve Louf (2023)
kendini düzeltmenin neyi düzeltip düzeltmediği Huang vd. (2024)
ölçekte araç kullanımı ve kusur biçimleri Qin vd. (2024)
geniş bir araç yüzeyinin maliyeti ve onu aramak Anthropic (2025)
araç menüsünün yerine bir yorumlayıcı koymak Cloudflare (2025)

24.12 Akılda kalması gerekenler

  • Bir araç şeması dokümantasyon değil prompt metnidir. Model ondan tek bir şans alır, kaynağınızı okuyamaz ve bir tahmini kontrol edemez. Şemanın söylemediği ne varsa uydurur.
  • Açıklamadan önce enum yazın. Bir parametreyi serbest dizgiden enum’a taşımak doğru çağrıları %25’ten %100’e çıkardı; enum 60/60’a ulaştıktan sonra üstüne eklenen düzyazı gözlenebilir hiçbir şey katmadı. Enum’suz düzyazı sınanmadı ve değerlerini listeleyemeyeceğiniz parametreler için elinizdeki tek köprü odur.
  • Kötü bir şema yanlış çağrı değil hiç çağrı üretir. Opak varyantta araç vakaların %41,7’sinde çağrılmadı ve model bunun yerine parametrik bellekten cevap verdi — kendinden emin, uydurulmuş bir paragrafla. Bu bir hatadan kötüdür, çünkü cevaba benzer.
  • Kısıt olmadan model kullanıcının sözcük dağarcığını API’nize yansıtır. mali buyukluk, ekip mevcudu, takvim — ve API’nin butce istediği yerde bütçe. Bu, Bölüm 16’daki sorunun bir işlev imzasının içinde ortaya çıkmasıdır.
  • Burada ölçülen en büyük tekil farkı hata dizgisi yarattı. Toparlanma, geçersiz değeri adlandırıp geçerlileri listeleyerek %1,7’den %100’e çıktı. Neyin işe yarayacağını yazın; gerisi isteğe bağlıdır.
  • Bir stack trace yarısı yazılmış bir hata mesajıdır. Başarısız olan değeri adlandırır, neyin işe yarayacağını hiç söylemez. Biçimler içinde en az yeniden denemeyi o üretti, ama denemeleri en sık doğru olan da oydu (9’da 7) — ikisi de n = 60’ta istatistiksel olarak sağlam olmayan, betimleyici örüntüler. Bunu hiçbir şeyden kötü diye değil, bitmemiş diye okuyun ve üçüncü cümleyi ekleyin.
  • Bir hatadan sonra baskın kusur döngüye girmek değil vazgeçmektir. Dört hata biçiminden üçü modeli araç çağırmayı bırakıp veriyi almadan cevaplamaya itti — bir yeniden deneme döngüsünden daha sessiz ve daha kötü bir kusur.
  • Bir aracın döndürdüğü şey, ajanın durumuna yapılan bir yazma işlemidir. Görevin ihtiyaç duyduğu alanları döndürün, sayfalamayı sonuçta belirtin ve araç tarafında özetleyin. 50.000 token’lık bir sonuç, sonraki adımların ihtiyaç duyduğu bağlamı tüketebilir ve sonraki her çağrıya taşınır; onu görevin bağlam ve maliyet bütçelerine karşı tartın. Sırları ya da kullanıcının göremeyeceği kayıtları asla döndürmeyin.
  • Eylem yapan bir araç iki kez çağrılmaya dayanıklı olmalı. Onu idempotent yapın, ona bir dry run verin ve onay kapısını prompt’a değil çalışma zamanına koyun.