Süreç çöktü. Kart ikinci kez çekilmedi.
Dayanıklı ajan framework'ü — runtime, HTTP sunucusu, Studio, evals, auth. Yeniden yazacağın bir şey yok: Vercel AI SDK ile yazdığın ajan olduğu gibi kalır, aynı runId ile tekrar çağır, tamamlanmış tool'lar bir daha çalışmaz.
npm create gnl@latest import { generateText } from 'ai';
+ import { runDurable } from '@gnldev/durable';
- const res = await generateText({ model, tools, prompt });
+ const res = await runDurable({
+ runId, journal, model, tools, prompt,
+ });generateText ile aynı argümanlar. Tek eklenen runId ve journal — tool tanımlarına hiç dokunmuyorsun.
Sen kaçırabilirsin. Modelin kaçırabilir. GNL kaçırmaz — durur, sorar.
AI'ınız "oluşturuldu" dedi. Gerçekten oluşturdu mu?
Bir tool sonucu çalıştırılmak yerine journal'dan cevaplandığında model bunu taze bir başarı gibi anlatır — kullanıcı ikisini birbirinden ayıramaz. Garanti çalışıyor, anlatım yalan söylüyordu. Bunu canlı testte ölçtük; kapatan mekanizmalar ve maliyetleri aşağıda. Ve tekrar gerçek hayatta çoğu zaman aynı baytlarla gelmez: birebir tekrarı hash yakalar; farklı yazımla geleni görebilecek tek katman semantik kimliktir — o da karar vermez, sorar.
Kullanıcı yeni bir iş istedi. Model önceki turun ödemesini yeniden yaydı.
"…bu ayki ödemelerin özetini mailleyelim" → payInvoice({ ref: 'INV-7702', amount: 4250 })
Bu bir kullanıcı hatası değil: cümleyi yazan insan doğru yazmıştı, argümanı üreten model önceki turun ödemesini yeniden yaydı — hiçbir dikkat, hiçbir prompt bunu kapatamaz. Gerçek motordan geçirdiğimiz konuşma trafiğinde, modelin araç çağırdığı 126 turun 13'ünde oldu; 13'ü de kapıda durdu ve karar insana gitti — katman olmasaydı ikinci kez ödenen faturalar, ikinci kez açılan siparişler olurdu. Aynı koşuda katman 3 kez de gereksiz sordu. Senaryoları biz ürettik ve tek bir araç modeli koşturduk; bu sizin kurulumunuzda çıkacak bir oran değil — ölçtüğümüz, bu hatanın var olduğu ve kullanıcının onu engelleyemediği.
Model üç kez "sipariş oluşturuldu" dedi. Gerçek sayaç 2'de kaldı.
Yan-etki sayacı ile modelin anlattığı arasındaki fark, kullanıcının göremediği bir yalandı — kayıttan gelen cevap taze bir başarıdan ayırt edilemiyordu. GNL'de model artık kendisi söylüyor: "işlem yeniden çalıştırılmadı — gördüğünüz önceki işin kaydı." Canlıda ikinci kanıt: "KLIMA-5" sipariş edildi; "klima-5" istendiğinde hash ıskaladı, semantik kimlik yakaladı — soru insana düştü.
replayDisclosure: 'explain'
Skor asla karar vermez — karar deterministik alanlarda, son söz insanda.
Karar anında kör, anlatırken dürüst
Not yalnızca kaydın tüketildiği adımdan SONRAKİ adıma enjekte edilir; journal'a, thread belleğine ya da sonraki turlara hiç girmez. Model işin daha önce yapıldığını KARAR vermeden önce öğrenmez — öğrenseydi elinizde sessiz ve denetlenemez bir dedup olurdu.
Kaza sorusuz emilir, gerisi her seferinde sorulur
Çift-tık ya da retry penceresine düşen tekrar soru bile sorulmadan emilir. Pencerenin dışında kalan tekrar ise — kullanıcı da yapmış olsa, model de — HER SEFERİNDE bir insan sorusuna düşer; onay ikinci işi gerçekten yaratır, ret yaratmaz. Sessizce yutulan tekrar da yok, sessizce koşan tekrar da.
Farklı kelimeler, aynı iş — hash'in kör olduğu yerde
Çift-tık'ı hash yakalar; ama kullanıcı bu sefer farklı yazar, model argümanı bu sefer farklı çıkarır ("LAMBA-1" / "lamba-1", unicode tire). O anda hash kördür ve araya girebilen TEK katman semantik kimliktir: embedding yalnızca ADAY bulur, kararı normalize edilmiş kimlik alanları verir, tutarlar farklıysa soruya ayrıca yazılır. Embedder ayakta değilse akış fail-open devam eder — kararı her durumda insan verir.
Onay kutusu modelin GERÇEK argümanlarını gösterir
Canlı bir vakada kullanıcı 250 dedi, model 100 geçirdi — modeller sizin söylediğiniz tutarı değil bağlamda duranı kopyalayabiliyor. Kutu, aracın çalışacağı TAM argümanları gösterdiği için farkı insan yakaladı; özetlenmiş bir cümle gösterseydi yakalayamazdı.
Sınırlarımızı ölçtük ve yayınlıyoruz.
Semantik maliyet thread-lokaldir: kullanıcı, kiracı ya da toplam hacimle değil, TEK bir konuşmadaki yan-etki işi sayısıyla büyür. Milyonlarca kullanıcılı bir kurulumda her kapılı çağrı yine on milisaniyeler öder; ölçeklenme sıradan yatay ölçeklenmedir.
Sınır açıkça yazılı: tek bir konuşmada binlerce yan-etki işi olan uç senaryoda tarama saniyeye yaklaşır — bu, v1'in bilinçli sınırıdır (süreç-içi kaba kuvvet, thread kapsamı). Harici vektör index'i (v2) veri gelene kadar bilerek bekliyor; recall arayüzü taramayı zaten yalıttığı için bu bir yeniden yazım değil, bir değiştirme olacak.
Ölçüm: 6 Eylül 2026 · gerçek Postgres · 2048 boyutlu vektörler · bench-scale.ts
Duplicate guard dokümanını açJournal'ın üstünde ne kuruyorsun
Aşağıdaki her yetenek aynı journal'a dayanıyor — her birinin exactly-once ve replay edilebilir olmasının, kendi kuralları olan ayrı bir alt sistem olmamasının sebebi bu.
Exactly-once tool'lar
Tool çağrıları AI SDK'nın ürettiği toolCallId ile anahtarlanır. Replay'de aynı id geldiği için tamamlanmış bir tool bir daha çalışmaz — kart iki kez çekilmez.
Dokümanı aç ›const journal = new InMemoryJournal();
const counter = { charges: 0 };
// 1) İlk çalıştırma: tool çağrılır, sonra çöker.
await expect(
runDurable({
runId: 'run-1', journal, model,
tools: tools(), prompt: 'charge',
}),
).rejects.toThrow('CRASH');
expect(counter.charges).toBe(1);
// 2) Aynı runId ile devam: chargeCard TEKRAR ÇALIŞMAZ,
// sonuç journal'dan gelir.
const res = await runDurable({
runId: 'run-1', journal, model,
tools: tools(), prompt: 'charge',
});
expect(counter.charges).toBe(1); // exactly-onceNasıl çalışır
İstekten çökmeye, çökmeden replay'e — journal her adımı tutar; çöken süreç kaldığı yerden, aynı sonuçla devam eder.
İstek gelir
`runDurable` çağrılır — runId + prompt ile ajan döngüsü başlar.
Journal'a eklenir
Model adımı ve toolCallId'li tool çağrısı journal'a append edilir (Sqlite/Postgres/Redis).
Süreç çöker
Process kill, deploy ya da timeout — bellekteki her şey kaybolur.
Replay & resume
Aynı runId ile tekrar çağrılır; journal deterministik oynatılır, tamamlanmış tool bir daha çalışmaz.
Her run'ı gör, her adıma geri dön.
Studio journal'ın üstünde çalışır — ayrı bir toplama katmanı yok. Çökmeden sonra da eksiksiz kalmasının sebebi bu: izler canlı toplanmaz, journal'dan sonradan türetilir; süreciyle birlikte ölen bir kütüphanenin yapamadığı şey.
Run, önemli olan adımda durmuş
Destek masası örneğinden gerçek bir run. Ajan politikayı aradı, sonra issueRefund'u çağırdı — ve guard, para hareket etmeden run'ı askıya aldı. Journal zaman çizelgesi onay şeridinin altında, time-travel çubuğu 4 adımın 3'ünde, Fork @3 tam oradan bir "ya olsaydı" dalı açıyor. COST $0.0000 görünüyor çünkü örnek ücretli bir sağlayıcıya değil, deterministik mock modele karşı koşuyor. — görsele tıkla, tam boyutta açılsın.
Üç ekran da examples/app destek masasından, API anahtarı olmadan, tek oturumda alındı — kendi makinende yeniden üretebilirsin.
Kimin için
GNL, yan etkisi geri alınamayan ajan işlerinde devreye girer.
Ödeme işleyen ajanlar
chargeCard gibi bir tool exactly-once çalışır: süreç ortasında çökse ve aynı runId ile tekrar çağrılsa bile kart ikinci kez çekilmez.
E-posta/bildirim gönderen ajanlar
sendEmail, sendNotification gibi tool'lar toolCallId ile anahtarlanır — resume sırasında kullanıcıya aynı bildirim tekrar gönderilmez.
Uzun süreli iş akışları
Çok adımlı ajan görevleri deploy, restart ya da timeout ortasında kalsa da journal'daki son adımdan kaldığı yerden devam eder. Dinamik agent ağlarında (networks) yönlendirme kararları da aynı journal'a CAS ile donar — resume'da router yeniden çağrılmaz.
Dayanıklı tool çağrıları
Harici API çağrıları (ödeme, e-posta, veritabanı yazma) journal'a append edilip idempotent biçimde yeniden oynatılır — bu garanti tanımlı her tool için geçerlidir.
Neden GNL?
Orkestrasyon her yerde var; dayanıklılık öyle değil. GNL, önce dayanıklılığı çözüp üzerine geri kalan her şeyi kurar.
Garantiyi framework olmadan alın
Çekirdek, tek bağımlılığı (superjson) olan tek bir fonksiyondur ve bağımlılıklar yalnız yukarı bakar — registry, REST katmanı, workflow’lar ve Studio onun üstünde durur ve isteğe bağlıdır. Yalnız runDurable’ı alın ya da bütün yüzeyi; yüzeyi sonra bıraktığınızda garanti olduğu yerde kalır.
Süreç ölüyken panonuz yeşil kalamaz
İzler canlı toplanmaz, journal’dan sonradan türetilir; bu yüzden bir çökmeden sonra bile eksiksizdirler ve replay’ler arasında birebir aynıdırlar. Bitmemiş bir çalıştırma OK değil UNSET gönderir — süreciyle birlikte ölen bir enstrümantasyon kütüphanesinin tam da yapamadığı şey.
Dünkü çalıştırmayı yeni modelle koşturun
replayRun, kayıtlı bir çalıştırmanın dondurduğu girdiyi alıp farklı bir model, prompt ya da tool setiyle yeniden koşar; diffRuns ikisini karar noktalarında hizalar ve ilk değişeni adlandırır. Belleğin enjekte ettiğini sıyırdığınızda “bu cevaba recall mı sebep oldu?” sorusu varsayım olmaktan çıkıp deneye döner.
Orkestrasyon değil, dayanıklılık duruşu
Çoğu ajan çatısı orkestrasyona odaklanıp dayanıklılığı sonradan ekler. GNL'de durability temel taş: journal önce gelir, orkestrasyon üstüne oturur — dinamik agent ağı yönlendirmesi ve RAG sorguları bile aynı journal'a durable şekilde yazılır.
Sıkça sorulan sorular
GNL bir agent framework'ü mü?
İkisi de — ne kadarını alacağınıza siz karar verirsiniz. En altta runDurable var: generateText ile aynı argümanları alır, tool tanımlarınıza dokunmaz ve yanında tek bir paket getirir (superjson). Exactly-once ve deterministik replay buradan gelir. Üstünde isteğe bağlı bir framework yüzeyi durur — ajan registry’si, otomatik REST, workflow’lar, ajan ağları, RAG — onun da üstünde Studio ve kurumsal yönetişim. İstediğiniz katmanda durabilirsiniz, çünkü bağımlılıklar yalnızca yukarı bakar: garanti framework’te değil, en altta yaşar.
Tam bir agent framework'ünden farkı ne?
Agent framework’lerinin çoğu orkestrasyon-öncelikli: workflow, RAG, bellek — dayanıklılık varsa da üstüne eklenir. GNL diğer uçtan başlar: exactly-once ve deterministik replay çekirdek garantidir, geri kalan her şey onu sağlayan journal’ın üstüne kurulur. Katmanların ayrılabilir olmasının sebebi bu sıralamadır — garantiyi framework olmadan alabilir, framework’ü sonra bırakıp garantiyi koruyabilirsiniz. Bilinçli yapmadıklarımız: ses ajanları, hazır kanal entegrasyonları (Slack, WhatsApp) ve görsel bir editör; bunlar gerekiyorsa doğru araç tam bir framework’tür. Sohbet arayüzü desteklenir — Vercel AI SDK useChat ve AG-UI için adaptörler vardır.
Mevcut Vercel AI SDK kodumu değiştirmem gerekiyor mu?
Hayır. runDurable, generateText ile aynı argümanları alır ve aynı sonucu döner — üstüne bir interrupts listesi ekler; girişte eklenen tek şey runId ve journal’dır. Tool tanımlarınız olduğu gibi kalır; dayanıklılık sarmalamasını çalışma zamanı kendisi yapar.
Exactly-once ne anlama geliyor?
Tool çağrıları AI SDK'nın ürettiği toolCallId ile anahtarlanır. Replay sırasında model cevabı birebir yeniden üretildiği için aynı id oluşur ve tamamlanmış bir tool bir daha çalıştırılmaz.
Journal verim GNL sunucularına mı gidiyor?
Hayır. Journal (agent koşum kaydı) kendi veritabanında yaşar (BYO-DB). GNL veriyi barındırmaz, payload telemetrisi ya da phone-home yok.
Hangi veritabanlarını destekliyor?
SqliteStorage (tek süreç, dev/self-host) ve ağ tabanlı Postgres/Redis journal adaptörleri (edge/serverless uyumlu) desteklenir.
Edge/serverless'te çalışır mı?
32.4 KiB çekirdek çalışma zamanı ve Postgres/Redis journal adaptörleriyle soğuk başlatma maliyeti olmadan Cloudflare Workers gibi edge ortamlarına gömülür.
Çoklu-agent (multi-agent) ve RAG senaryolarını destekliyor mu?
Evet, aynı journal garantisiyle: statik agent-as-tool'un yanında dinamik agent ağları da var — router-LLM her turda hangi alt-agent'ın çalışacağına karar verir, kararlar journal'a CAS ile donar ve resume'da router yeniden çağrılmaz. RAG tarafında chunking, kalıcı pgvector store ve benzerlik-grafı (GraphRAG) retrieval'i de aynı exactly-once garantisiyle çalışır (bkz. /docs/agent-networks, /docs/rag-pipeline).
Studio nedir?
Koşumları (runs), zaman çizelgesini ve time-travel replay’i gösteren görsel ops paneli. Organizasyonlar, bütçeler, kullanıcılar, policy ve eval yönetimini de barındırır.
Ajanını bugün dayanıklı hâle getir.
Exactly-once ve deterministik replay ile üretime çık — journal senin veritabanında kalır.