Autor: Jakub Rusinowski · Ostatnia aktualizacja 2026-08-04 · Wartości sprzętowe wyliczone naszym silnikiem VRAM
Tool calling to miejsce, w którym lokalne agenty kodujące psują się najczęściej — nie dlatego, że model nie potrafi rozumować, tylko dlatego, że emituje JSON, którego harness nie sparsuje. Trzy poprawki w kolejności skuteczności: weź model, którego szablon czatu ma natywną obsługę wywołań narzędzi; ogranicz dekodowanie gramatyką ze schematu JSON, żeby niepoprawne wyjście było niemożliwe z konstrukcji; i trzymaj małą powierzchnię narzędziową. Razem zamieniają niestabilnego agenta w przewidywalnego, bez zmiany progu modelu.
Agent to model, który potrafi działać. Mechanizm jest mało efektowny: model emituje ustrukturyzowane wywołanie — nazwę i obiekt JSON z argumentami — a harness je wykonuje. Każda zdolność, na której ci zależy, od odczytania pliku po uruchomienie zestawu testów, przechodzi przez ten jeden wąski interfejs.\n\nModele z czołówki sprawiają, że wygląda to trywialnie. Lokalne obnażają, jak wąski ten interfejs naprawdę jest. Model 8–32B poproszony o wywołanie narzędzia z pewną częstotliwością owinie JSON wyjaśnieniem, użyje file tam, gdzie schemat mówił path, wyemituje dwa wywołania tam, gdzie dozwolone było jedno, albo zacznie wywołanie i zjedzie w prozę. Harness widzi akcję nie do sparsowania, a twój agent staje, ponawia albo umiera. To nie jest porażka rozumowania i większy model nie jest jedynym lekarstwem.
Świadomość, którego mechanizmu używa twój stack, wyjaśnia większość jego awarii.\n\n1 · Natywne wywoływanie narzędzi przez szablon czatu. Model został dostrojony do emitowania wywołań w konkretnym formacie, a szablon czatu w GGUF-ie ten format koduje. Serwer parsuje go i zwraca ustrukturyzowane pole tool_calls w odpowiedzi zgodnej z OpenAI. To ścieżka niezawodna — i dlatego modele reklamowane jako warianty *agentic* albo *coder* zachowują się w agentach nieporównanie lepiej niż ogólne modele czatowe tej samej wielkości.\n\n2 · Promptowany JSON. Harness opisuje narzędzia w prompcie systemowym, prosi o JSON i sam go parsuje. Działa z każdym modelem; zawodzi znacznie częściej, bo nic nie wymusza kształtu. Większość zgłoszeń „dlaczego mój agent stanął?” mieszka właśnie tutaj.\n\n3 · Formaty edycji zamiast wywołań narzędzi. Podejście Aidera: zamiast schematu narzędzi poproś o diff albo blok szukaj-i-zamień. To format *tekstowy*, więc słabsze modele radzą sobie z nim lepiej niż z zagnieżdżonym JSON-em, a błąd jest widoczny (łatka się nie nakłada), nie cichy. To rzeczywisty powód, dla którego Aider bije ponad swoją wagę przy małych modelach.\n\nPreferuj 1, w razie czego schodź do 3, a 2 traktuj jako to, co trzeba ograniczyć.
Najmocniejsza dostępna poprawka nie prosi modelu, żeby się zachowywał — czyni złe zachowanie niemożliwym. Przy każdym tokenie dekodowanie ograniczone gramatyką maskuje wszystkie tokeny, które nie mogłyby kontynuować poprawnego wyjścia. Niepoprawny JSON nie jest naprawiany po fakcie; on nigdy nie powstaje.
llama.cpp używa GBNF (własnego formatu gramatyk w stylu BNF) i automatycznie zamienia JSON Schema w gramatykę, więc w praktyce podajesz jej ten sam schemat, który dałbyś w definicji narzędzia. Zbudowane na niej serwery zgodne z OpenAI wystawiają to jako ustrukturyzowane wyjście albo format odpowiedzi zgodny ze schematem JSON; vLLM i SGLang mają swoje odpowiedniki.
# serwer llama.cpp: wymuś, by każda odpowiedź pasowała do schematu wywołania narzędzia
llama-server -m qwen3-coder-8b-q4_k_m.gguf --port 8080 --ctx-size 16384
curl http://localhost:8080/v1/chat/completions -H "Content-Type: application/json" -d '{
"messages": [{"role":"user","content":"Read src/auth.py"}],
"response_format": {
"type": "json_schema",
"json_schema": {"name":"tool_call","schema":{
"type":"object",
"properties":{
"tool":{"type":"string","enum":["read_file","edit_file","run_tests"]},
"args":{"type":"object"}
},
"required":["tool","args"],
"additionalProperties": false
}}
}
}'
Dwa zastrzeżenia, które warto znać, zanim włączysz to wszędzie:
Niezawodność wywołań narzędzi jest własnością treningu, nie czymś, co się samo wyłania. Dwa modele identycznej wielkości potrafią różnić się ogromnie, a różnica idzie za tym, czy model był dotrenowany na przebiegach agentowych i różnorodnych formatach wywołań.\n\nNa co patrzeć, po kolei:\n\n1. Jawne dostrojenie agentowe albo koderskie. Devstral-2 22B jest trenowany pod agentową inżynierię oprogramowania; linia Qwen3-Coder pod pracę agentów kodujących i wywoływanie narzędzi. Oba zachowują się w harnessie dużo lepiej niż ogólny model czatowy o tej samej liczbie parametrów.\n2. Szablon czatu z obsługą narzędzi. Sprawdź, czy GGUF faktycznie taki ma — ollama show --modelfile <tag> pokaże szablon. Brak tokenów narzędziowych w szablonie oznacza, że jesteś na ścieżce promptowanego JSON-a, chciałeś tego czy nie.\n3. W obrębie progu — świeżość ponad rozmiar. Jakość wywoływania narzędzi poprawiała się w latach 2025–2026 dużo szybciej niż samo rozumowanie. Aktualny 22B zwykle bije dwuletniego 34B wewnątrz pętli agenta.\n\nWybory na każdy próg i dokładne wartości VRAM znajdziesz w najlepszych lokalnych modelach do kodowania. Krótko, pod agentów: 8B da radę z ograniczeniami i małym zestawem narzędzi; 22B to pierwszy wygodny próg; przy 27–32B przestajesz o tym myśleć.
Progi, na których wywoływanie narzędzi jest na tyle niezawodne, że można zostawić agenta w ruchu. Wartości VRAM to wagi Q4_K_M z silnika obliczeniowego tej strony — cache KV pod twój kontekst dolicz ponad to.
| Model | VRAM (Q4) | Uruchomi się na | Kontekst | Licencja |
|---|---|---|---|---|
| Qwen3-Coder 8B Wejście — ogranicz go — Nadaje się do pętli przy małym zestawie narzędzi i ograniczeniach gramatycznych. Trzymaj zadania w obrębie jednego pliku. ollama pull qwen3-coder:8b | 5.6 GB | 8 GB GPU (RTX 3060/4060) Mac: 16 GB pamięci zunifikowanej | 125K | Apache-2.0 |
| Devstral-2 22B Pierwszy wygodny próg — Wprost dostrojony agentowo pod inżynierię oprogramowania; niezawodnie trzyma się formatów edycji i schematów narzędzi. ollama pull devstral:22b | 14.1 GB | 16 GB GPU (RTX 4060 Ti 16GB / 5060 Ti) Mac: 24 GB pamięci zunifikowanej | 125K | Apache-2.0 |
| Qwen 3.6 27B Autonomia godna zaufania — Próg, na którym zepsute wywołania przestają być czymś, o czym myślisz na co dzień. ollama pull qwen3.6:27b | 17.6 GB | 24 GB GPU (RTX 3090/4090) Mac: 24 GB pamięci zunifikowanej | 256K | Apache-2.0 |
| Qwen3-Coder 80B-A3B (MoE) Stacja robocza / Mac od 96 GB — Szybkie dekodowanie MoE plus mocny trening pod wywoływanie narzędzi — lokalny sufit dla długich przebiegów agenta. ollama pull qwen3-coder:80b-a3b-q4 | 49.1 GB | 2×48 GB GPUs / big unified memory Mac: 96 GB pamięci zunifikowanej | 125K | Apache-2.0 |
Każde wystawione narzędzie jest opisywane w każdym żądaniu, a każda dodatkowa opcja to kolejna szansa, że słabszy model wybierze źle. Oba koszty są lokalnie dotkliwsze: tokenów brakuje, bo okno jest małe, a trafność wyboru i tak jest niższa na starcie.\n\n- Sześć do ośmiu narzędzi w zupełności wystarczy do pracy z kodem: odczyt, edycja, listowanie i wyszukiwanie, uruchomienie polecenia, uruchomienie testów, ewentualnie pobranie zasobu. Jeśli twój rejestr ma dwadzieścia pozycji, tnij.\n- Podpięte serwery MCP to też narzędzia. Kilka serwerów potrafi wstrzyknąć dziesiątki tysięcy tokenów schematów, zanim napiszesz choć słowo — jedną trzecią dużego okna, a więcej niż całe małe. Podpinaj je per projekt, nie globalnie (MCP przy lokalnych agentach).\n- Dawaj narzędziom rozłączne zadania. search_files i grep_repo robiące prawie to samo kosztują tokeny i fundują modelowi rzut monetą. Scal je.\n- Opisy to prompty. Jedna linijka, w trybie rozkazującym, mówiąca dokładnie, kiedy tego użyć i co to zwraca. Jeśli model uparcie używa narzędzia źle, dopisz, czego ono *nie* robi.
Nawet z ograniczeniami pojedyncze wywołania będą padać. Obsłuż je w harnessie, zamiast eskalować do człowieka:\n\n1. Ponowienie naprawiające parsowanie. Po błędzie parsowania poproś ponownie, podając surowe wyjście i schemat, i prosząc wyłącznie o poprawiony JSON. Zwykle udaje się za pierwszym razem i *nie* powinno liczyć się do limitu iteracji pętli — to błąd formatowania, nie nieudana próba.\n2. Waliduj argumenty, nie tylko parsuj. Poprawny JSON ze zmyśloną ścieżką jest gorszy od błędu parsowania, bo się wykona. Sprawdź, czy ścieżka istnieje i mieści się w dozwolonym katalogu, czy wartości należą do enumów i czy są wszystkie wymagane pola — a potem zwróć modelowi komunikat błędu jako wynik narzędzia. Modele poprawiają się po konkretnym sprzężeniu zwrotnym zaskakująco dobrze.\n3. Obniż temperaturę na tury z akcją. Ustrukturyzowane wyjście chce dekodowania bliskiego zachłannemu. 0,0–0,2 na tury z wywołaniem narzędzia; wyższą temperaturę zostaw dla prozy.\n4. Loguj każde zepsute wywołanie. Wskaźnik powyżej mniej więcej jednego na dwadzieścia to problem konfiguracji — zły szablon, nieograniczone dekodowanie, za dużo narzędzi — a nie pech. Log powie ci który.\n5. Ogranicz pętlę naprawczą. Dwie nieudane naprawy oznaczają: zatrzymaj się i pokaż to człowiekowi. Trzy modele kłócące się ze schematem to zmarnowany wieczór.
| Objaw | Przyczyna | Poprawka |\n|---|---|---|\n| tool_calls zawsze puste, model zamiast tego opowiada swój plan | Szablon czatu nie obsługuje narzędzi albo harness jest na ścieżce promptowanego JSON-a | Przejdź na dostrojenie agentowe lub koderskie z tokenami narzędziowymi w szablonie; sprawdź to przez ollama show --modelfile |\n| JSON poprawny, nazwy argumentów złe | Schemat nie jest wymuszany, model zgaduje z opisu | Ogranicz schematem JSON; w opisach podawaj nazwy pól wprost |\n| Wywołanie ucięte w połowie JSON-a | Za niski limit tokenów odpowiedzi albo okno się zapełniło i na odpowiedź nie zostało miejsca | Zarezerwuj miejsce na odpowiedź w budżecie kontekstu; podnieś maksymalną liczbę tokenów |\n| Poprawne wywołanie, zła ścieżka pliku | To nie problem wywoływania narzędzi — modelowi brakuje kontekstu repozytorium | Mapa repozytorium albo krok wyszukiwania przed edycją (context engineering) |\n| Działa pojedynczo, psuje się po dwudziestu turach | Degradacja kontekstu, nie formatowanie | Kompaktuj wcześniej albo zrestartuj sesję |\n\nWzorzec wart zapamiętania: awarie formatowania to błędy konfiguracji, a błędy konfiguracji naprawia się tanio. Dopiero gdy wskaźnik poprawnych wywołań jest czysty, przeskok na wyższy próg modelu mówi ci cokolwiek wiążącego.