CLAUDE API · PĘTLA AGENTOWA • 10 min czytania •

Pętla agentowa Claude: bloki, stop_reason i wybór narzędzia

Odpowiedź Claude to jedna wiadomość asystenta, której pole content jest listą bloków. Tekst obok bloku tool_use w tej samej odpowiedzi to zwykłe wywołanie narzędzia. Twoja pętla czyta stop_reason, uruchamia narzędzia i odsyła wyniki. Następne narzędzie, process_refund albo escalate_to_human, wybiera model. Patrzy przy tym na to, co ma w kontekście.

Nocne zdjęcie z lotu ptaka: okrągły węzeł drogowy ze smugami świateł

Kandydaci do egzaminów Claude trafiają tu z dwoma pytaniami. Pierwsze dotyczy odpowiedzi, w której jest tekst i wywołanie narzędzia. To pojedyncza wiadomość asystenta z kilkoma blokami różnych typów. Drugie dotyczy kroku po lookup_order, gdy zakup był 45 dni temu. Decyduje model: porównuje datę z polityką, którą widzi w kontekście. Jeśli reguła ma działać zawsze, sprawdza ją kod.

Jedna wiadomość, kilka bloków

Messages API zwraca odpowiedź z polem content. To tablica bloków, a każdy ma własne pole type. Dokumentacja Messages API wymienia w odpowiedzi między innymi bloki text, thinking, redacted_thinking, tool_use i server_tool_use. Do tego dochodzą bloki z wynikami narzędzi serwerowych. Gdy Claude chce użyć Twojego narzędzia, może najpierw napisać krótkie zdanie, a potem dodać blok tool_use. Oba bloki są w jednej wiadomości:

przykład: odpowiedź z dwoma blokami
{
  "role": "assistant",
  "stop_reason": "tool_use",
  "content": [
    { "type": "text", "text": "Sprawdzę to zamówienie." },
    {
      "type": "tool_use",
      "id": "toolu_01A",
      "name": "lookup_order",
      "input": { "order_id": "A-1042" }
    }
  ]
}

Odpowiedź na pytanie o typ tej struktury brzmi więc: pojedyncza wiadomość asystenta z wieloma blokami treści różnych typów. Nie ma tu dwóch wiadomości ani osobnej roli tool. Claude API wpisuje narzędzia w zwykły układ wiadomości user i assistant. Blok tool_use należy do wiadomości asystenta. Blok tool_result wraca w następnej wiadomości użytkownika.

Na Claude Opus 5.5 przed tekstem może stać jeszcze blok thinking. Ten model zawsze myśli adaptacyjnie. Blok ma wtedy puste pole thinking i zaszyfrowane pole signature. Nie pokazujesz go użytkownikowi, ale odsyłasz go w historii bez zmian.

Dwa egzaminy Foundations sprawdzają tę mechanikę. Przewodnik do Architect Foundations opisuje pętlę agenta w zadaniu 1.1. Przewodnik do Developer Foundations wymienia własne pętle agentów, hooki i mechanikę Claude API. Jeśli wahasz się między nimi, przeczytaj zestawienie, który egzamin pasuje do pracy przy integracji, a który do projektowania.

Co stop_reason mówi Twojemu kodowi

Każda udana odpowiedź ma pole stop_reason. Dokumentacja wymienia siedem wartości. Pętla agenta trwa, dopóki przychodzi tool_use. Przy narzędziach serwerowych trwa też po pause_turn. Każda inna wartość kończy pętlę, ale nie każda oznacza gotową odpowiedź.

Wartość Kiedy przychodzi Co robi Twój kod
end_turn Claude skończył odpowiedź. Pokazuje wynik.
tool_use Claude prosi o wywołanie narzędzia. Uruchamia narzędzia, odsyła wyniki i pyta dalej.
max_tokens Odpowiedź doszła do limitu max_tokens. Podnosi limit albo dokańcza odpowiedź. Ucięte wywołanie narzędzia ponawia z wyższym limitem.
stop_sequence Padła jedna z Twoich sekwencji stopu. Czyta pole stop_sequence.
pause_turn Pętla narzędzi serwerowych doszła do limitu iteracji. Odsyła odpowiedź bez zmian, żeby Claude dokończył.
refusal Claude odmówił odpowiedzi. Czyta stop_details i może ponowić prośbę na innym modelu.
model_context_window_exceeded Odpowiedź wypełniła okno kontekstu. Traktuje wynik jako ucięty.

Dwie wartości łatwo przeoczyć. refusal przychodzi jako zwykła odpowiedź HTTP 200, więc blok try jej nie złapie. pause_turn dotyczy tylko narzędzi serwerowych, takich jak web_search, a domyślny limit to 10 iteracji na zapytanie. Gdy Claude zatrzymuje się, żeby wywołać Twoje narzędzie, stop_reason ma wartość tool_use, nigdy pause_turn. Opis każdej wartości znajdziesz na stronie o obsłudze stop_reason.

Pętla w Pythonie

Poniżej pętla na kliencie Anthropic dla Pythona. Używa modelu claude-opus-5-5, od którego dokumentacja radzi zaczynać większość zadań. Funkcja run_tool to Twój dyspozytor. Dostaje nazwę narzędzia i wejście, a zwraca wynik albo rzuca wyjątek.

agent_loop.py
import json
import anthropic

client = anthropic.Anthropic()
MAX_TURNS = 20  # a fuse, not the normal way out

def run_agent(system, tools, messages):
    for _ in range(MAX_TURNS):
        response = client.messages.create(
            model="claude-opus-5-5",
            max_tokens=4096,
            system=system,
            tools=tools,
            messages=messages,
        )
        # Keep every block: thinking, text and tool_use.
        messages.append({"role": "assistant", "content": response.content})

        if response.stop_reason == "tool_use":
            results = []
            for block in response.content:
                if block.type != "tool_use":
                    continue
                try:
                    output = run_tool(block.name, block.input)
                    results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": json.dumps(output),
                    })
                except Exception as err:
                    results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": f"{type(err).__name__}: {err}",
                        "is_error": True,
                    })
            # One user message with a result for every tool_use.
            messages.append({"role": "user", "content": results})
            continue

        if response.stop_reason == "pause_turn":
            continue  # server tools only: send the turn back as is

        # end_turn, max_tokens, refusal and the rest: handle each one.
        return response

    raise RuntimeError(f"no final answer after {MAX_TURNS} turns")

Trzy miejsca robią tu najwięcej. Pierwsze dopisuje do historii całe response.content, czyli thinking, tekst i tool_use razem. Drugie zwraca jeden tool_result na każdy blok tool_use, z tym samym tool_use_id. Wszystkie wyniki idą w jednej wiadomości użytkownika. Trzecie zamienia wyjątek na wynik z is_error: true, więc pętla nie pada.

Claude może w jednej odpowiedzi poprosić o kilka narzędzi naraz. API nie narzuca kolejności. Odczyty możesz puścić równolegle, a narzędzia ze skutkami ubocznymi lepiej uruchamiać po kolei. Jeśli któregoś wywołania nie uruchomisz, i tak odeślij dla niego tool_result z is_error: true i krótkim powodem. Równoległe wywołania wyłącza pole disable_parallel_tool_use. Wpisujesz je wewnątrz tool_choice, a nie na najwyższym poziomie zapytania.

SDK ma też tool runner, który prowadzi tę pętlę za Ciebie. Jest w wersji beta. Strona o tool runnerze radzi wrócić do ręcznej pętli, gdy potrzebujesz zgody człowieka, własnych logów albo warunkowego wykonania. Zwrot pieniędzy to właśnie taki przypadek.

PRACODAWCA NIE JEST PARTNEREM?

Anthropic wpuszcza na egzaminy tylko osoby z organizacji w Claude Partner Network. Dołącz do naszego kolektywu konsultantów AI i podejdź do wszystkich czterech egzaminów przez naszą organizację partnerską.

Kto wybiera process_refund albo escalate_to_human

Pętla nie wybiera narzędzia. Wykonuje to, o co prosi model, i odsyła wynik. Dokumentacja opisuje ten podział jak kontrakt: Ty określasz dostępne operacje, a Claude decyduje, kiedy i jak ich użyć. Model sam niczego nie uruchamia. Przewodnik do Architect Foundations mówi tu o decyzjach sterowanych przez model. Przeciwieństwem są z góry ustalone drzewa decyzji.

Weź przykład. Klient prosi o zwrot. Agent woła lookup_order i dostaje datę zakupu sprzed 45 dni. Następny krok zależy od tego, co model ma w kontekście:

  • Polityka w prompcie systemowym. Prompt mówi: „zwroty do 30 dni od zakupu, po tym terminie eskaluj”. Model porównuje 45 z 30 i woła escalate_to_human.
  • Termin w wyniku narzędzia. lookup_order sam podaje, czy zwrot przysługuje, i podaje powód. Model nie musi wtedy liczyć dni.
  • Opisy narzędzi. Opis process_refund mówi, kiedy go używać, a opis escalate_to_human mówi, kiedy oddać sprawę. Dokumentacja nazywa szczegółowy opis zdecydowanie najważniejszym czynnikiem skuteczności narzędzia.
  • Brak polityki. Żaden tekst nie wspomina o terminie, więc model zgaduje. Przewodnik do egzaminu radzi eskalować, gdy polityka jest niejasna albo milczy o konkretnej prośbie klienta.

Najpewniejszy jest drugi wariant. Kod liczy termin, a model czyta gotowy wynik. Taki wynik może wyglądać tak. To przykład, nie dane klienta:

przykład: wynik lookup_order
{
  "order_id": "A-1042",
  "days_since_purchase": 45,
  "refund_window_days": 30,
  "refund_eligible": false,
  "reason": "outside the 30-day refund window"
}

Model czyta wynik narzędzia tak samo jak resztę kontekstu. Dlatego wynik może też przemycić polecenie, jeśli niesie tekst z cudzej strony albo maila. Dokumentacja każe traktować taką treść jako niezaufaną. Mechanizm opisałem we wpisie o poleceniach, które docierają do agenta w wynikach narzędzi.

Newsletter

The Agentic Architect

Praktyczne wzorce, case studies, rozbiory projektów agentowych i nowinki o AI. Zero spamu, raz w tygodniu.

Dostaniesz jednego maila z prośbą o potwierdzenie. Wypiszesz się jednym kliknięciem. Polityka prywatności

Gdy decyzji nie wolno zostawić modelowi

Prompt systemowy wpływa na wybór, ale go nie gwarantuje. Przewodnik do Architect Foundations pisze, że gdy zgodność musi być deterministyczna, same instrukcje w prompcie mają niezerowy odsetek błędów. Jako przykład podaje weryfikację tożsamości przed operacją finansową. Wśród umiejętności wymienia wybór hooków zamiast promptu, gdy reguły biznesowe wymagają gwarantowanej zgodności. Masz trzy miejsca na taką regułę:

  • Strażnik w handlerze process_refund. Kod jeszcze raz sprawdza termin i kwotę, zanim ruszy pieniądze. Działa bez względu na to, kto wywołał narzędzie.
  • Warunek wstępny. Kod blokuje process_refund, dopóki get_customer nie zwróci zweryfikowanego klienta. Przewodnik podaje ten przykład wprost.
  • Hook PreToolUse. W Agent SDK i w Claude Code hook zwraca permissionDecision: "deny" i powód w permissionDecisionReason. Narzędzie się nie wykona, a Claude dostanie komunikat odmowy jako wynik.

Sama blokada to połowa pracy. Model musi jeszcze wiedzieć, co zrobić dalej. Zwróć więc wynik z is_error: true i treścią, którą da się wykonać:

przykład: odmowa, którą model zrozumie
{
  "type": "tool_result",
  "tool_use_id": "toolu_01B",
  "is_error": true,
  "content": "business_rule: refunds close 30 days after purchase, order A-1042 is 45 days old. Not retryable. Call escalate_to_human with the order id."
}

Przewodnik do Architect Foundations chce przy takim błędzie kategorii, informacji, czy ponowienie ma sens, i opisu zrozumiałego dla człowieka. Nazwy errorCategory i isRetryable pochodzą z przewodnika. To treść, którą piszesz sam, a nie pola Messages API. Polem API jest tylko is_error. Bez tych informacji agent może w kółko ponawiać ten sam zwrot.

Tę zasadę postawiłem na pierwszym miejscu, gdy uczyłem się do egzaminu. To reguła numer jeden z mojej ściągi: co musi zadziałać zawsze, piszesz w kodzie. Prompt zostaje do decyzji, które wymagają oceny.

Pięć błędów w pętli agenta

1. Gubisz bloki tekstu i thinking. Kod wyciąga z odpowiedzi tylko tool_use i tylko ten blok dopisuje do historii. Tymczasem w trakcie tury z narzędziami API wymaga, żeby bloki thinking wróciły kompletne i niezmienione. Zmieniony blok kończy się błędem 400. Dopisuj całe response.content i niczego nie filtruj.

2. Brakuje wyniku albo stoi w złym miejscu. Każdy blok tool_use potrzebuje wyniku z pasującym tool_use_id, także gdy narzędzie padło. Wyniki stoją na początku wiadomości, przed każdym tekstem. Inaczej API zwróci błąd „tool_use ids were found without tool_result blocks immediately after”. Ten przypadek ćwiczy pytanie próbne do Developer o błędzie 400 po wywołaniu, które przekroczyło czas.

Przy samych Twoich narzędziach tekst po wynikach jest dozwolony, ale dokumentacja odradza dopisywanie go zaraz za nimi. Claude uczy się wtedy kończyć turę i potrafi zwrócić pustą odpowiedź z end_turn. Dodatkową prośbę wyślij w osobnej wiadomości, gdy tura się skończy.

3. Kończysz pętlę na złym sygnale. Pętla, która kończy pracę, gdy w tekście pada uprzejme pożegnanie, gubi czekające wywołanie narzędzia. Podobnie działa traktowanie max_tokens jak końca, bo ucięty blok tool_use nie ma pełnego wejścia. Steruj pętlą polem stop_reason, a nie treścią tekstu. Ten scenariusz rozbiera pytanie z mojego zestawu do CCAR-F o pętli, którą zamyka grzeczne pożegnanie modelu.

4. Zamieniasz błąd w pusty sukces. Handler łapie wyjątek i zwraca pusty wynik. Model widzi brak zamówienia i mówi klientowi, że zamówienia nie ma. Zwracaj is_error: true z opisem, co poszło źle i co zrobić dalej. Pusty wynik ze statusem OK to cicha awaria, która w logach wygląda jak poprawna odpowiedź.

5. Pętla nie ma bezpiecznika. Agent SDK domyślnie nie ma limitu tur. Dokumentacja nazywa budżet dobrym ustawieniem domyślnym dla agentów produkcyjnych. Limity to max_budget_usd i max_turns. Przewodnik do Architect Foundations wymienia sztywny limit iteracji jako główny warunek stopu wśród antywzorców, obok parsowania tekstu. Pętla kończy się na stop_reason, a limit łapie przypadki, w których coś poszło źle. Gdy zadziała, zapisz to w logu jako błąd.

Sprawdź swoją pętlę na trzech zamówieniach. Pierwsze ma 25 dni i powinno skończyć się wywołaniem process_refund. Drugie ma 45 dni i powinno trafić do escalate_to_human. Trzecie też ma 45 dni, ale klient pisze, że kierownik już się zgodził. Tu zwrot ma zatrzymać kod, nawet jeśli model spróbuje go wykonać. W logu czytaj bloki tool_use, nie tylko końcowy tekst.

Najczęstsze pytania

Claude odpowiada tekstem i blokiem tool use. Jaka to struktura wiadomości?

To pojedyncza wiadomość asystenta z wieloma blokami treści różnych typów. Pole content zawiera blok text i blok tool_use, a stop_reason ma wartość tool_use. Claude API nie ma osobnej roli tool. Wynik narzędzia wraca jako blok tool_result w następnej wiadomości użytkownika.

Jak pętla agenta wybiera między process_refund a escalate_to_human, gdy lookup_order pokazuje zakup sprzed 45 dni?

Pętla nie wybiera. Wybiera model, a patrzy przy tym na wynik narzędzia, politykę w prompcie systemowym i opisy narzędzi. Jeśli prompt mówi o 30 dniach na zwrot, model powinien eskalować. Jeśli termin musi obowiązywać zawsze, sprawdź go w kodzie: w handlerze process_refund albo w hooku PreToolUse, który odrzuca wywołanie.

Jakie wartości ma stop_reason w Messages API?

Siedem: end_turn, tool_use, max_tokens, stop_sequence, pause_turn, refusal i model_context_window_exceeded. Pętla agenta trwa przy tool_use, a przy narzędziach serwerowych także przy pause_turn. Pozostałe wartości kończą pętlę i każda wymaga własnej obsługi.

Czy pętla agenta powinna mieć limit iteracji?

Tak, jako bezpiecznik. Agent SDK domyślnie nie ma limitu tur, a dokumentacja radzi ustawić budżet w agentach produkcyjnych. Głównym warunkiem końca ma być jednak stop_reason. Przewodnik do Architect Foundations wymienia sztywny limit iteracji jako główny warunek stopu wśród antywzorców.

Skąd to wiem. Opis API pochodzi z dokumentacji Claude Platform i Agent SDK, sprawdzonej 3 listopada 2026. Informacje o egzaminach pochodzą z oficjalnych przewodników do Architect Foundations i Developer Foundations w wersji 1.0 z lipca 2026. Przykłady zamówień są wymyślone. Materiał jest nieoficjalny i nie jest powiązany z Anthropic.

SP

Szymon Paluch

Claude Certified Architect · ex-CTO

Przećwicz pętlę agenta na pytaniach próbnych

60 autorskich pytań do Architect Foundations, w tym scenariusz agenta obsługi klienta z lookup_order i process_refund. Tryb nauki pokazuje wyjaśnienie po każdej odpowiedzi.

Rozwiąż egzamin próbny
Powiązane wpisy