Wszystkie posty
aiAI-Powered

Integracja OpenAI Function Calling z własnym API: kompletny przewodnik

Naucz się integrować OpenAI Function Calling z własnym API: definicje funkcji, tool_choice, obsługa odpowiedzi tool_calls i obsługa błędów. Praktyczne przykłady JSON i kodu.

5 min czytaniaAktualizacja: 8 lipca 2026

Function Calling to jedna z najważniejszych możliwości API OpenAI, jeśli chcesz zbudować asystenta, który realnie działa – nie tylko gada. Model dostaje definicje funkcji, które Twoja aplikacja potrafi wykonać, i zamiast zgadywać odpowiedź, zwraca ustrukturyzowaną prośbę o wywołanie konkretnej funkcji z argumentami. Ty wykonujesz kod, zwracasz wynik, a model na jego podstawie formułuje odpowiedź dla użytkownika.

W tym artykule pokażę kompletny przepływ: definicje funkcji, sterowanie trybem tool_choice, obsługę odpowiedzi tool_calls, łączenie kroków w pętlę oraz typowe błędy i sposoby ich rozwiązania.

Jak działa Function Calling krok po kroku

Przepływ zawsze wygląda tak samo i warto go zapamiętać, bo każda iteracja to ta sama sekwencja:

  1. Wysyłasz wiadomości użytkownika oraz listę definicji funkcji (tools).
  2. Model odpowiada albo normalną treścią, albo żądaniem wywołania funkcji (tool_calls).
  3. Jeśli są tool_calls, Twój kod wykonuje każdą z funkcji i dołącza wyniki jako wiadomości role: "tool".
  4. Wysyłasz całą historię ponownie – model formułuje odpowiedź lub żąda kolejnych wywołań.
  5. Powtarzasz, aż model zwróci zwykłą odpowiedź tekstową.

Kluczowa zasada: każdy krok to nowe wywołanie API z pełną historią. Model nie pamięta niczego poza tym, co wyślesz, więc historia musi zawierać wszystkie wcześniejsze wiadomości, w tym wyniki funkcji.

Definicje funkcji – pierwszy i najważniejszy krok

Jakość całej integracji stoi na jakości definicji. Model nigdy nie uruchamia Twojego kodu – tylko opisuje, co chcesz wywołać. Dlatego opis funkcji musi mówić, kiedy jej użyć i czego oczekujesz w argumentach.

Przykład definicji funkcji sprawdzającej status zamówienia w Twoim API:

{
"tools": [
{
"type": "function",
"function": {
"name": "sprawdz_status_zamowienia",
"description": "Sprawdza status zamówienia po numerze zamówienia. Użyj, gdy użytkownik pyta o status, śledzenie przesyłki lub szczegóły zamówienia.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Numer zamówienia w formacie ORD-XXXXXX, podany przez użytkownika."
}
},
"required": ["order_id"],
"additionalProperties": false
}
}
},
{
"type": "function",
"function": {
"name": "anuluj_zamowienie",
"description": "Anuluje zamówienie, jeśli jest w statusie 'oczekujace'. NIE używaj bez potwierdzenia od użytkownika.",
"parameters": {
"type": "object",
"properties": {
"order_id": { "type": "string" },
"reason": {
"type": "string",
"enum": ["zmiana_zdania", "bledne_zamowienie", "inne"]
}
},
"required": ["order_id", "reason"],
"additionalProperties": false
}
}
}
]
}

Zwróć uwagę na detale, które realnie zmieniają zachowanie modelu:

  • Opis zawiera warunek użycia (“Użyj, gdy użytkownik pyta o status”). Model lepiej klasyfikuje intencję, gdy opis przypomina instrukcję.
  • additionalProperties: false wymusza ścisłe argumenty – model nie dopisze pól, których nie zdefiniowałeś.
  • Ograniczenia zapisuj w opisie (“NIE używaj bez potwierdzenia”). To jedyny sposób, by model wiedział o zasadach Twojej firmy.
  • enum przy reason ogranicza wartości do znanych Ci przypadków – później łatwiej mapować je na logikę biznesową.

Sterowanie wywołaniem przez tool_choice

Pole tool_choice decyduje, czy i jaką funkcję model może wywołać:

{ "tool_choice": "auto" },
{ "tool_choice": "none" },
{ "tool_choice": "required" },
{
"tool_choice": {
"type": "function",
"function": { "name": "sprawdz_status_zamowienia" }
}
}
  • "auto" – domyślny. Model sam decyduje, czy potrzebuje funkcji.
  • "none" – zakaz wywołań. Przydatne w pierwszym kroku rozmowy, gdy chcesz najpierw zebrać intencję.
  • "required" – wymusza wywołanie dokładnie jednej funkcji. Świetne do testów i przepływów, w których funkcja jest niezbędna (np. weryfikacja dostępności terminu).
  • Wartość z nazwą funkcji – wymusza konkretną funkcję. Użyj jej, gdy kontekst rozmowy jednoznacznie wskazuje potrzebny krok.

Praktyczna zasada: zaczynaj od "auto". Wymuszanie trybów zbyt wcześnie produkuje wywołania, których użytkownik nie potrzebował.

Obsługa odpowiedzi – pętla tool_calls

Model zwraca prośbę o wywołanie w polu tool_calls wiadomości asystenta. Twój kod musi:

  1. Sprawdzić, czy odpowiedź zawiera tool_calls.
  2. Dla każdego wywołania wykonać funkcję o nazwie z function.name z argumentami z function.arguments (JSON string!).
  3. Dodać wiadomości role: "tool" z wynikiem i tym samym tool_call_id.
{
"role": "assistant",
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "sprawdz_status_zamowienia",
"arguments": "{\"order_id\":\"ORD-123456\"}"
}
}
]
}

Uwaga na pułapkę: arguments to string z JSON-em, nie obiekt. Przed użyciem musisz go sparsować (JSON.parse), a wynik wykonania funkcji zwrócić jako string:

{
"role": "tool",
"tool_call_id": "call_abc123",
"content": "{\"status\":\"w_drodze\",\"przewidywana_dostawa\":\"2026-07-15\"}"
}

Po dodaniu tej wiadomości wysyłasz pełną historię ponownie. Model zobaczy wynik i sformułuje odpowiedź dla użytkownika – albo zażąda kolejnego wywołania, np. anulowania zamówienia po sprawdzeniu statusu. Tak powstają łańcuchy wywołań: model sam decyduje, że potrzebuje kilku kroków, żeby odpowiedzieć.

Obsługa błędów – błędy Twojego API to też treść

Błędy w integracji Function Calling dzielą się na dwie grupy: błędy po stronie Twojego API i błędy po stronie modelu.

Błąd w Twoim API (np. zamówienie nie istnieje, usługa nie odpowiada): nie przerywaj rozmowy błędem HTTP. Zwróć modelowi komunikat błędu jako wynik funkcji:

{
"role": "tool",
"tool_call_id": "call_abc123",
"content": "{\"error\":\"Zamowienie ORD-999999 nie istnieje w systemie.\"}"
}

Model przeczyta błąd, przeprosi użytkownika i zaproponuje poprawę – np. poprosi o inny numer. To duża przewaga nad klasycznymi API, gdzie błąd kończył rozmowę. Dodatkowo zawsze waliduj argumenty po swojej stronie (JSON.parse w trybie z błędem) – zanim trafią do Twojej logiki.

Błąd po stronie modelu – nieprawidłowy JSON w arguments, brak tool_call_id, nagłe zakończenie odpowiedzi. Obsłuż je tak:

  • Nieudany parse: wyślij modelowi wiadomość role: "tool" z treścią "Invalid JSON: <raw>" i poproś o poprawne argumenty.
  • Przekroczony limit kroków: wprowadź twardy limit iteracji (np. 5) i zakończ rozmowę komunikatorem, że potrzebujesz pomocy człowieka.
  • Cięcie odpowiedzi (finish_reason: "length"): powiększ max_tokens lub podziel zadanie na mniejsze funkcje.
  • Wszystkie wywołania zwracają błąd: przełącz tool_choice na "none" i poproś model o wyjaśnienie użytkownikowi.

Warto też logować każde wywołanie: tool_call_id, nazwę funkcji, argumenty, wynik, czas trwania. Bez logów debugowanie pętli wielokrokowych jest drogie.

Kiedy w ogóle używać Function Calling?

Function Calling ma sens, gdy model potrzebuje danych, których nie ma w prompcie: statusów z Twojej bazy, operacji zapisu, wywołań zewnętrznych API. Jeśli pytanie jest statyczne (cennik, FAQ), zwykły prompt wystarczy i będzie tańszy.

Zaczynaj od jednej, dobrze opisanej funkcji, przetestuj pętlę na 10-20 rozmowach, a dopiero potem dodawaj kolejne. Więcej funkcji w jednym wywołaniu = większe ryzyko błędnych wyborów, szczególnie gdy ich opisy są do siebie podobne.

Function Calling to fundament agentów działających na Twoich danych – jeśli planujesz budowę bardziej złożonych systemów, przeczytaj o wieloagentowych systemach AI i o architekturach RAG z API OpenAI.

Tagi:#openai#ai#function-calling#api#automatyzacja

Najczęściej zadawane pytania

Czym jest Function Calling w OpenAI?
To mechanizm, w którym model nie zwraca bezpośredniej odpowiedzi, tylko prośbę o wywołanie zdefiniowanej przez Ciebie funkcji z konkretnymi argumentami. Twój kod wykonuje funkcję i zwraca wynik modelowi, a model formułuje finalną odpowiedź. Dzięki temu model może sięgać po dane z Twojej bazy, API czy narzędzi, do których nie ma bezpośredniego dostępu.
Czy muszę używać tool_choice w każdym wywołaniu?
Nie. Domyślnie model sam decyduje, kiedy użyć funkcji. tool_choice: 'auto' to tryb domyślny. Tryb 'required' wymusza wywołanie dokładnie jednej funkcji, a 'none' zabrania wywołań. Wartość wymuszającą konkretną funkcję (np. tool_choice z nazwą) stosuj, gdy wiesz, że to wywołanie jest konieczne dla danego kroku przepływu.
Jak obsłużyć błąd po stronie mojego API podczas wywołania funkcji?
Zwróć komunikat błędu jako treść wiadomości z role: 'tool' i wyślij go z powrotem do modelu z tym samym tool_call_id. Model przeanalizuje błąd i podejmie decyzję – poprawi argumenty, zaproponuje alternatywę albo poinformuje użytkownika. Dzięki temu rozmowa nie kończy się awaryjnie, a model ma kontekst do naprawy.

Powiązane posty

MAHAWIR IWANOWSKI · WROCŁAW

Przyszłość organizacji — budowana tam, gdzie psychologia spotyka inżynierię, renderowana w kodzie, dostarczana z intencją.

Przyszłość Organizacji w Kodzie

AI · Fullstack · Psychology

© 2026 Mahawir Iwanowski · Wszystkie prawa zastrzeżone.