Bir AI ajanı, bir döngü içinde çalışan dil modelidir. Görevi okur, "bu dosyayı oku" veya "şu dosyayı sil" gibi bir araç kullanır, sonuca bakar ve iş bitene kadar bu döngüyü sürdürür. Modelin bir aracı kullanmak için yaptığı her istek araç çağrısı (tool call) olarak adlandırılır.
Bu döngüyü çalıştıran koda harness denir. Ne yapılacağına model karar verir. Harness ise bu kararı uygular ve aynı zamanda modelin neler yapabileceğine sınırlar çizer.
İyi bir harness, süreç boyunca pek çok küçük karar alır. Bu isteği hangi model işlemeli? Bu araç çağrısını çalıştırmak güvenli mi? Bu yanıt geri verilmek için yeterince iyi mi? Çoğu harness bu soruları bir sohbet modeline sorarak ve yanıtını okuyarak cevaplar. Ancak bu her seferinde tam bir model çağrısına mal olur; dolayısıyla pratikte kontrollerin büyük kısmı atlanır.
TypeSafe AI'dan Jev, yalnızca bu tür kararlar için tasarlanmış küçük bir modeldir. Durumu tarif edip birkaç soru sorarsınız, o da her birini bir sayıyla yanıtlar. Asla metin üretmez.
Bunun en çok önemsediği nokta, hazır bir ajan yerine kendi ajan döngünüzü, yani bir özel harness kurduğunuz zamandır. Özel bir harness sayesinde hangi modellerin çalışacağını, ajanın nelere erişebileceğini ve işin ne zaman tamamlandığını siz belirlersiniz. Jev, bu tercihlerin arkasındaki kontrolleri her adımda çalıştırılabilecek kadar ucuz hale getirir.
Bu eğitimde, ajan geliştirmek için kullanılan bir TypeScript araç seti olan Pi SDK ile bir harness oluşturacak ve Jev'i üç farklı noktada kullanacaksınız. Sonunda ise tamamlanan harness'ı canlı bir sandbox ortamında çalıştıracak ve ayarlarını kendiniz değiştireceksiniz.
Tam etkileşimli eğitime ve oyun alanına buradan ulaşabilirsiniz:
https://academy.dair.ai/resources/jev-decisions-in-a-pi-sdk-harness
Bu rehber, Sydney Runkle'ın LangChain blogundaki model yönlendirme ve araç geçidi (tool gating) kavramlarını kullanıma hazır LangChain ara yazılımları olarak gösteren Building a Harness with Jev yazısından ilham almıştır. Burada aynı fikirleri Pi SDK üzerinde kendiniz inşa edecek, ardından hataları yönetmek ve yanıtları kontrol etmek için iki yeni kalıp daha ekleyeceksiniz.
Ne geliştireceksiniz?
Harness üç bölümden oluşur. Her biri farklı bir anda Jev'e bir soru sorar ve bu rehberin devamında bu bölümlerden bu isimlerle bahsedeceğiz.

Kullanacağımız örnek senaryo, gezi notlarının bulunduğu bir klasörde çalışan ve her gezi için ayrı bir dosya tutan bir ajandır. Ajan bu notları okuyabilir, yazabilir ve gerçekten silebilir; işte geçidin (gate) bu kadar önemli olmasının sebebi budur.
Jev nedir?
TypeSafe, Jev'i bir Sistem Bir modeli olarak tanımlar. Bu isim, düşünmenin iki modunu tanımlayan psikolog Daniel Kahneman'dan gelir. Sistem Bir hızlı ve otomatiktir; tıpkı bir tavaya dokunduğunuzda sıcak olduğunu anında anlamanız gibi. Sistem İki ise yavaş ve bilinçlidir; uzun bölme işlemi yapmak gibi.
Bu harness'ta sıradan bir dil modeli dosyaları okumak ve yanıtlar yazmak gibi ağır işleri üstlenir. Jev ise etrafındaki hızlı kararları verir. Jev o kadar ucuz ve hızlıdır ki yalnızca riskli olmasını beklediğiniz değil, her araç çağrısı için ona danışabilirsiniz.

Her sayı 0 ile 1 arasında bir olasılıktır. 0.83, Jev'in yanıtın evet olduğundan oldukça emin olduğu anlamına gelir. 0.03 ise hayır yanıtından oldukça emin olduğunu gösterir.
Üç soru türü
Her Jev isteğinin iki parçası vardır. Durum (state), değerlendirilmesini istediğiniz koşuldur; örneğin bir araç çağrısı veya kullanıcı isteği. Sorular ise bu durum hakkında öğrenmek istediklerinizdir. Jev tüm soruları tek bir çağrıda ve eşzamanlı olarak yanıtlar; bu yüzden üç soru sormak, bir soru sormakla yaklaşık aynı süreyi alır.
Jev üç tür soruyu destekler. Jev'in "noul" olarak adlandırdığı ilk tür, evet/hayır sorusudur.

Jev yalnızca sizin söylediğinizi bilir, bu yüzden her seçeneği ve her seviyeyi açık bir dille tarif edin. Bu açıklamalar prompt'un ta kendisidir.
Kurulum
Jev'e, tek bir API anahtarıyla birçok AI modeline erişmenizi sağlayan OpenRouter hizmeti üzerinden ulaşabilirsiniz. Bu tek anahtar hem dil modelini hem de Jev'i kapsar. İki Pi paketini kurun ve anahtarınızı ayarlayın.
1npm install @earendil-works/pi-agent-core @earendil-works/pi-ai
1OPENROUTER_API_KEY=...
Jev'in, standart sohbet adresinden ayrı kendi web adresi vardır. Her zaman typesafe/jev-1.13 gibi belirli bir sürüm belirtin. Tüm Jev istemcisi tek bir fetch çağrısından ibarettir.
1const JEV = "typesafe/jev-1.13";23async function ask(state: unknown, questions: unknown) {4 const response = await fetch("https://openrouter.ai/api/alpha/decisions", {5 method: "POST",6 headers: {7 "Content-Type": "application/json",8 Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,9 },10 body: JSON.stringify({ model: JEV, state, questions }),11 signal: AbortSignal.timeout(2_000),12 });13 if (!response.ok) throw new Error(await response.text());14 return response.json();15}
Ajan, Jev yanıt verene kadar beklediği için çağrı iki saniye sonra iptal edilir. Normal bir yanıt 200 ila 400 milisaniye sürer.
Jev nereye bağlanır?
Pi'nin Agent sınıfı döngüyü sizin yerinize çalıştırır. Kendi kodunuzun bu döngünün belirli anlarında devreye girmesine izin verir. Bu noktalara hook denir. Harness, üç bölümünün her biri için bir hook kullanır.

İlk geçit
Geçidin işe yarar en küçük haliyle başlayalım. Her araç çağrısından önce Jev'e bir evet/hayır sorusu sorun ve yanıt evet gibi görünüyorsa çağrıyı engelleyin.
1import { Agent } from "@earendil-works/pi-agent-core";23const agent = new Agent({4 initialState: { systemPrompt, model, tools },5 streamFn: models.streamSimple.bind(models),67 beforeToolCall: async ({ toolCall, args }) => {8 const { answers } = await ask(9 { tool: toolCall.name, arguments: args },10 {11 destructive: {12 type: "noul",13 instructions: "Bu araç çağrısı, bu çalışma tarafından oluşturulmamış verileri yok eder veya üzerine yazar.",14 criteria: {15 true: "Dosyaları siler, mevcut içeriği keser veya üzerine yazar, verileri düşürür ya da geçmişin üzerine zorla gönderim (force-push) yapar.",16 false: "Okur, listeler, yeni bir dosya oluşturur veya bu çalışmada zaten oluşturulmuş bir dosyaya ekleme yapar.",17 },18 },19 },20 );2122 if (answers.destructive.noul >= 0.65) {23 return { block: true, reason: "Engellendi: bu yıkıcı görünüyor.", terminate: true };24 }25 },26});
Buradaki 0.65 bir eşik değeridir; harness'ın bir çağrıya güvenmeyi bıraktığı sınır çizgisidir. Jev'in bu değerde veya üzerinde puanladığı her şey engellenir.
Artık notlarınızı silmeye çalışan bir ajan, silme işlemi gerçekleşmeden durdurulur. Bir notu silmek yaklaşık 0.83, okumak ise 0.01 puan alır. Ancak bu geçit biraz kabataslaktır. Yepyeni bir dosya yazmak yaklaşık 0.70 puan aldığından o da engellenir.
Soru sormanın maliyeti çok düşüktür. Jev, milyon input token başına 0.042 dolar ücretlendirir; bu, harness'ın kullandığı iki modelden daha ucuz olan GLM 5.3 Flash'ın input fiyatının üçte birinden bile azdır.
İlk geçitten tam teşekküllü harness'a
İlk geçit işe yarıyor ancak dört açık bırakıyor.
- Eşik değeri hook'un içine gömülü olduğundan ayarlamak veya test etmek zordur.
- Kolay veya zor olmasına bakılmaksızın her istek aynı modelde çalışır.
- Jev'e ulaşılamazsa ne olacağını belirten bir kural yoktur.
- Nihai yanıtın kalitesini kontrol eden bir mekanizma yoktur.
Aşağıdaki numaralandırılmış bölümlerin her biri bu açıklardan birini kapatır.
1. Eşik değerlerini tek yerde tutun
Bu bölüm geçidi iyileştirir.
Eşik değerleri ajanın neler yapabileceğine karar verir ve gerçek sonuçları görmeye başladığınızda bunları sık sık ayarlamanız gerekir. Bu yüzden onları hook'un dışına çıkarıp decideGate() adında sade bir fonksiyona taşıyın. Bu fonksiyon Jev'in sayılarını alır ve bir karar (verdict) döndürür: harness'ın bir çağrı hakkındaki nihai kararı. Bu kuralları tek bir yerde toplamaya politika (policy) denir.
Politika ayrıca bir orta seçenek de ekler. Tek bir eşik değeri yalnızca izin ver veya engelle diyebilir. İki eşik değeri ise üç farklı karar sunar.
- blockAt değerinde veya üzerindeyse çağrı engellenir.
- askAt değerinin altındaysa çağrı çalışır.
- İkisinin arasındaysa çağrı, bir insanın onaylamasını bekler.
Bu orta aralık, Jev'in emin olamadığı çağrıları yakalar; tek bir sınır çizgisi bu çağrıları yanlışlıkla ya engeller ya da geçirirdi.

1export function decideGate(signals: GateSignals, policy = DEFAULT_GATE_POLICY): GateVerdict {2 const worst = Math.max(3 signals.destructive.noul,4 signals.irreversible.noul,5 signals.outsideWorkspace.noul,6 );7 if (worst >= policy.blockAt) return { action: "block", ... };8 if (worst >= policy.askAt) return { action: "ask", ... };9 return { action: "allow", ... };10}
Sade bir fonksiyon olduğu için, canlı bir modele ihtiyaç duymadan yukarıdakiler gibi sayıları doğrudan ileterek test edebilirsiniz.
2. Her istek için bir model seçin
Bu bölüm yönlendiriciyi (router) ekler.
Tek bir dosyayı okumak gibi bazı istekler kolaydır. Bir hatanın nedenini bulmak gibi bazıları ise zordur. Her şeyi en güçlü modelde çalıştırmak para israfıdır; her şeyi ucuz bir modelde çalıştırmak ise zor isteklere zayıf yanıtlar verilmesine yol açar. Yönlendirici, her isteği doğru katmanla (tier) eşleştirir; yani hızlı ve ucuz modelle mi yoksa güçlü ve pahalı modelle mi işleneceğine karar verir.
Bir istek başlamadan önce yönlendirici, tek bir çağrıyla Jev'e iki soru sorar. Bir seçim (choice) katmanı belirler, bir puan (score) ise isteğin karmaşıklığını derecelendirir.

1const ROUTER_QUESTIONS = {2 tier: choice("Bu isteği hangi model katmanı işlemeli?", {3 fast: "Tek bir dosyayı okumak, içinden bir bilgi çekmek veya tek bir yerde küçük bir düzenleme yapmak.",4 powerful: "Birden fazla dosyayı kapsayan işler veya bariz bir nedeni olmayan hatalar.",5 }),6 complexity: score("Bu istek ne kadar akıl yürütme gerektiriyor?", [7 "Mekanik. Tek adım, muhakeme gerektirmez.",8 "Yerel. Tek bir alanda birkaç adım.",9 "Mimari. Çok sayıda hareketli parça veya bilinmeyen bir kök neden.",10 ]),11};
Yönlendiricinin politikası bu iki yanıtı şu şekilde kullanır.
- Karmaşıklık puanı yüksekse, Jev "fast" seçmiş olsa bile güçlü modeli kullan.
- Jev kendi seçimine güvenmiyorsa, garanti olsun diye güçlü modeli kullan.
- Aksi takdirde Jev'in seçtiği modeli kullan.
1if (complexity.score >= policy.escalateAtComplexity) return powerful;2if (tierAnswer.confidence < policy.minConfidence) return policy.fallbackTier;3return tierAnswer.choice;
Bu sadece bir politika örneğidir. Sizin politikanız, kendi alanınıza uygun olarak yanıtları farklı şekillerde değerlendirebilir; örneğin yüksek hacimli bir toplu iş için ucuzdan yana olabilir veya production ortamına dokunan her şeyi mutlaka üst modele aktarabilir. Jev yalnızca yanıtları sağlar; onlarla ne yapılacağına sizin kodunuz karar verir.
Neden yalnızca bir kez seçim yapılır?
Yönlendirici modeli bir kez, istek başladığında seçer ve istek bitene kadar onu kullanmaya devam eder. Bunun nedeni prompt önbelleğe alma (prompt caching) özelliğidir.
Ajan her adım attığında, model o ana kadarki tüm konuşmayı yeniden okur. AI sağlayıcıları yakın zamanda okunan konuşmaları depolar, böylece tekrar okumak ucuza gelir. Ancak her modelin kendi deposu vardır. İşin yarısında modeli değiştirirseniz, yeni model her şeyi tam ücret karşılığında baştan okumak zorunda kalır.
Jev'in kurucusu bu hesaplamaları kodlama ajanları üzerine hazırladığı bir tasarım dokümanında detaylıca anlatıyor. Uzun bir oturumda Claude Opus'tan daha ucuz olan Sonnet'e geçip tekrar Opus'a dönmek, sürekli Opus'ta kalmaktan yaklaşık %50 daha pahalıya mal oluyor. Bu yüzden modeli, konuşma henüz kısanken başlangıçta seçin ve onunla devam edin.
3. Jev'in çökme ihtimaline karşı plan yapın
Bu bölüm hem geçidi hem de yönlendiriciyi değiştirir.
Harness her araç çağrısı için Jev'e danışmaya başladığında, ajan tamamen Jev'e bağımlı hale gelir. Her çevrimiçi hizmet gibi Jev de yavaşlayabilir veya çökebilir. Hiç yanıt alamadığında her bölümün ne yapacağını önceden belirleyin. Doğru tercih her bölüm için farklıdır.
Geçit çağrıyı engeller. Geçit Jev'e soramazsa, çağrının güvenli olup olmadığını bilemez. Çağrıya izin vermek dosyaların silinmesine yol açabileceğinden geçit reddeder. Mühendisler buna kapalı kalarak hata verme (failing closed) der; tıpkı elektrikler kesildiğinde kendini kilitleyen bir kapı gibi.
Yönlendirici güçlü modeli kullanır. Yönlendirici Jev'e soramazsa, isteğin ne kadar zor olduğunu bilemez. Güçlü model her şeyin üstesinden gelebileceği için istek yine de iyi bir yanıt alır, siz de biraz daha fazla ödeme yapmış olursunuz. Bu açık kalarak hata vermedir (failing open); işin devam etmesine izin vermektir.

4. Yanıtı doğrulayın
Bu bölüm doğrulayıcıyı (verifier) ekler. Ajan harness'larında doğrulayıcı, ajanın işini tamamlanmış saymadan önce kontrol eden adımdır.
Bir ajan, bir şeyleri eksik bırakan veya dosyalarda aslında kontrol etmediği şeyleri söyleyen bir yanıtla işi bitirebilir. Bunu okuyan kişi genellikle farkı anlayamaz. Yanıtı geri vermeden önce kontrol etmek, ajanın yeniden deneme şansı varken bu durumu yakalar.
Doğrulayıcı, bitmiş yanıtı temel aldığı dosyalar ve araç sonuçlarıyla birlikte Jev'e gönderir. Jev yanıtın kalitesini puanlar ve iddialarının temellendirilmiş (grounded) olup olmadığını, yani ajanın gerçekten okuduklarıyla desteklenip desteklenmediğini söyler.

1const VERIFY_QUESTIONS = {2 quality: score("Yanıt isteği ne kadar iyi karşılıyor?", [3 "İsteği yanıtlamıyor.",4 "Okuyucunun fark edeceği bir eksikle kısmen yanıtlıyor.",5 "İsteği tamamen yanıtlıyor.",6 ]),7 grounded: noul("Her olgusal iddia, transkriptteki dosyalar veya araç sonuçlarıyla desteklenmektedir."),8};
İki kural, ajanın sonsuza dek yeniden denemesini engeller. Toplamda en fazla iki deneme hakkı vardır. Ayrıca Jev kendi verdiği nota güvenmediğinde, harness başka bir deneme için ödeme yapmak yerine yanıtı kabul eder.
Güvenlik ve loglama
Jev size bir olasılık verir ve bir olasılık yanlış çıkabilir. Bu nedenle düz kodla kesin olarak kontrol edilebilen her şey kodla kontrol edilmelidir. Bu harness'ta her dosya aracı, Jev ne derse desin proje klasörü dışındaki herhangi bir yolu reddeder. Jev'i, kodun veremeyeceği kararlara saklayın.
Geçit yalnızca araç çağrısının kendisine, yani aracın adına ve girdilerine bakar. Bu, bir dosyaya veya web sayfasına gizlenmiş metnin modeli zararlı bir şey yapmaya kandırdığı prompt injection saldırılarına karşı koruma sağlar. Geçit kandırmacayı görmez ama onun yol açtığı zararlı çağrıyı görür.
Her kararı, arkasındaki sayılarla birlikte loglayın. Log, bir şeyin neden engellendiğini açıklar ve eşik değerlerini ayarlamak için gerçek veriler sunar. Harness, decisions.jsonl adlı bir dosyaya her karar için bir satır yazar. Geçit ajanın yapmaya çalıştığı her şeyi gördüğünden, log dosyası e-posta adreslerini ve anahtarları gizler, uzun girdileri kısaltır.
Deneyin
Aşağıdaki sandbox, bu eğitimdeki tamamlanmış harness'ı gerçek Jev'e bağlı olarak çalıştırır. Gezi notlarının bulunduğu klasör üzerinde işlem yapar ve delete_path aracı bu notları gerçekten silebilir.
Buradan deneyin: https://academy.dair.ai/resources/jev-decisions-in-a-pi-sdk-harness
Neden kendi harness'ınızı kurmalısınız?
Hazır ajanlar bu kararları kendi dahili kurallarıyla alır. Özel bir harness ise bunları sizin kodunuza taşır. Modelleri siz seçer, eşik değerlerini siz belirlersiniz, bir insanın ne zaman devreye gireceğine siz karar verir ve loglardan her çağrının tam olarak neden yapıldığını okursunuz.
Bunu uygulanabilir kılan şey Jev'dir. Her karar birkaç yüz milisaniye sürer ve bir sentin çok küçük bir kısmına mal olur; böylece kontrolleri yalnızca tam bir model çağrısını karşılayabildiğiniz yerlerde değil, işinizin gerektirdiği her yere ekleyebilirsiniz. Bu eğitimdeki üç bölüm bir başlangıç noktasıdır. Kendi alanınız için kuracağınız özel bir harness, Jev'e o alanda önem taşıyan her türlü soruyu sorabilir.
Diğer kullanım alanları
Aynı üç bölüm, kodlama ajanları dışında da işe yarar.
- Kod inceleme botları. Önerilen her değişikliği puanlayın ve bir insana yalnızca okunmaya değer olanları gösterin.
- Kayıt temizliği. İki kaydı birleştirmeden önce aynı şeyi tanımlayıp tanımlamadıklarını sorun ve emin olunmayan çiftleri bir insana bırakın.
- Belge iş akışları. Çıkarılan her sayfayı puanlayın ve yalnızca düşük puan alanları yeniden çalıştırın.
- Onay kuyrukları. Yalnızca "insana sor" aralığındaki çağrılar bir insan inceleyiciye ulaşsın.
Her durumda açık uçlu işi dil modeli yapar, Jev ise etrafındaki küçük soruları yanıtlar.
Bu eğitimdeki sorular, eşik değerleri ve politikalar öğrenme amaçlı örneklerdir, üretime hazır ayarlar değildir. Bu harness değişikliklerinin maliyeti ve yanıt kalitesini nasıl etkilediğine dair kıyaslamalar yapıyoruz; bu sonuçları içeren devam rehberi yakında yayımlanacak.
Bu rehberi ve sandbox'ı hazırlamak için Opus 5.5 ile bir akşamımı geçirdim. Herhangi bir sorunla karşılaşırsanız lütfen bana DM atın. Makaleyi kopyalamaktan ve bu fikirleri denemeye devam etmek için ajanlarınıza beslemekten çekinmeyin.





