2026-07-06

Duraklat, Onayla, Devam Et, Yönlendir

Bazı action'lar insan onayı gerektirir ve bir kullanıcı ajanı koşu ortasında düzeltmek isteyebilir. Journal destekli bir interrupt, resume ve steer, bir insanı döngüye durable biçimde dahil eder.

Neler öğreneceksin

Part 9 ajanı durable kıldı: iki step arasında crash edip state’i kaybetmeden ya da bir müşteriyi iki kez charge etmeden geri dönebilir. Ama hâlâ inatçı bir alışkanlığı var. Başı eğik, kendi başına baştan sona koşuyor, hiç durup sormuyor. Gerçek bir deployment’ın ihtiyaç duyduğu iki şey eksik, ve ikisi de koşunun durup kontrolü bir kişiye devretmesini gerektirir. İlki onay: bazı action’lar bir insan evet demeden gerçekleşmemeli, ve kanonik durum paradır. Bir $100 policy threshold’unun üzerindeki bir $180.00 refund, yetkisi olan biri onaylamadan post edilmemeli. İkincisi düzeltme: koşuyu izleyen bir kişi, ajanın bir sonraki adımda ne yapacağını yalnızca kutsamak ya da engellemek yerine değiştirmek isteyebilir, ve ikili bir onayla-ya-reddet gate’i “yap, ama daha düşük bir tutar için” ifadesini taşıyamaz. Bu parça ikisini de, Part 9’un journal’ının üzerine, dört hamleyle ekler. İlki, interrupt(): gate’li bir action’da ajan tool’u çağırmaz, bir token’la birlikte bir pending_approval event’ini journal’a yazar ve serializable bir PendingApproval raise eder, ki bu en üst seviyede yakalanır, böylece koşu duraklatılır ve token döndürülür, öldürülmez. İkincisi, resume(run_id, decision): daha sonra bir insan karar verir, ve resume journal’ı tam olarak Part 9’daki gibi replay eder, kararı kaydeder ve devam eder, gate’li refund idempotency key’ini koruyarak, böylece onaylanmış bir resume retry edilse bile effectively-once çalışır. Üçüncüsü, steer, yalnızca approve ya da deny değil: karar first-class bir action’dır, APPROVE, DENY ya da bir düzeltmeyi STEER etmek (burada refund’ı threshold’un altına indirmek), ve kullanıcıya bir clarifying question’ı geri yanıtlamak aynı mekanizmadır. Dördüncüsü, streaming progress: her step zaten bir journal event’i olduğundan, canlı bir feed aynı log’un üzerinde bir okumadan ibarettir, ve pause, karar ve resume hepsi onda görünür.

Ön koşullar

Temel Python yeterli: fonksiyonlar, bir dictionary, bir liste ve bir loop. Hepsi bu. Part 9 çok yardımcı olur, çünkü bu parça doğrudan onun iki fikrinin üzerine kurulu, state’in log’un üzerindeki fold olduğu append-only journal ve bir side-effect’i effectively-once kılan idempotency key, ama yazı kendi içinde bütünlüklü. Part 9’a yaslandığı yerde fikri tek bir cümleyle yeniden ifade eder ve journal’ı ya da ReAct loop’unu yeniden inşa etmez; bunlar Part 1 ve 9’a aittir ve burada referans verilir. Eşlik eden kod, pause_approve_resume.py, API anahtarı, ağ ve bağımlılık olmadan offline çalışır; böylece her satırı okuyup bu yazıdaki her trace’i kendiniz yeniden üretebilirsiniz. Timestamp’ler ve run id (run-aa10) donduruludur, dolayısıyla journal byte-reproducible’dır, gerçek LLM path’i (generate()) tek bir ortam bayrağı uzaklıkta, tam olarak Part 1’den 9’a kadarki gibi.

Part 9’dan beri yeni olan ne

Bir insan için duraklamanın kendi failure mode’larıyla kendi katmanı olduğu için, neyin yeni olduğu konusunda kesin olmak istiyorum. Part 9 durability ekledi, bir crash’ten ve bir recovery’den sağ çıkma yeteneği, ama durable bir ajan hâlâ yalnız çalışır: ya biter ya da crash edip kendini resume eder, ve hiçbir noktada bilerek durup bir kişiyi beklemez. Bu parça o bilerek durmayı ekler. Önceki serideki en yakın şey RAG Part 20’nin conversational ajanıydı, ama o farklı bir hayvan: turn’leri same-process’ti, bir kullanıcı bir follow-up gönderdi ve aynı canlı loop, baştan sona state RAM’de olacak şekilde devam etti. Gate yoktu, token yoktu, ikinci process yoktu. Ve RAG Part 19’un ajanının yalnızca read-only tool’ları vardı, dolayısıyla hiç onaya ihtiyaç duymadı, çünkü yaptığı hiçbir şey para hareket ettiremez ya da engellenmeye değer bir side-effect commit edemezdi. Burada gerçekten yeni olan, onay için cross-process pause ve resume ile mid-run steering, ve ikisi de durable territory, conversational territory değil. Pause, journal’a persist olan ve bir token döndüren gerçek bir kesintidir; resume ise ayrı bir act, muhtemelen ayrı bir process içinde, o journal’ı geri okuyan. Steer, pause ile resume arasında bir insan tarafından enjekte edilen bir düzeltmedir. Bunların hiçbiri daha önce yoktu. Bu parça Part 9’un journal’ını ve idempotency key’ini substrate olarak yeniden kullanır, onlara referans verir ve onları yeniden inşa etmez; yeni kod interrupt, resume ve bir düzeltme olabilen karardır.

Interrupt

Koşu güvenle gidebildiği kadar gider, ve sonra gate’te durur. İlk step, search_policy, read-only’dir ve onay gerektirmez, dolayısıyla çalışır ve sonucunu journal’a yazar. İkinci step refund’dır, ve $180.00, $100 threshold’unun üzerindedir, dolayısıyla ajan gate’e ulaşır ve refund tool’unu çağırmaz. Bunun yerine bir token ve pending action taşıyan bir pending_approval event’ini journal’a yazar ve bir PendingApproval raise eder. İşte pause, artefaktın gerçek çıktısından alıntılanmış:

    step 0 search_policy: Refunds after the window are refundable minus a 10% restocking fee.
    PAUSED: refund $180.00 exceeds the $100 threshold
    returned token 'appr-1'; the run is persisted, not dead. Ledger so far: (empty, no money moved yet)

Ne olup ne olmadığını oku. Step 0 çalıştı, policy text journal’da. Sonra gate, step 1’i payment provider’a dokunmadan önce durdurdu, ki ledger’ın (empty, no money moved yet) olmasının nedeni bu: para hareket etmedi, çünkü gate side-effect’ten önce kontrol edilir, sonra değil. Kritik tasarım seçimi persisted kelimesinde. Interrupt bir PendingApproval exception’ıdır, sys.exit değil. Bu göründüğünden daha önemli. sys.exit interpreter’ı yıkar, ki bu tek seferlik bir script için iyidir ama bir notebook’ta ya da uzun ömürlü bir server’da felakettir, soru sormak için process’i öldürmek saçmadır. En üst seviyede yakalanan serializable bir exception bunun tersini yapar: caller onu yakalar, journal’ı persist eder ve token’ı refund’ı isteyen kişiye döndürür. Koşu paused, not dead. Token 'appr-1', bir insanın daha sonra duran tam koşuyu resume etmek için zikredeceği handle’dır, ve diskteki pending_approval event’i pause’un onu raise eden process’ten sağ çıkmasını sağlayan şeydir. Journal üzerindeki stream aynı üç ritmi gösterir:

      > run started
      > done: Refunds after the window are refundable minus a 10% restocking fee.
      > PAUSED for approval (refund $180.00 exceeds the $100 threshold); token appr-1

O son satır pause’un tamamı, bir journal event’i olarak ifade edilmiş: bir crash değil, bir exit değil, koşunun nerede durduğunu ve hangi token’ın onu yeniden açacağını söyleyen kaydedilmiş bir waypoint.

Resume, effectively-once

Daha sonra bir insan karar verir. resume(run_id, decision) taze bir koşu başlatmaz; duraklatılmış olanı journal’ı replay ederek rehydrate eder, tam olarak Part 9 fold’u, kararı bir approval_decision event’i olarak kaydeder ve loop’a yeniden girer. Replay resume’u güvenli kılan şeydir: loop’a tam olarak hangi step’lerin zaten bittiğini, dolayısıyla onları yeniden yapmamasını ve hangi step’in hâlâ gate’te beklediğini söyler. Approve path’ini izle, artefaktın gerçek çıktısından alıntılanmış:

    [human] decision = approve
    step 0 search_policy: memoized -> 'Refunds after the window are refundable minus a 10% restocking fee.'
    step 1 process_refund: refunded $180.00 to ORD-3300
    finished -> Refund of $180.00 for ORD-3300 is complete.
    ledger: {'ORD-3300': 180.0}

Part 9’dan iki mekanizma burada işi yapıyor. Step 0 memoized: journal üzerindeki fold onun kaydedilmiş sonucunu buldu, dolayısıyla resume search’ü yeniden çalıştırmadan memoized -> 'Refunds after the window...' döndürdü. Sonra step 1 gerçekten çalışır, refund post edilir, refunded $180.00 to ORD-3300, koşu biter, ve ledger {'ORD-3300': 180.0} okur, bir refund. Bunun resume iki kez çağrılsa bile güvenli olmasının nedeni, diyelim ki dengesiz bir ağdan sonra bir retry ya da approve’a tekrar tıklayan sabırsız bir operatör, Part 9’dan gelen idempotency key’dir. Gate’li refund key’ini pause boyunca korudu, dolayısıyla ikinci bir onaylanmış resume provider’ın zaten honor ettiği bir key’e çarpar ve tekrar charge etmek yerine orijinal sonucu geri alır. İşte bir insan pause’u boyunca taşınan effectively-once budur: refund kararı bir retry’da yeniden verilebilir, ama effect tam olarak bir kez gerçekleşir. Pause Part 9’un garantisini zayıflatmadı; onu miras aldı. Diagram 1 iki fazı izler, token’ı journal’a yazan interrupt ve replay edip action alan resume.

A two-phase diagram. Phase one, labelled INTERRUPT, shows a run lane: a box run_started, then step 0 search_policy with a green check and the result Refunds after the window are refundable minus a 10 percent restocking fee, then step 1 process_refund ORD-3300 180 dollars reaching a gate drawn as a barrier labelled threshold 100 dollars, 180 over threshold. At the gate the lane forks down to a journal row pending_approval with token appr-1 and the pending action, and an exception symbol labelled raise PendingApproval, caught at top level, NOT sys.exit. A side note reads ledger empty, no money moved, run paused not dead, token returned to caller. Phase two, labelled RESUME, shows a human icon choosing a decision that becomes an approval_decision journal event, an arrow into a replay box that folds the journal, step 0 shown greyed and labelled memoized, no re-run, then step 1 process_refund executing with the same idempotency key labelled effectively-once even if retried, ending in refunded 180 dollars to ORD-3300, finished, and a ledger reading ORD-3300 equals 180 dollars. A caption strip reads: pause journals a token and raises, resume replays and acts, the key makes it effectively-once.
Fig 1 The interrupt and resume across the journal. In phase one the agent runs step 0 search_policy, journals its result, then reaches the gated refund of 180 dollars which is over the 100 dollar threshold. Instead of calling the refund tool it journals a pending_approval event carrying the token appr-1 and the pending action, and raises a serializable PendingApproval that is caught at the top level. The caller persists the journal and returns the token; the ledger is empty because no money moved, and the run is paused, not dead, because this is an exception and not sys.exit. In phase two a human calls resume with the run id and a decision; resume replays the journal, finds step 0 already complete and returns its memoized result without re-running the search, records an approval_decision event, then executes the gated refund. Because the refund kept its idempotency key from Part 9, an approved resume executes effectively-once even if retried, so the ledger ends at a single 180 dollar refund and the run finishes.

Karar bir action’dır: approve, deny, steer

İşte gerçek bir human-in-the-loop’u bir checkbox’tan ayıran kısım. Karar ikili bir gate değildir. First-class bir action’dır, ve ajan APPROVE, DENY ve STEER’ı insanın yapabileceği üç farklı şey olarak ele alır. Approve’u az önce gördük. Deny temiz reddir: insan hayır der, ve koşu hiç para hareket etmeden biter, artefaktın gerçek çıktısından alıntılanmış:

    [human] decision = deny
    step 0 search_policy: memoized -> 'Refunds after the window are refundable minus a 10% restocking fee.'
    step 1 process_refund: DENIED by approver -> no money moved
    ledger: (empty)

DENIED by approver -> no money moved, ve ledger (empty) kalır. Bu ikili yarısı, ve çoğu sistem orada durur. Ama ikili bir gate, ajan neredeyse haklı olduğunda kötü bir seçimi dayatır: refund haklı ama tutar yanlış, ve approve fazla öderken deny kimseye yardım etmez. Steer üçüncü seçenektir, ve ilginç olan da o. Onaylayan kişi yalnızca evet ya da hayır demez; ajanın bir sonraki adımda ne yapacağını değiştiren bir düzeltme enjekte eder. Burada refund’ı $180.00’dan $90.00’a indirirler, ki bu onu threshold’un altına düşürür, ve ajan sonra düzeltilmiş action’ı gerçekleştirir, artefaktın gerçek çıktısından alıntılanmış:

    [human] decision = steer (correction: $90.00)
    step 0 search_policy: memoized -> 'Refunds after the window are refundable minus a 10% restocking fee.'
    step 1 process_refund: STEERED by approver -> amount lowered to $90.00 (now under the $100 threshold)
    step 1 process_refund: refunded $90.00 to ORD-3300
    finished -> Refund of $90.00 for ORD-3300 is complete.
    ledger: {'ORD-3300': 90.0}

Step 1 için iki satırı oku. Önce STEERED by approver -> amount lowered to $90.00 (now under the $100 threshold), düzeltme uygulandı; sonra refunded $90.00 to ORD-3300, düzeltilmiş action gerçekleştirildi; ve ledger {'ORD-3300': 90.0} okur. İnsan yanlış şeyi onaylamadı ya da gerekli bir refund’ı reddetmedi; onu koşu ortasında düzeltti ve ajanın doğru şeyi bitirmesine izin verdi. Kararın first-class bir action olmasının önemi bu yüzden: bir düzeltme yalnızca ikiliden daha zengin bir gate’in taşıyabileceği bir şeydir. Ve mekanizma paranın ötesine genelleşir. Kullanıcıya bir clarifying question sormak için duraklayan bir ajan tam olarak aynı şeyi yapıyor, bir pause’u journal’a yazıyor, kontrolü geri veriyor ve insanın cevabı planına bir düzeltme olarak enjekte edilmiş şekilde resume ediyor. Onay, ret, steering ve bir clarifying question, dört şapka takan tek bir mekanizmadır. Diagram 2 gate’i üç yönlü bir branch olarak ortaya koyar, ve aşağıdaki interaktif figür üç çözümün hepsini canlı journal ve ledger’a karşı sürmenizi sağlar.

A diagram of an approval gate drawn as a single paused node branching three ways. At the top, a box reads PAUSED: refund 180 dollars exceeds the 100 dollar threshold, token appr-1, with a small human icon labelled approver decides. Three labelled arrows fan out below. The first, APPROVE, leads to a box reading execute unchanged, refunded 180 dollars to ORD-3300, with a ledger chip showing ORD-3300 equals 180 dollars. The second, DENY, leads to a box reading DENIED by approver, no money moved, with a ledger chip showing empty. The third, STEER, leads to a two-step box: first amount lowered to 90 dollars, now under the 100 dollar threshold, then refunded 90 dollars to ORD-3300, with a ledger chip showing ORD-3300 equals 90 dollars. A side note next to STEER reads a correction, not a yes or no; same mechanism as answering a clarifying question. A caption strip reads: the decision is a first-class action, approve, deny, or steer a correction, never just a binary gate.
Fig 2 The approval gate as a three-way decision, not a binary switch. The agent reaches a gated refund of 180 dollars that is over the 100 dollar threshold and pauses with token appr-1. A human resolves the pause one of three ways. APPROVE executes the gated action unchanged: refunded 180 dollars to ORD-3300, ledger 180 dollars. DENY refuses cleanly: DENIED by approver, no money moved, ledger empty. STEER injects a correction rather than a yes or no: the approver lowers the amount to 90 dollars, now under the threshold, the agent applies the correction and then executes it, refunded 90 dollars to ORD-3300, ledger 90 dollars. The point is that the decision is a first-class action: a binary gate forces approve the wrong amount or deny a needed refund, while steering lets a human fix the action mid-run. Answering a clarifying question back to the user is the same mechanism, a pause resolved by an injected correction.

Open figure ↗

Fig 3 Pause, approve, resume, and steer, interactive. Run the refund task until it hits the approval gate and pauses with token appr-1 and an empty ledger because no money has moved, then resolve the pause three ways and watch the journal and ledger respond. APPROVE replays the journal, memoizes step 0 search_policy without re-running it, and executes the gated refund effectively-once via its idempotency key, finishing with the ledger at 180 dollars for ORD-3300. DENY records the decision and finishes with DENIED by approver, no money moved, and an empty ledger. STEER injects a correction that lowers the refund to 90 dollars under the 100 dollar threshold, applies it, and executes the corrected refund, finishing with the ledger at 90 dollars. The figure shows the interrupt journaling a token and raising a serializable PendingApproval rather than calling sys.exit, the resume replaying the same journal Part 9 built, and the decision being a first-class action that can approve, deny, or steer, with the idempotency key making an approved resume safe to retry.

Journal’dan streaming

Part 9’da her step’i bir journal event’i yapmış olmanın sessiz bir getirisi var. Canlı bir progress feed’i inşa etmek hiçbir ekstra maliyet getirmez, çünkü o yalnızca koşuyu durable kılan aynı log üzerinde bir okumadır. Pause bir event’tir, karar bir event’tir, resume’un sonuçları event’lerdir, dolayısıyla streaming state’i yeniden inşa eden değil, onları geldikçe yazdıran bir fold’dur. İşte steer timeline’ı, pause ve düzeltmesi dahil bir koşunun tüm yaşamı, artefaktın gerçek çıktısından alıntılanmış:

      > run started
      > done: Refunds after the window are refundable minus a 10% restocking fee.
      > PAUSED for approval (refund $180.00 exceeds the $100 threshold); token appr-1
      > human decision: steer
      > done: refunded $90.00 to ORD-3300
      > finished: Refund of $90.00 for ORD-3300 is complete.

Yukarıdan aşağı oku ve o koşunun tüm hikayesidir: başladı, search bitti, token appr-1 ile onay için duraklattı, bir insan onu steer etti, $90.00’lık düzeltilmiş refund geçti, ve bitti. Bu feed’i tail eden bir izleyici ajanın durduğunu görür, insanın müdahale ettiğini görür ve tekrar devam ettiğini görür, hepsi bir crash’ten sonra yeni bir process’in koşuyu resume etmesini sağlayacak aynı event’lerden. Durability ve observability iki şekilde okunan aynı log’dur: onu bir process’e replay et resume alırsın, bir ekrana replay et stream alırsın. Her step’i yazıya dökmenin anlamı, onu yalnızca bir kez yazman gerekmesidir.

Process’ler arasında

Cross-process hikayesi konusunda dürüst olmak istiyorum, çünkü tek dosyalık demo yanıltabilir. Gerçek bir deployment tek bir nefeste pause edip resume etmez. Onay gate’ine çarpan request token’ı döndürür ve biter, bir process içinde; koşu artık journal’da oturuyor, duraklatılmış. Bir süre sonra, bir insan ona gerçekten baktıktan sonra, farklı bir process içinde, daha sonraki bir web request’i ya da bir CLI re-invocation’ı, resume o token’la aynı journal üzerinde çağrılır, ve koşu durduğu yerden devam eder. İki faz zamanda ve process’te gerçekten ayrılmıştır, ve onları bağlayan tek şey durable log ve duraklatılmış koşuyu adlandıran token’dır. Bu dosyadaki demo her iki fazı tek bir programda modeller, PendingApproval’ı yakalayarak, dünyayı persist ederek ve sonra o persist edilmiş dünya üzerinde resume çağırarak, böylece tüm yayı tek bir trace’te izleyebilirsin. Bu bir kısayol değil, sadık bir modeldir: resume gerçekten journal’ı in-memory bir değişkene güvenmek yerine baştan replay eder, ki bu tam olarak ikinci bir process’in yapmak zorunda olacağı şeydir. CLI iki-process versiyonu aynı fikrin literal hali, duraklatıp journal’ı yazan ilk invocation, o journal’ı okuyup resume eden ikinci invocation. Tek dosya timeline’ı okunabilirlik için sıkıştırır; durable log, sıkıştırmayı geri açmayı güvenli kılan şeydir.

💡 Deneyimden. Bir onay gate’i bir keresinde beni gerçekten kötü bir günden kurtardı. Refund işleyen bir ajanımız vardı, ve bozuk bir upstream kaydı, bir müşterinin makul herhangi bir şeyden kabaca iki kat büyüklük mertebesinde daha büyük bir refund’a hak kazandığına karar vermesine yol açtı. Post edilmemesinin tek nedeni aptal bir threshold’du: birkaç yüz dolardan fazla herhangi bir şey duraklatıp bir insan kuyruğuna ping atıyordu. Onu ele aldım, sayıyı gördüm, ve onaylamak ya da reddetmek yerine üçüncü şeyi yaptım, onu doğru tutara steer ettim ve bitmesine izin verdim, çünkü müşteri bir refund’a hak kazanmıştı, sadece o refund’a değil. Gate ikili olsaydı, meşru bir refund’ı reddedip manuel bir ticket başlatmak ya da bir fraud review ve bir clawback tetikleyecek bir sayı onaylamak zorunda kalacaktım. Steer, neredeyse bir incident’i otuz saniyelik bir düzeltmeye dönüştürdü. Diğer ders, hiç pause’u olmayan daha eski bir sistemdeki tersi hatadan geldi: bir ajan koşu ortasında raydan çıktığında tek aracımız process’i öldürüp sıfırdan restart etmekti, ki bu zaten yaptığı iyi işi çöpe atıyor ve side-effect’leri yeniden yapma riskini taşıyordu. Bir koşuyu durdurabilmek, onu tekrar raya sokabilmek ve tam duraklattığı yerden resume edebilmek, öldürüp restart etmek yerine, bir arabayı sürmek ile sıfırdan başlamak için onu yoldan dışarı itmek arasındaki farktır.

Özet / Çıkarımlar

  • Part 9’un durable ajanı bir crash’ten sağ çıkar ama hâlâ yalnız çalışır, durup sormanın bir yolu yoktur. Gerçek deployment’lar eksik olduğu iki şeye ihtiyaç duyar: gate’li bir action’dan önce onay (bir $100 threshold’unun üzerinde bir $180.00 refund) ve ajanın koşu ortasında düzeltilmesi, ve ikisi de koşunun duraklayıp kontrolü bir insana devretmesini gerektirir.
  • interrupt() bir token’la birlikte bir pending_approval event’ini journal’a yazar ve en üst seviyede yakalanan serializable bir PendingApproval raise eder, sys.exit değil, böylece caller journal’ı persist eder ve token’ı ('appr-1') döndürürken ledger (empty, no money moved yet) kalır. Koşu paused, not dead, dolayısıyla notebook’lar ve server’lar çalışabilir halde kalır.
  • resume(run_id, decision) journal’ı replay eder (Part 9’un fold’u), zaten bitmiş search_policy step’ini memoize eder, kararı kaydeder ve devam eder. Gate’li refund idempotency key’ini korur, dolayısıyla onaylanmış bir resume retry edilse bile effectively-once çalışır: refunded $180.00 to ORD-3300, ledger {'ORD-3300': 180.0}.
  • Karar first-class bir action’dır, ikili bir gate değil: DENIED by approver -> no money moved (ledger empty), ya da STEERED by approver -> amount lowered to $90.00 sonra refunded $90.00 to ORD-3300 (ledger {'ORD-3300': 90.0}). Steer bir düzeltme enjekte eder; kullanıcıya bir clarifying question’ı geri yanıtlamak aynı mekanizmadır.
  • Streaming aynı log üzerinde bir okumadır. Steer timeline’ı (run started, done, PAUSED for approval ... token appr-1, human decision: steer, done: refunded $90.00, finished) yalnızca koşuyu zaten durable kılan journal event’leri üzerinde bir fold’dur. Her step’i bir kez yaz ve hem resume hem de canlı bir feed elde edersin.
  • Cross-process, dürüstçe: gerçek bir deployment bir process içinde pause eder (request token’ı döndürür) ve başka birinde resume eder (daha sonraki bir request ya da CLI re-invocation’ı) aynı journal üzerinde. Tek dosyalık demo her iki fazı PendingApproval’ı yakalayıp sonra persist edilmiş dünya üzerinde resume çağırarak modeller, ki bu sadıktır çünkü resume RAM’e güvenmek yerine baştan replay eder.

Sözlük

  • Human-in-the-loop: ajanın tam otonom çalışmak yerine belirli noktalarda bilerek durup bir kişinin yapmak üzere olduğu şeyi onaylamasına, reddetmesine ya da düzeltmesine izin verdiği bir tasarım; burada Part 9’un journal’ı üzerine kurulu, böylece pause process’ten sağ çıkar.
  • Approval gate / threshold: side-effect üreten bir action’dan önce bir policy check’i (burada $100’ün üzerindeki refund’lar) ki insan onayı gerektirir; gate effect’ten önce kontrol edilir, ki bir duraklatılmış refund’ın ledger’ı boş, para hareket etmemiş bırakmasının nedeni budur.
  • interrupt(): gate’li bir action’a ulaşma, bir token ve pending action’la bir pending_approval event’ini journal’a yazma ve tool’u çağırmak yerine PendingApproval raise etme act’ı; koşuyu duraklatır ve kontrolü caller’a devreder.
  • PendingApproval (serializable, sys.exit değil): interrupt’ın raise ettiği exception, token’ı, pending action’ı ve nedeni taşıyan; en üst seviyede yakalanır, böylece caller journal’ı persist eder ve token’ı döndürür. Bilerek sys.exit değildir, böylece bir notebook ya da server duraklatılır, öldürülmez.
  • Token: bir koşu duraklatıldığında döndürülen handle (burada 'appr-1'); bir insan daha sonra duran tam koşuyu resume etmek için onu zikreder, ve pending_approval journal event’ine kaydedilir, böylece pause process’ten sağ çıkar.
  • resume(run_id, decision): duraklatılmış bir koşuyu journal’ını replay ederek (Part 9’un fold’u) rehydrate etmek, bir approval_decision event’i kaydetmek ve karara göre action almak için loop’a yeniden girmek; bitmiş step’ler memoize edilir, böylece yalnızca gate’li step çalışır.
  • Steer (first-class karar): ikili bir evet ya da hayır yerine bir düzeltme enjekte eden (burada refund’ı threshold’un altında $90.00’a indiren) bir insan kararı; ajan düzeltmeyi uygular ve düzeltilmiş action’ı gerçekleştirir. Kullanıcı tarafından yanıtlanan bir clarifying question aynı mekanizmadır.
  • Streaming progress: journal event’lerini eklendikçe okuyarak üretilen canlı bir feed; durability zaten her step’i kaydettiğinden, pause, karar ve resume stream’de bedavaya görünür.
  • Part 9’u yeniden kullanır: append-only journal ve idempotency key Part 9’dan miras alınır, yeniden inşa edilmez; journal pause ve resume’u durable kılar, ve key onaylanmış bir resume’u retry edilse bile effectively-once kılar.

Bu parçanın kuralı: durable bir ajan tam otonom çalışmak ile hiç çalışmamak arasında seçim yapmak zorunda kalmamalı, çünkü bazı action’lar bir insan gerektirir ve bazı koşular uçuş ortasında düzeltilmeyi gerektirir. Journal’ı koşunun durabileceği bir yere çevir: gate’li bir action’da, bir token’ı journal’a yaz ve sys.exit yerine serializable bir PendingApproval raise et, böylece koşu duraklatılır ve token döndürülür, öldürülmez (interrupt). Bir insanın o journal’ı replay edip karara göre action alarak daha sonra karar vermesine izin ver, idempotency key onaylanmış bir retry’ı güvenli kılarak (resume, effectively-once). Kararı first-class bir action yap, böylece bir kişi yalnızca ikili bir switch’i çevirmek yerine approve, deny ya da bir düzeltmeyi steer edebilsin. Ve progress’i bedavaya stream et, çünkü o aynı journal’ın bir ekrana okunmasıdır. Ama hâlâ iyi yapamadığımız şeye dikkat et: bu koşulardan biri production’da pause, resume, steer ve side-effect’ler boyunca yanlış gittiğinde, elle okuyabileceğimiz bir journal’a ve fazla bir şeye sahip değiliz. İçini göremediğin bir durable ajan undebuggable’dır, ve “JSONL’i elle oku” gerçek bir incident’le temasta hayatta kalmaz. Part 11, The Observable Agent, core capstone’dur: bu aynı journal’ı gerçek tracing için OpenTelemetry şeklindeki span’lere fold et, ham token sayıları yerine cost-per-success ölç, ve inşa ettiğimiz ajanı gerçekten operate edebileceğin birine dönüştür.

AgentsHuman-in-the-LoopApprovalsDurabilitySteeringAI