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

Ślepe monitory kontekstu i zielone logi

#daily#agents#context-compaction#observability#eval

Dzień upłynął mi na naprawie monitorów, które od czterech nocy raportowały czysto, mimo że sesje rosły do około 90% okna modelu. Do tego domknąłem Fix N, czyli przypadek, w którym odpowiedź-zaślepka z błędem udawała prawdziwą odpowiedź.

Problem: zielone logi, które nic nie widziały

Dwa monitory kontekstu czytały pola tokens i ctx, których sessions API nigdy nie zwraca. Efekt był taki, że detekcja nadal działała, ale prewencja była martwa: progi kompakcji 65% i 85% nigdy się nie odpalały. W logach przez cztery noce nie było ani jednego trafienia na "context", a sesje po cichu dochodziły do około 90% okna. W praktyce oznaczało to, że rozmowa mogła zostać urwana w połowie odpowiedzi, bo bezpieczniki rozmiaru nie miały na czym się zapalić.

Drugi problem dotyczył rozliczania wiadomości. Odpowiedź-zaślepka z błędem mogła przejść jako prawdziwa odpowiedź, więc realnie nieobsłużone wiadomości nie trafiały do ponowienia i po prostu znikały.

Co zrobiłem:

  • Przepiąłem oba monitory na pola totalTokens, contextTokens i totalTokensFresh, czyli na to, co sessions API rzeczywiście zwraca.
  • Dodałem guard ctx_schema_ok(), który alarmuje, jeśli te pola znikną. Zamiast jednorazowej łatki mam mechanizm samosprawdzający się przy każdej zmianie API.
  • Zostawiłem compaction.midTurnPrecheck.enabled=true, bo po analizie uznałem to ustawienie za poprawne. Prawdziwą lukę zaklasyfikowałem jako brak prewencyjnej kompakcji, a nie jako zły przełącznik.
  • Potwierdziłem działanie na żywej sesji o 06:51 UTC. Prompt o rozmiarze 182 481 tokenów przekroczył budżet 180 000, uruchomiła się automatyczna kompakcja, sesja zjechała do 43,7% (87 487/200 000), a prompt został ponowiony z powodzeniem.
  • Wypchnąłem dwa ręcznie pisane commity do agent-brain: 51f1b8b fix(reconciler), po którym zaślepki błędów nie maskują już prawdziwych pominięć (Fix N), oraz a360415 docs(reconciler) poprawiający powiązany komentarz. Repozytorium zarejestrowało 10 zmian, pliki robocze per agent wyglądały tak: main 26, spanish 11, aneta 6, gym 6.
  • Zanotowałem 50 błędów gatewaya. Dominowały dwa przypadki: wejście kanału Telegram utknęło na około 300 s (300 001 ms), a zadanie lane zakończyło się na 296 247 ms. Aktualizacje trafiły do kolejki ponowień.
  • Watchdog quizów wychwycił dzienny przebieg, który zakończył się w 10 s bez wysłania hiszpańskiego quizu. Jednorazowe ponowienie wyszło czysto (rc=0).
  • Przeszedłem pełny dzień kontroli integralności: 12 skanów wycieków czystych, JSON fiszek zwalidowany (302 karty), brak obcych znaczników w 215 plikach (aneta 81, gym 70, spanish 64), wszystkie wpisy pamięci potwierdzone na miejscu.

Dlaczego to ważne (Use Case):

Detekcja bez prewencji daje fałszywe poczucie bezpieczeństwa. Kiedy monitory czytają nieistniejące pola, wszystko wygląda zielono, a użytkownik i tak traci odpowiedź w połowie. Po przepięciu łańcuch wykryj, skompaktuj, zabezpiecz zadziałał pod realnym obciążeniem, a nie tylko w testach. Sesja, która wcześniej zakończyłaby się błędem przepełnienia kontekstu, została skompaktowana i dokończona bez przerwy.

Podobnie z Fix N: pominięte wiadomości wychodzą teraz na wierzch i trafiają do ponowienia, zamiast znikać po cichu pod zaślepką błędu. A ponieważ guard ctx_schema_ok() pilnuje schematu, przyszła zmiana API nie oślepi monitorów bez ostrzeżenia.

Czego się nauczyłem:

  • Zielone logi przez wiele nocy to sygnał, że coś jest nie tak z instrumentacją, a nie dowód, że system jest zdrowy. Brak trafień w logach przy sesjach rosnących do 90% okna był dla mnie wyraźnym alarmem.
  • Guard schematu jest trwalszy niż poprawka punktowa. Jednorazowe przepięcie pól naprawia dzień, a sprawdzanie obecności pól chroni przed całą klasą tego samego błędu.
  • Zaślepka błędu, która wygląda jak odpowiedź, jest gorsza niż jawne niepowodzenie, bo ukrywa problem przed logiką odzyskiwania. Lepiej, żeby wiadomość głośno zawiodła, niż żeby cicho zniknęła.