Dokümanlar menüsü
Deterministik replay & çökme kurtarma
Journal'a yazılan her model/araç adımı sayesinde yarıda kesilen bir run aynı runId ile kaldığı yerden, prompt'u yeniden vermeden deterministik olarak devam eder.
Ne işe yarar / ne zaman kullanılır#
Uzun süren bir agent koşusu ortasında process çöker, deploy yeniden başlatır ya da bir araç onay bekleyip askıya alınır (bkz. human-in-loop-approvals). Klasik generateText bu noktadan sonra hiçbir şey bilmez — konuşmayı ve tüm araç sonuçlarını yeniden üretmeniz gerekir. runDurable her model adımını ve her araç çağrısının sonucunu journal'a yazar; aynı runId ile tekrar çağrıldığında (veya resumeRun ile) daha önce üretilmiş adımları modele YENİDEN sormaz — journal'dan okur, kaldığı yerden devam eder. Sonuç: yan-etkili bir araç (ör. ödeme tahsili) çökme sonrası ikinci kez çalışmaz, model aynı token'ları ikinci kez harcamaz.
Mekanizmadan değil de yaşadığın sorundan mı geliyorsun? Süreç çöktükten sonra generateText ajanını devam ettirmek aynı konuyu sorun tarafından anlatıyor.
Kurulum / import#
Paket tek girişten dışa açılır — alt-yol gerekmez (yalnız kalıcı depolama adaptörleri @gnldev/durable/sqlite ve @gnldev/durable/postgres ayrı export'tur, bkz. storage-adapters).
import { runDurable, resumeRun, InMemoryJournal } from '@gnldev/durable';Adım adım kullanım#
Aşağıdaki örnek gerçek test senaryosundan alınmıştır: 5000 birim tahsilat isteyen bir araç çağrısı, guard tarafından onaya (require-approval) düşürülür — run askıya alınır. Prompt hiçbir yerde tekrar yazılmaz; resumeRun yalnızca runId ve onay bilgisiyle çağrılır.
const journal = new InMemoryJournal();
const r1 = await runDurable({
runId: 'o1',
journal,
model: makeModel(),
tools: makeTools(counter),
guard,
prompt: 'charge 5000',
stopWhen: stepCountIs(6),
});
// nothing has been charged yet — the guard suspended it
console.log(counter.charges); // 0
console.log(r1.interrupts.length); // 1const r2 = await resumeRun('o1', {
journal,
model: makeModel(),
tools: makeTools(counter),
guard,
approvals: { 'call-c': true },
stopWhen: stepCountIs(6),
});
console.log(counter.charges); // 1 — exactly once
console.log(r2.text); // 'Done.'resumeRun içeride, ilk çağrıda journal'a yazılmış girdiyi (prompt/messages/system) okuyup runDurable'ı aynı runId ile tekrar çağırır — self-contained resume budur. Kayıtlı girdi yoksa (bilinmeyen runId) anlamlı bir hata fırlatır.
API referansı#
runDurablegenerateText'in yerine geçer: model + araçları durable sarmalayıcılarla çalıştırır, her adımı journal'a yazar. Aynı runId ile tekrar çağrılırsa kayıtlı adımları yeniden çalıştırmaz.
resumeRunrunId'ye kayıtlı girdiyi (prompt/messages/system) journal'dan okuyup runDurable'ı tekrar çağırır — prompt'u yeniden vermeye gerek yok, sadece runId + agent config + approvals.
ResumeAgentConfigresumeRun için agent yapılandırması: model, tools?, guard?, stopWhen?, replay? — Studio embed ve resume çağrılarında ortak kesit.
reconstructStateSaf fonksiyon: journal entry'lerinden (JournalEntry[]) belirli bir adıma (uptoStep) kadar konuşma durumunu materyalize eder — time-travel ve fork'un temeli (bkz. time-travel-fork).
DivergenceErrorreplay: 'strict' modunda, replay sırasında bir aracın yeniden üretilen argümanları kayıtlı argsHash ile uyuşmazsa fırlatılır (non-determinizm tespiti). Varsayılan 'lenient' modda yalnız uyarı basar.
RunBusyErrorAynı runId eşzamanlı başka bir process/çağrı tarafından çalıştırılıyorsa (opt-in run-level lock veya tool execute in-flight) fırlatılır.
loadReplayCacheDahili optimizasyon: journal bir readRun (JournalReader) sağlıyorsa (ör. SQLite/Postgres) resume'da tüm model/araç kayıtlarını tek sorguda önceden yükler. runDurable/resumeRun tarafından otomatik kullanılır — genelde doğrudan çağırmanız gerekmez.
InMemoryJournalTest/geliştirme için bellek-içi journal (Journal + JournalReader). Prod'da kalıcılık için SQLite/Postgres adaptörleri aynı arayüzü uygular (bkz. storage-adapters).
runDurable'a verilen replay: 'strict' seçeneği, replay sırasında bir aracın girdisi kayıtlı hash'iyle uyuşmazsa (ör. model prompt değişmiş, non-deterministik bir üretim yapmış) çalışmayı DivergenceError ile durdurur. Varsayılan 'lenient' modda drift yalnızca konsola uyarı olarak düşer, kayıtlı çıktı yine de döner.failed kaydıyla kalan yan-etkili (ör. ödeme) bir çağrıyı otomatik tekrar çalıştırmaz — çift tahsilat riskine karşı kullanıcının açıkça approvals ile onay vermesi gerekir. Aynı davranış aynı runId içindeki her araç çağrısı için geçerlidir — bkz. exactly-once-tools.