Dokümanlar menüsü
Durable workflow'lar
Çok-adımlı workflow'ları aynı runId ile durable çalıştırır; suspend/resume güvenlidir, retry() ile bildirimsel yeniden deneme (journal'lı sayaç) sunar ve /workflows/:name/run ucundan REST olarak sunulur.
Ne işe yarar / ne zaman kullanılır#
Tek bir agent çağrısının ötesine geçen, birden çok adımdan oluşan iş akışlarını (ör. önce bir kayıt oluştur, sonra ödeme kontrolü yap, ardından onay bekleyip bildirim gönder) modellemek için kullanılır. Her adım journal'a ayrı ayrı kaydedilir; süreç ortasında proses çökerse veya bir adım (sleep/waitFor) askıya alınırsa, aynı runId ile tekrar çağrıldığında tamamlanmış adımlar yeniden ÇALIŞMAZ (replay), yalnızca kaldığı yerden devam eder.
Somut senaryo: bir sipariş akışında "ödeme onayı bekle" adımı saatler sürebilir. Süreç bu sırada kapansa bile, aynı runId ile tekrar çalıştırıldığında ödeme adımı hâlâ askıdaysa suspended döner; koşul sağlandığında adım gerçekten ilerler ve sonraki adımlara geçilir.
Kurulum / import#
Workflow'u tanımlamak için @gnldev/workflow paketindeki workflow() builder'ı kullanılır; çalıştırmak/kaydetmek için ise @gnldev/durable'ın createGnl registry'si gerekir (Workflow sınıfı, createGnl'ın beklediği WorkflowLike yapısal arayüzünü zaten karşılar — ayrı bir uyarlama gerekmez).
import { workflow, step, retry } from '@gnldev/workflow';
import { createGnl } from '@gnldev/durable';Adım adım kullanım#
1) Workflow'u workflow() ve step(id, run) ile sıralı adımlar halinde tanımlayın:
const myWorkflow = workflow<{ email: string }>()
.then(step('onboard:create-account', async (input) => {
// ... create the account
return { ...input, accountId: 'acc_1' };
}))
.then(step('onboard:send-welcome', async (input) => {
// ... send the welcome email
return { ...input, welcomed: true };
}));2) Workflow'u createGnl'ın workflows alanına isimle kaydedin:
const config: CreateGnlConfig = {
storage,
agents: { /* ... */ },
workflows: { onboard: myWorkflow },
};
const gnl = createGnl(config);3) runWorkflow ile aynı runId'yi vererek çalıştırın — süreç kesilse bile aynı runId ile tekrar çağrı, tamamlanmış adımları atlayıp kaldığı yerden devam eder:
const res = await gnl.runWorkflow('onboard', input, { runId: 'wf-1' });
// POST /workflows/onboard/run with the same runId -> resumes where it stoppedREST tarafında bu, @gnldev/server'ın otomatik ürettiği POST /workflows/:name/run ucu üzerinden aynı sözleşmeyle sunulur — gövdede { runId?, input } beklenir; verilen runId journal'da zaten bir iz taşıyorsa istek otomatik olarak bir resume kabul edilir (bütçe kapısı bu durumda atlanır, yalnız gerçekten yeni iş zorlanır). Kayıtlı workflow'ların adım listesi GET /workflows ile introspect edilebilir.
4) Bir adımı bildirimsel olarak retry'lamak için retry(step, policy) kullanın — attempts (ilk çalıştırma dahil toplam deneme), opsiyonel backoffMs (sabit ms ya da deneme indeksinden hesaplayan fonksiyon) ve tüm denemeler tükenince koşacak opsiyonel fallback adımı alır. Sarılmış adım drop-in'dir — aynı id'yi taşır, then/branch/parallel içinde sarılmamış bir adım gibi kullanılır:
import { retry, step } from '@gnldev/workflow';
const chargeStep = retry(
step('order:charge', async (input) => chargeCard(input)),
{
attempts: 3,
backoffMs: (attempt) => attempt * 500, // 500ms, 1000ms, ...
fallback: step('order:charge-fallback', async (input) => ({ ...input, charged: false })),
},
);
const orderWorkflow = workflow<{ orderId: string }>().then(chargeStep);Deneme sayacı `${runId}:wf:${id}:attempts` anahtarıyla journal'a yazılır — crash-resume'da sayaç sıfırdan BAŞLAMAZ, "toplam N deneme" sözü process ölümlerinden bağımsız kalır. Önceki bir koşuda tükenmiş bir adım, resume'da doğrudan fallback'e (varsa) gider — yeniden N deneme yapılmaz. Askı (WorkflowSuspended, ör. sleep/waitFor) hata sayılmaz ve deneme tüketmeden aynen dışarı yayılır. fallback, adımın kendi anahtarında ayrıca journal'lanır — fallback koşup crash olursa resume'da yeniden çalışmaz.
API referansı#
workflowworkflow<Input>() — bir workflow tanımını başlatır; .then(step) sıralı adımları zincirler.
stepstep(id, run) — journal'lanan tek bir adım. id, bir resume'un eşleştiği şeydir; yani bir etiket değil, sözleşmenin parçasıdır.
waitForResumeTipli insan-döngüde askı: workflow durur ve operatörün verdiği değerle runResumable({ resume }) üzerinden devam eder.
cancelWorkflowRunDayanıklı iptal — karar journal'lanır, yani sonradan dönen bir worker da onu görür.
forkWorkflowRunBir workflow çalıştırmasını belirli bir adıma kadar yeni bir runId'ye kopyalar; forkRun'ın workflow düzeyindeki karşılığı.
createGnlAgent + workflow registry'sini kurar; dönen nesnenin runWorkflow/listWorkflows metodları workflow'ları çalıştırır/introspect eder.
WorkflowLikecreateGnl'ın workflows alanına verilebilecek yapısal arayüz — build()/run()/opsiyonel runResumable(). @gnldev/workflow'un Workflow sınıfı bunu zaten karşılar.
WorkflowMetalistWorkflows()'un döndürdüğü introspeksiyon şekli: { name, steps: { id, kind }[] }.
WorkflowRunResultrunWorkflow() sonucu: runId, output, suspended/paused bayrakları, stepId/reason ve adım başına çıktılar.
RunOptionsgnl.run()/stream() için çağrı seçenekleri (runId, prompt/messages, context, vb.) — runWorkflow ayrıca kendi { runId?, maxSteps? } seçeneğini kullanır.
retry(step, policy: RetryPolicy) → Step. Bir adımı bildirimsel retry-policy ile sarar — drop-in (aynı id); deneme sayacı journal'da (crash-resume'da tükenmez), askı deneme tüketmez, fallback ayrı journaled.
RetryPolicy{ attempts, backoffMs?: number | ((attempt) => number), fallback?: Step } — attempts ilk çalıştırma dahil toplam deneme sayısı.
RetryExhaustedErrorTüm denemeler tükendi ve fallback verilmedi — { stepId, attempts, cause } taşır.
input ve ctx parametrelerine güvenin; dış (closure) durum yerine journal'lanan çıktıya dayanın — aksi halde resume sırasında replay edilen adımlarla gerçek zamanlı yeniden çalışan adımlar arasında tutarsızlık oluşabilir.sleep/waitFor içeren workflow'lar için run() yerine runResumable() gerekir — düz run() askıya alma sinyalini (WorkflowSuspended) fırlatıp hata olarak yükseltir. createGnl.runWorkflow, workflow'da runResumable varsa onu otomatik tercih eder.İlgili sayfalar#
- Deterministic replay & crash recoveryAn interrupted run resumes deterministically from where it left off.
- Human-approved tools (guard)Guard suspends risky calls; resumed on approval.
- Automatic REST API + OpenAPI + SSETurns createGnl into a durable HTTP API + SSE stream in one line.