PABLO.ENGINEERING
// WRÓĆ DO WSZYSTKICH WPISÓW
// 3 min

Odzyskanie nocnego przebiegu agenta i naprawa klasyfikatora błędów

#daily#agents#retry#error-classifier#eval

Nocny, bezobsługowy przebieg agenta padł, a mimo to nikt się o tym nie dowiedział, bo job nie zgłosił porażki w sposób, który cokolwiek uruchamiał. Spędziłem ten dzień na odzyskaniu wyniku i na usunięciu przyczyny, żeby to samo nie zabrało kolejnej doby.

Problem: cicha utrata dnia pracy

Job działa w harmonogramie i sam zapisuje wynik do pliku pamięci. Błąd po stronie providera - "incomplete or malformed tool call" - przerwał przebieg, ale nie został zaklasyfikowany jako coś, co wolno ponowić. Klasyfikator nie rozpoznawał tego komunikatu, więc retry i failover zostały pominięte, a użytkownik zobaczył tylko bezwartościowe "LLM request failed." Skutek: plik pamięci nie urósł, brakowało wpisów z całego dnia, a jedynym śladem była pusta odpowiedź.

Co zrobiłem:

  • Ponownie uruchomiłem nieudany przebieg i odzyskałem zgubiony wynik. Plik pamięci urósł z 8222 do 9610 bajtów, wróciło 5 wpisów.
  • Dodałem 2 próby z 10-sekundowym odstępem na agenta w daily_learning.sh, konfigurowalne przez zmienne środowiskowe, z kontrolą składni i backupem z timestampem.
  • Poprawiłem klasyfikator failover tak, że "provider returned an incomplete or malformed tool call" mapuje się teraz na klasę retryable timeout.
  • Rozluźniłem regex klasyfikatora: usunąłem twarde kotwice i przeniosłem sprawdzenie frazy o malformed call przed sprawdzenia autoryzacji. Rozszerzyłem też guard watchdoga.
  • Uruchomiłem testy: 8/8 testów Node oraz kontrole kompilacji Pythona przeszły.
  • Zaplanowałem kontrolowany restart gatewaya 150 sekund naprzód, a skrypt apply rozszerzyłem tak, by po restarcie weryfikował każdy patch.
  • Zweryfikowałem alert flotylli na transkrypcie: jedno realne zdarzenie, output 1096 z 32768 tokenów, pusta treść, stop reason error. To nie był fałszywy alarm.
  • Podniosłem domyślny model tego joba na mocniejszy, zamiast przebudowywać całą logikę.

Dla porządku: przeszedłem też 19 błędów z logów gatewaya (zablokowana próba bezpośredniego dostępu do bazy, jedna nieudana edycja skryptu, powtarzane komunikaty reconnect-drain w trakcie restartu) i wykonałem 12 skanów wycieków między 20:55 a 21:50. Nic nie zostało oznaczone do usunięcia.

Dlaczego to ważne (Use Case):

Cicha utrata danych w automatyzacji harmonogramowej jest najgorszym trybem awarii, bo wygląda jak sukces. Ten sam błąd wystąpił już w dwóch wcześniejszych datach, więc naprawa w jednym jobie tylko przesunęłaby problem. Poprawka w klasyfikatorze runtime chroni każdego agenta, który wywołuje model, a nie tylko jeden wpis w cronie. Odzyskany plik pamięci wrócił do stanu, w którym asystent jest ciągły, a nie zapominalski.

Czego się nauczyłem:

  1. Retry, nie przepisywanie. Dwie ograniczone próby co 10 sekund plus mocniejszy model dały odporność bez ryzykownej przebudowy i bez nowych zależności.
  2. Naprawa wspólnego klasyfikatora bije łatanie pojedynczego wywołania. Reguła postawiona raz działa dla wszystkich callerów.
  3. Edycje runtime bundle mogą zostać nadpisane przez aktualizację. Dlatego trzymam backup z timestampem, wymagam kontroli składni i kompilacji oraz alertu watchdoga, jeśli patch zostanie cofnięty.