Przeszliśmy przez cały model: tokeny, znaczenie, uwagę, trening, generowanie, koszt, rozmiar, rozumowanie. Został ostatni krok, który jest zarazem najważniejszy praktycznie.
Nie „co model robi”, tylko czego nie robi — i gdzie dokładnie przebiega linia, za którą zaczyna się wszystko inne.
Model nie ma rąk
To jedno zdanie porządkuje cały temat.
Model nie wywołuje narzędzi. Nie ma dostępu do internetu, plików, twojej bazy ani żadnego stanu poza kontekstem. Nie wykonuje niczego. Robi jedno: dostaje ciąg i przewiduje jego kolejny element.
Kiedy więc mówimy „model wywołał narzędzie”, dzieje się coś innego. Model generuje tekst, który wygląda jak prośba o wywołanie — nazwa funkcji, argumenty. Ten tekst przechwytuje zwykły kod poza modelem, faktycznie odpala funkcję i wkleja jej wynik z powrotem jako kolejny fragment kontekstu.
Model nigdy się nie dowiaduje, czy cokolwiek naprawdę się wykonało. Widzi tylko, że w kontekście pojawiło się coś nowego.
Trzy warstwy, nie dwie
Stąd wynika podział, który warto mieć w głowie przy każdej rozmowie o agentach.
Model — przewiduje kolejny element ciągu. Nic więcej.
Pętla sterująca — wywołuje model, czyta jego wyjście, decyduje, czy to prośba o narzędzie, wykonuje ją, dokłada wynik do kontekstu i wywołuje model ponownie. To zwykły kod, który napisałeś ty albo framework.
Narzędzia — funkcje, które robią coś w świecie: odpytują API, zapisują do bazy, wysyłają maila.
Agent to całość — pojemnik obejmujący wszystkie trzy, razem z celem i uprawnieniami. Nie jest warstwą nad modelem. Model jest w nim jednym z klocków.
Model i narzędzia nigdy się nie stykają
To jest najważniejsza konsekwencja tego podziału. Między modelem a narzędziami zawsze stoi pętla — nie ma połączenia bezpośredniego.
Model widzi wyłącznie opisy narzędzi w tekście i produkuje wyłącznie tekst wyglądający jak wywołanie. Wszystko, co się realnie wydarza, wydarza się w pętli.
Rozbraja to trzy pomyłki, które w rozmowach o agentach powtarzają się najczęściej.
Narzędzie nie jest warstwą między modelem a agentem. Jest funkcją, którą wywołuje pętla. Dla modelu narzędzie to fragment tekstu w kontekście.
Model to nie agent bez narzędzi. Model bez pętli nie wykona nawet drugiego kroku — nie ma czym uruchomić się ponownie. Pętla, nie narzędzia, jest tym, co czyni z modelu agenta.
Agent to nie warstwa nad modelem. To pojemnik razem z modelem w środku.
Dlatego wszystkie zabezpieczenia są w pętli
Skoro model niczego nie wykonuje, to nie może niczego zepsuć. Może zaproponować coś złego — ale między propozycją a skutkiem stoi kod, który napisałeś.
To ustawia całą dyskusję o bezpieczeństwie agentów w jednym miejscu. Okno zgody nie chroni przed modelem, tylko przed pętlą, która za chwilę wykona to, co model zaproponował — o czym pisaliśmy w artykule o human-in-the-loop. Walidacja argumentów działa w pętli. Uprawnienia są w pętli. Limity, potwierdzenia, dzienniki — wszystko w pętli.
Wynika stąd też, dlaczego prompt injection nie jest luką do załatania. Model nie ma osobnego kanału na instrukcje i osobnego na dane — wszystko jest jedną sekwencją tokenów, a każdy token może dostać wagę. Tekst pobrany ze strony ma dokładnie ten sam status co twój prompt systemowy, o czym więcej w artykule o zatrutym kontekście. Obrona nie polega więc na przekonaniu modelu, żeby ignorował podejrzane polecenia, tylko na tym, żeby pętla nie wykonywała rzeczy, których wykonywać nie powinna.
Prośba o wywołanie narzędzia to dane wejściowe do walidacji, nie polecenie. To zdanie warto powiesić nad biurkiem.
Co należy do modelu, a co do pętli
Podsumowanie całej serii z tej jednej perspektywy.
Halucynacje są własnością modelu i nie da się ich usunąć. Weryfikacja wobec źródła prawdy należy do pętli.
Brak pamięci jest własnością modelu — wagi są zamrożone, nie ma gdzie zapisać. Pamięć agenta buduje się w pętli.
Koszt długiego kontekstu jest własnością architektury. Kompaktowanie kontekstu i układanie promptu pod cache to decyzje w pętli.
Niedeterminizm wynika z warstwy samplingu. Powtarzanie przebiegów przy ewaluacji to robota pętli i procesu wokół niej.
Brak sprawczości jest własnością modelu i akurat jest zaletą — to dzięki niej istnieje miejsce, w którym da się cokolwiek skontrolować.
Reguła, którą warto stąd wynieść: jeśli próbujesz naprawić promptem coś, co jest własnością modelu, marnujesz czas. Prompt przesuwa rozkład prawdopodobieństwa. Nie zmienia tego, czym model jest.
Kaskada, czyli motyw, który wracał trzy razy
Warto go nazwać wprost, bo pojawił się w tej serii w trzech miejscach i za każdym razem był tą samą rzeczą.
Przy rozmiarze modelu: mały model obsługuje typowy ruch, trudne przypadki idą wyżej. Przy modelach rozumujących: rozumowanie w kroku planowania, szybki model w krokach wykonawczych. Przy samplingu: ustawienia niskolosowe tam, gdzie model wybiera narzędzie, wyższe tam, gdzie pisze dla człowieka.
We wszystkich trzech przypadkach decyzja nie zapada w modelu. Zapada w pętli — bo to ona wybiera, który model wywołać, z jakimi parametrami i na którym kroku. Model jest zasobem, którym się dysponuje, a nie bytem, który się konfiguruje raz.
Jak to sprawdzić u siebie
Najlepszym dowodem na wszystko powyżej jest napisanie pętli samemu. Poniżej minimalna wersja — mniej niż trzydzieści linii i widać w nich całą granicę.
import json
from openai import OpenAI
client = OpenAI()
def pogoda(miasto): # to jest narzędzie
return {"miasto": miasto, "temp": 21, "opis": "pochmurno"}
narzedzia = [{
"type": "function",
"function": {
"name": "pogoda",
"description": "Zwraca aktualną pogodę dla miasta",
"parameters": {
"type": "object",
"properties": {"miasto": {"type": "string"}},
"required": ["miasto"],
},
},
}]
wiadomosci = [{"role": "user", "content": "Jaka jest pogoda we Wrocławiu?"}]
while True: # to jest pętla
odp = client.chat.completions.create(
model="gpt-4o-mini", messages=wiadomosci, tools=narzedzia
).choices[0].message
wiadomosci.append(odp)
if not odp.tool_calls: # to jest decyzja — twoja, nie modelu
print(odp.content)
break
for wywolanie in odp.tool_calls:
argumenty = json.loads(wywolanie.function.arguments)
print("model poprosił o:", wywolanie.function.name, argumenty)
wynik = pogoda(**argumenty) # TY wykonujesz, nie model
wiadomosci.append({
"role": "tool",
"tool_call_id": wywolanie.id,
"content": json.dumps(wynik),
})
Zwróć uwagę na trzy miejsca. Instrukcja if decydująca, czy coś wykonać, jest twoja. Wywołanie funkcji jest twoje. Wynik wracający do kontekstu wkładasz ty.
Teraz eksperyment, który pokazuje istotę rzeczy: zakomentuj linię wykonującą narzędzie i wstaw dowolny wymyślony wynik. Model przyjmie go bez mrugnięcia i zbuduje na nim odpowiedź. Nie ma jak sprawdzić, czy cokolwiek się wydarzyło — dla niego to po prostu kolejny tekst w kontekście.
I drugi, ważniejszy: dopisz przed wykonaniem sprawdzenie argumentów — czy miasto jest na liście dozwolonych, czy kwota mieści się w limicie, czy adresat jest znany. Właśnie zbudowałeś jedyne miejsce w całym systemie, w którym da się cokolwiek zatrzymać.
Koniec serii, początek następnej
Wiesz już, czym model jest i czego nie potrafi. To wiedza, która przydaje się dokładnie w jednym momencie: kiedy trzeba zdecydować, co takiemu systemowi wolno powierzyć.
Wszystko, co dzieje się po tej stronie granicy — pętla, narzędzia, pamięć, uprawnienia, ewaluacja, wdrożenie — opisuje Anatomia agenta AI. Ta seria tłumaczyła, dlaczego tamte rozwiązania musiały powstać. Tamta pokazuje, jak się je buduje.
A jeśli po tej lekturze nachodzi cię myśl, że w twoim przypadku agent może być rozwiązaniem szukającym problemu — to też jest dobry wniosek i ma swój tekst: Kiedy nie budować agenta.





















