BlogAgenci AI
Jak sprawić, by agent nie wykonał tego samego działania biznesowego dwa razy
Nadaj każdemu działaniu biznesowemu klucz wyprowadzony z tego, czym jest działanie, a nie z próby. Frameworki agentowe potrafią zapisać postęp i wznowić pracę, ale nie sprawią, że wywołanie zewnętrznego API zadziała dokładnie raz. Tylko system, który faktycznie wywołuje skutek, może niezawodnie odrzucić powtórzenie: albo API docelowe deduplikuje żądania, albo sam kontrolujesz zapis i klucz w jednej transakcji. Warstwa przed zewnętrznym API, która nie robi żadnej z tych rzeczy, zmniejsza liczbę duplikatów, ale ich nie wyklucza, więc część wyników pozostaje niejasna i musi je rozstrzygnąć zadanie uzgadniające.
Pięć sposobów, w jakie agent powtarza działanie
- Ponowienie po timeoucie, choć pierwsze żądanie zostało już wykonane
- Model ponownie wywołuje narzędzie, bo nie zobaczył pierwszego wyniku albo mu nie ufał
- Odtworzenie przez framework: LangGraph przy wznowieniu uruchamia przerwany węzeł od początku, a odtworzenie od checkpointu ponownie uruchamia późniejsze węzły razem z wywołaniami API
- Kolejka dostarcza tę samą sprawę dwa razy albo podejmują ją dwa workery
- To samo zgłoszenie przychodzi dwa razy, na przykład faktura wysłana e-mailem i dodatkowo wgrana do portalu
Tylko ostatni przypadek to duplikat biznesowy, który wymaga reguł dziedzinowych. Pierwsze cztery to to samo działanie podjęte ponownie i klucz idempotencji obsługuje je wszystkie, jeśli pozostaje taki sam we wszystkich próbach.
Wyprowadź klucz z działania biznesowego
Losowa wartość generowana w chwili wywołania zmienia się przy każdej próbie modelu albo frameworka, więc chroni tylko przed najwęższym ponowieniem. Buduj klucz w kodzie ze stabilnych faktów: sprawy, rodzaju działania, jego celu i miejsca w sprawie. Model nigdy go nie wybiera.
import hashlib
import json
def action_key(case_id: str, action: str, target: str, step: int) -> str:
"""Same business action, same key, across retries, replays and restarts."""
# A JSON array keeps the fields apart: ("a|b", "c") and ("a", "b|c")
# produce different strings, which a plain "|".join would not.
canonical = json.dumps([case_id, action, target, step],
ensure_ascii=False, separators=(",", ":"))
return hashlib.sha256(canonical.encode("utf-8")).hexdigest()[:40]
# action_key("claim-88213", "create_payment", "payee:SUP-2291", 1)
# returns the same 40-character key every time it is called with these valuesPrzed haszowaniem zakoduj pola jednoznacznie. Łączenie dowolnych identyfikatorów separatorem, na przykład pionową kreską, pozwala dwóm różnym działaniom dać ten sam ciąg wejściowy, choćby wtedy, gdy identyfikator sprawy sam zawiera separator, a wtedy dostałyby ten sam klucz. To błąd kodowania, niezwiązany z kolizjami funkcji skrótu. Kanoniczna tablica JSON, jak powyżej, albo pola poprzedzone długością eliminują ten problem; separator jest bezpieczny tylko wtedy, gdy każdy identyfikator jest walidowany pod kątem tego, że nigdy go nie zawiera.
Haszowanie trzyma surowe wartości, takie jak dane bankowe, poza kluczem, ale nie czyni ich anonimowymi: hasz identyfikatora często da się z powrotem powiązać z osobą. Traktuj więc klucze i rejestr działań jako spseudonimizowane dane osobowe i uzgodnij sposób ich obsługi z inspektorem ochrony danych. Dokumentacja Stripe odradza na przykład używanie danych wrażliwych jako kluczy idempotencji. Numer kroku pozwala, żeby sprawa w uzasadniony sposób wykonała dwie podobne płatności, na przykład dwie raty, bez kolizji.
Egzekwować go musi strona odbierająca
Klucz, który system docelowy ignoruje, niczego nie chroni. Dla każdego narzędzia zapisującego sprawdź, z którą z trzech sytuacji masz do czynienia.
API obsługuje klucze idempotencji
Dokładnie przeczytaj zasady dostawcy, bo się różnią. API v1 Stripe przyjmuje na przykład klucze w żądaniach POST, zapisuje pierwszą odpowiedź łącznie z błędami 500, odrzuca ponownie użyty klucz z innymi parametrami i może usuwać klucze po co najmniej 24 godzinach. Te szczegóły dotyczą Stripe i nic nie mówią o twoim ERP. Polegaj tylko na gwarancjach, które dostawca dokumentuje, w tym na tym, jak długo przechowuje klucze i jak traktuje żądania równoległe albo nieudane.
Kontrolujesz ścieżkę zapisu
Jeśli narzędzie albo serwer MCP zapisuje do bazy, którą kontrolujesz, zapisz klucz, hasz parametrów i wynik w tej samej transakcji co zmianę. Artykuł z Amazon Builders' Library o idempotentnych API opisuje ten wzorzec: zapisz identyfikator żądania i zmianę atomowo, przy powtórzeniu zwróć równoważną odpowiedź, a ten sam identyfikator z innymi parametrami odrzuć. Działa to tylko dlatego, że klucz i zmiana są zatwierdzane razem. Narzędzie, które jedynie przekazuje wywołanie do zewnętrznego API, tego nie potrafi: jeśli zgubi odpowiedź, nie wie, czy skutek nastąpił.
Żadna z tych opcji nie jest możliwa
Użyj naturalnej unikalnej referencji, którą system docelowy już sprawdza, na przykład dostawca plus numer faktury, i przed zapisem odczytaj stan. Jeśli nawet to jest niedostępne, działanie wymaga człowieka albo trzeba zaakceptować sporadyczne duplikaty i je uzgadniać. Odczyt zmniejsza okno na duplikaty, ale go nie zamyka, bo pierwsze żądanie może wciąż być w toku. Sprawy, w których sprawdzenie nie rozstrzyga wyniku, trafiają do człowieka albo do uzgadniania.
Długie pauzy przeżywają krótko żyjące klucze
Przebiegi agentów mogą czekać na akceptację całymi dniami. Jeśli dostawca przechowuje klucze przez ograniczony czas, wznowienie po długiej pauzie może wypaść poza to okno. Prowadź własny rejestr działań ze stanami takimi jak oczekujące, wykonane i nieudane i przechowuj go co najmniej tak długo, jak sprawa może pozostać otwarta. Oczekujący wpis starszy niż przewidywany czas oznacza nieznany wynik: sprawdź system docelowy, zanim spróbujesz ponownie.
Uzgadniaj stan, potem testuj punkty awarii
Uruchamiaj regularnie zadanie, które porównuje rejestr działań z systemem docelowym: działania zapisane bez efektu, efekty bez zapisu i efekty występujące dwa razy. Duplikaty koryguje się procesem biznesowym właściwym dla danego działania, na przykład anulowaniem albo zwrotem, a wzorzec Compensating Transaction Microsoftu zaznacza, że takie kroki korygujące też muszą być idempotentne.
Potem testuj dokładnie punkty awarii: zatrzymaj proces po wywołaniu zewnętrznym, ale przed jakimkolwiek zapisem, wznów i sprawdź, że istnieje jeden rekord. Dostarcz tę samą sprawę jednocześnie do dwóch workerów. Dobry pierwszy krok to lista wszystkich narzędzi zapisujących z informacją, która z trzech sytuacji dotyczy każdego z nich.
Pytania
Czy durable execution nie zapobiega już duplikatom?
Nie. Checkpointy zapisują postęp samego agenta, żeby przebieg mógł zostać wznowiony. Nie mogą wiedzieć, czy system zewnętrzny wykonał wywołanie wysłane tuż przed awarią, a wznowione albo odtworzone kroki mogą wywołać je ponownie.
Czy możemy użyć identyfikatora wywołania narzędzia z modelu jako klucza?
Identyfikuje pojedyncze wywołanie, więc nowe wywołanie przez model albo odtworzony krok zwykle ma inny identyfikator. Zamiast tego użyj klucza zbudowanego z działania biznesowego.
A co z działaniami, których nie da się uczynić idempotentnymi, jak wysłanie e-maila?
Zapisz zamiar wysyłki we własnej tabeli pod kluczem działania i pozwól osobnemu nadawcy dostarczyć każdy wpis raz. Po awarii w niefortunnym momencie wciąż może się zdarzyć rzadki duplikat, więc zdecyduj, czy dla danego typu wiadomości jest to do przyjęcia.
Powiązane usługi
Więcej z bloga
Gdy narzędzia agenta zawodzą
Co powinien zrobić agent procesowy, gdy API przekracza limit czasu albo narzędzie zwraca niepełne dane: typowane błędy, ograniczone ponowienia i czyste przekazanie.
Akceptacja człowieka w workflow agentów
Które działania agenta na rekordach biznesowych wymagają akceptacji człowieka, co musi zobaczyć akceptujący i jak sprawić, by akceptacje nie blokowały każdej sprawy.
Wersjonowanie agenta procesowego
Co wymaga wersji, gdy zmienia się agent procesowy, jak oznaczać nią każdą sprawę i jak po miesiącach wyjaśnić wynik bez ponownego uruchamiania.
Porozmawiaj z inżynierem
Przyjdź z jednym zadaniem, które chcesz usprawnić. Rozmowa trwa 30 minut i nie wymaga dostępu do twoich systemów ani danych.
Rezerwacja odbywa się w Kalendarzu Google.
Wolisz najpierw napisać? Zostaw adres e-mail i kilka zdań, a odpowiemy, proponując terminy.
Sprawdź wersję roboczą w swoim programie pocztowym
Wyślij ją stamtąd, a inżynier odpowie ci osobiście, proponując terminy 30-minutowej rozmowy. Jeśli wersja robocza się nie otworzyła, napisz do nas na adres miki@cloudsail.com.