Agent kończy, ale zadania nie wykonał

przez Łukasz | sie 24, 2026

Objawy

Agent odpowiada: „Przygotowałem i wysłałem potwierdzenie do klienta.” Potwierdzenie nie zostało wysłane.

Albo: „Zaktualizowałem wszystkie rekordy” — zaktualizował trzy z dwunastu. Albo: „Nie znalazłem żadnych zamówień” — bo narzędzie zwróciło błąd, którego nikt nie przekazał.

Cecha wspólna: nic w odpowiedzi nie sygnalizuje problemu. Zdanie o wysłaniu brzmi identycznie jak przy realnej wysyłce.

Objaw systemowy, po którym poznasz to najszybciej: metryki pokazują niemal sto procent sukcesów. Jeśli twój agent nigdy nie zawodzi, prawdopodobnie nie mierzysz wykonania zadania, tylko zakończenie pętli.

Mechanizm w trzech zdaniach

Model nigdy się nie dowiaduje, czy cokolwiek naprawdę się wykonało. Widzi wyłącznie, że w kontekście pojawił się nowy tekst — a czy pochodzi on z realnego wywołania, z atrapy, czy z komunikatu błędu, jest dla niego nierozróżnialne.

Zdanie „wysłałem potwierdzenie” nie jest więc raportem, tylko prawdopodobną kontynuacją. Model przewiduje, co zwykle następuje po takim ciągu zdarzeń. Pełne wyjaśnienie: Gdzie kończy się model.

Diagnostyka różnicowa

1. Zakończenie wymuszone podane jako wynik

Jak rozpoznać: przebieg dobił do limitu kroków, budżetu albo czasu, a pętla zwróciła to, co miała, bez adnotacji.

Dlaczego to boli: agent przerwany limitem też coś zwróci — najczęściej odpowiedź niepełną, sformułowaną równie pewnie jak każda inna. Jeśli pętla nie odróżnia zakończenia normalnego od wymuszonego, system nadrzędny traktuje jedno i drugie tak samo.

Test: czy w śladzie jest pole z powodem zakończenia? Jeśli nie, to jest pierwsza rzecz do dopisania.

2. Model raportuje intencję jako fakt

Jak rozpoznać: w odpowiedzi jest „wysłałem”, a w śladzie nie ma odpowiadającego wywołania narzędzia.

Dlaczego się dzieje: model zaplanował krok i opisał go w czasie przeszłym, zamiast poprosić o wywołanie. To najczystsza postać tego syndromu i najłatwiejsza do automatycznego wykrycia — sposób w aneksie.

3. Narzędzie zwróciło sukces przy nieudanej operacji

Jak rozpoznać: wywołanie jest, status techniczny poprawny, a operacja się nie wydarzyła.

Dlaczego się dzieje: API odpowiada dwusetką z komunikatem o błędzie w treści. Kolejka przyjęła zadanie, ale go nie przetworzyła. Zapis trafił do transakcji, która została wycofana.

Test: sprawdź w systemie docelowym, czy skutek istnieje. To jedyny wiarygodny test.

4. Cichy wyjątek przechwycony w kodzie

Jak rozpoznać: w kodzie narzędzia jest except, który zwraca wartość domyślną.

Dlaczego się dzieje: ktoś zabezpieczył się przed wywróceniem pętli i przy okazji zamienił awarię w wynik. Model dostał coś, co wygląda jak odpowiedź.

Test: przejrzyj obsługę wyjątków w narzędziach pod kątem tego, czy błąd dociera do modelu jako błąd.

5. Odrzucenie walidacji niezakomunikowane

Jak rozpoznać: w logu pętli jest odrzucenie, w kontekście modelu nie ma po nim śladu.

Dlaczego się dzieje: to ta sama przyczyna, która przy zapętleniu prowadziła do powtórzeń. Tutaj model zamiast powtarzać, uznaje krok za wykonany i idzie dalej.

6. Wynik częściowy podany jako pełny

Jak rozpoznać: narzędzie zwróciło stronicowany wynik, agent przetworzył pierwszą stronę.

Dlaczego się dzieje: odpowiedź nie mówi jasno, że to fragment. Pole total bez pola has_more nie jest sygnałem, który model rozpozna.

7. Zadanie było niewykonalne

Jak rozpoznać: agent próbował kilku dróg, żadna nie mogła zadziałać, a odpowiedź i tak brzmi jak sukces.

Dlaczego się dzieje: model musi coś zwrócić. Zakończenie brzmiące na udane jest prawdopodobniejszą kontynuacją niż przyznanie się do niemożności — zwłaszcza po treningu premiującym pewność.

8. Niejednoznaczny wynik odczytany jako sukces

Jak rozpoznać: narzędzie zwróciło coś w rodzaju {"przetworzono": 0} albo {"status": "pending"}.

Dlaczego się dzieje: zero przetworzonych rekordów to formalnie poprawna odpowiedź. Model odczytuje ją jako „operacja się udała”, bo nie było błędu.

Postępowanie

Natychmiast: zwracaj powód zakończenia razem z odpowiedzią. Cztery możliwe wartości — model odpowiedział, limit kroków, limit budżetu, wykryte zapętlenie — i tylko pierwsza oznacza, że zadanie prawdopodobnie zostało wykonane. To zmiana na kilkanaście linii, która natychmiast urealnia metryki.

Potem: przestań mierzyć zakończenie pętli, zacznij mierzyć skutek. Metryka „agent zakończył” zawsze pokaże niemal sto procent. Metryka „operacja istnieje w systemie docelowym” pokazuje prawdę.

Weryfikuj deklaracje modelu wobec śladu. Jeśli odpowiedź mówi o wykonanej operacji, a w śladzie nie ma odpowiadającego wywołania ze skutkiem — to przyczyna druga i da się ją wychwycić automatycznie.

Popraw narzędzia, żeby zwracały jednoznaczny status. Rozdziel „wykonano” od „przyjęto do wykonania”. Przy wyniku stronicowanym powiedz wprost, że to fragment. Przy zerze przetworzonych rekordów napisz, dlaczego zero.

Nie ufaj deklaracji, ufaj wynikom narzędzi. To jest zasada, która porządkuje cały ten syndrom: źródłem prawdy o tym, co się wydarzyło, jest ślad wywołań, nigdy zdanie w odpowiedzi.

Profilaktyka

Kryteria akceptacji zadania zdefiniowane osobno od zakończenia pętli. Dla „odpowiedz klientowi” kryterium brzmi „istnieje wysłana wiadomość powiązana z identyfikatorem przebiegu”, nie „agent zakończył bez błędu”.

Ślad przebiegu z powodem zakończenia, liczbą kroków i liczbą wykonanych operacji ze skutkiem ubocznym — czyli to, co opisuje artykuł o logowaniu.

Przy zadaniach o wysokiej stawce — weryfikacja po fakcie jako osobny krok pętli, nie jako założenie.

Jak zdiagnozować u siebie

Weryfikator porównujący deklaracje w odpowiedzi z faktycznymi wywołaniami w śladzie. Wykrywa przyczyny pierwszą i drugą, czyli te dwie, które da się złapać bez odpytywania systemów zewnętrznych.

python
import re

CZASOWNIKI = {
    "wyslij_mail":       [r"wysłał", r"wysłano", r"przesłał", r"powiadomił"],
    "utworz_zamowienie": [r"utworzył", r"założył", r"złożył zamówienie"],
    "aktualizuj_rekord": [r"zaktualizował", r"zmienił", r"poprawił"],
}

def weryfikuj(odpowiedz, slad, powod_zakonczenia):
    problemy = []

    if powod_zakonczenia != "model odpowiedział":
        problemy.append(
            f"zakończenie WYMUSZONE ({powod_zakonczenia}) — "
            f"odpowiedź może być niepełna (przyczyna 1)")

    wykonane = {k["narzedzie"] for k in slad
                if k.get("skutek") and not k.get("odrzucenie")}

    for narzedzie, wzorce in CZASOWNIKI.items():
        deklaruje = any(re.search(w, odpowiedz, re.IGNORECASE) for w in wzorce)
        if deklaruje and narzedzie not in wykonane:
            problemy.append(
                f"odpowiedź deklaruje działanie '{narzedzie}', "
                f"a w śladzie brak takiego wywołania (przyczyna 2)")

    odrzucone = [k["narzedzie"] for k in slad if k.get("odrzucenie")]
    if odrzucone:
        problemy.append(
            f"odrzucone wywołania: {odrzucone} — sprawdź, czy powód "
            f"wrócił do modelu (przyczyna 5)")

    return problemy

odpowiedz = "Sprawdziłem zamówienie i wysłałem klientowi potwierdzenie."
slad = [
    {"narzedzie": "status_zamowienia", "skutek": False},
    {"narzedzie": "wyslij_mail", "skutek": True, "odrzucenie": "adres poza domeną"},
]

for p in weryfikuj(odpowiedz, slad, "limit kroków"):
    print("!", p)

Powyższy przykład zapala trzy lampki naraz i każda dotyczy innej przyczyny: zakończenie było wymuszone, odpowiedź deklaruje wysyłkę bez pokrycia w wykonanych wywołaniach, a odrzucenie walidacji prawdopodobnie nie wróciło do modelu.

Ćwiczenie: puść ten weryfikator na dwustu ostatnich przebiegach i policz, ile z nich zapala choć jedną lampkę. Potem porównaj z metryką sukcesu, którą raportujesz. Różnica między tymi dwiema liczbami jest miarą tego, jak bardzo twoje statystyki mijają się z rzeczywistością.

Drugie ćwiczenie, cięższe i wartościowsze: dla dwudziestu przebiegów oznaczonych jako udane sprawdź ręcznie w systemie docelowym, czy skutek naprawdę istnieje. To jedyny sposób na wychwycenie przyczyn od trzeciej do ósmej — i zwykle jednorazowy, bo po nim wiadomo, które narzędzie kłamie.

Powiązane

Warunki zakończenia i co zwracać z pętli: Maszyneria agenta. Dlaczego model nie wie, czy coś się wykonało: Anatomia LLM.

Ostatni syndrom: Działa w testach, nie działa na produkcji.

Agent zrobił coś, o co nikt nie prosił

Agent zrobił coś, o co nikt nie prosił

Objawy Operacja, której nikt nie zlecił. Dane wysłane pod adres, którego nie ma w żadnej konfiguracji. Rekord zmieniony poza zakresem zadania. Odpowiedź, z której wynika, że agent dostał instrukcje od kogoś innego niż ty. Cecha wspólna: technicznie wszystko zadziałało...

Agent zrobił to samo dwa razy

Agent zrobił to samo dwa razy

Objawy Ten syndrom różni się od pozostałych jedną rzeczą: objaw widzi klient, nie ty. Trzy identyczne wiadomości w skrzynce. Dwa zamówienia zamiast jednego. Podwójne obciążenie. Duplikaty rekordów, które ktoś zauważa tydzień później. W twoim dzienniku wszystko wygląda...

Agent gubi wątek w długim zadaniu

Agent gubi wątek w długim zadaniu

Objawy Pierwsze kroki idą wzorowo. Po kilkunastu agent zaczyna się rozjeżdżać. Przestaje przestrzegać reguły z promptu systemowego, której trzymał się na początku. Zmienia format odpowiedzi w połowie zadania. Wraca do czegoś, co już ustalił, i ustala to inaczej....

Agent podaje dane, których nie ma

Agent podaje dane, których nie ma

Objawy Numer zamówienia w idealnym formacie, którego nie ma w bazie. Kwota, której w dokumencie nie ma. Nazwa pola API, które nigdy nie istniało. Cytat z regulaminu, brzmiący dokładnie jak reszta regulaminu i w nim nieobecny. Cecha wspólna wszystkich tych przypadków:...

Działał wczoraj, dziś nie działa

Działał wczoraj, dziś nie działa

Objawy Nic się nie wywala. Nie ma wyjątków, nie ma timeoutów, dziennik wygląda tak samo jak zawsze. Po prostu odpowiedzi są gorsze. Postacie, w jakich to się objawia: Jakość. Agent zaczyna pomijać kroki, które wcześniej wykonywał, albo odpowiada ogólniej. Format....

Agent wybiera złe narzędzie

Agent wybiera złe narzędzie

Objawy Agent odpowiada nie na to pytanie. Pobiera listę zamówień, gdy pytano o jedno konkretne. Odpowiada z pamięci, choć miał sprawdzić w bazie. Albo sięga po właściwe narzędzie i wpisuje w argumenty coś, czego nie da się użyć. Sygnał, który odróżnia ten syndrom od...

Agent kręci się w kółko

Agent kręci się w kółko

Objawy Agent wykonuje kolejne obroty pętli, nie zbliżając się do zakończenia zadania. W dzienniku widać jedną z trzech postaci. Powtórzenie. To samo narzędzie, te same argumenty, raz za razem — czasem dziesiątki razy pod rząd. Oscylacja. Agent wywołuje na przemian dwa...

Co logować w pętli agenta

Co logować w pętli agenta

W drugim artykule padło, że pętla powinna zwracać nie samą odpowiedź, lecz odpowiedź razem z powodem zakończenia, liczbą kroków i zużytym budżetem. To był zalążek. Tu jest pełna wersja. Typowy dziennik agenta zapisuje pytanie i odpowiedź. To akurat najmniej użyteczna...