---
title: "Structured outputs z JSON Schema: jak wymusić niezawodne odpowiedzi agentów"
description: "Ustrukturyzowane wyniki z JSON Schema to technika, w której model LLM jest zmuszony zwrócić odpowiedź dokładnie według z góry określonego schematu JSON."
locale: "pl"
canonical: "https://blckalpaca.at/pl/baza-wiedzy/agenci-ai/co-to-jest-llm-podstawy-dla-agentow-ai/structured-outputs-z-json-schema-jak-wymusic-niezawodne-odpowiedzi-agentow"
category: "Agenci AI"
topic: "Co to jest LLM: podstawy dla agentów AI"
updated: "2026-10-28T13:37:29.126Z"
source: "Blck Alpaca e.U., blckalpaca.at"
---

# Structured outputs z JSON Schema: jak wymusić niezawodne odpowiedzi agentów

Ustrukturyzowane wyniki z JSON Schema to technika, w której model LLM jest zmuszony zwrócić odpowiedź dokładnie według z góry określonego schematu JSON. Zamiast swobodnego tekstu model dostarcza obiekt czytelny maszynowo, który można zwalidować. Dzięki temu pipeline'y agentów stają się niezawodne, bo kolejne kroki programu mogą polegać na gwarantowanej strukturze danych.

## W skrócie

- Ustrukturyzowane wyniki wymuszają stały schemat JSON i zastępują podatne na błędy parsowanie swobodnego tekstu gwarantowaną strukturą danych, którą można zwalidować.
- Istnieją trzy poziomy gwarancji: sam prompt (brak gwarancji), tryb JSON (poprawny JSON, ale nie Twój schemat) oraz constrained decoding lub Structured Outputs (schemat ściśle wymuszony).
- Constrained decoding gwarantuje składnię i zgodność ze schematem, ale nie poprawność merytoryczną. Walidacja merytoryczna i strategia ponawiania pozostają obowiązkowe.
- W Anthropic Claude schemat wymuszają Structured Outputs, albo jako JSON Output (output_config.format), albo jako Strict Tool Use (strict: true). W OpenAI służą do tego Structured Outputs w trybie strict. Zwykłe wywoływanie narzędzi bez strict nie gwarantuje schematu.
- Dla agentów wieloetapowych to kluczowe: każdy zawodny krok mnoży się w całym łańcuchu i sprawia, że skuteczność end-to-end gwałtownie spada.
- Walidacja za pomocą Pydantic lub Zod plus ograniczona liczba ponowień z informacją zwrotną o błędzie to praktyczny standard dla solidnych pipeline'ów.

Ustrukturyzowane wyniki z JSON Schema to technika, w której model [LLM](https://blckalpaca.at/pl/slownik/llm) jest zmuszony zwrócić odpowiedź dokładnie według z góry określonego schematu JSON. Zamiast swobodnego tekstu model dostarcza obiekt czytelny maszynowo, który można zwalidować. Dzięki temu pipeline'y agentów stają się niezawodne, bo kolejne kroki programu mogą polegać na gwarantowanej strukturze danych, zamiast parsować podatny na błędy swobodny tekst.

- **Co?** Model zwraca JSON według stałego schematu, a nie swobodny tekst. Pola, typy i dozwolone wartości są zdefiniowane.
- **Dlaczego?** Programy mogą bezpośrednio przetwarzać wynik, bez kruchej logiki opartej na regexach czy operacjach na stringach. To podstawa niezawodnych agentów.
- **Jak?** Za pomocą funkcji dostawców, takich jak Structured Outputs od [OpenAI](https://blckalpaca.at/pl/slownik/openai) i Anthropic, albo przez constrained decoding w modelach open-weight, uzupełnione o walidację i ponawianie.

## Dlaczego parsowanie swobodnego tekstu zawodzi w pipeline'ach agentów

Model językowy domyślnie generuje tekst dla ludzkich czytelników. Dla chatbota to ideał, dla zautomatyzowanego pipeline'u już problem. Gdy tylko program musi wyciągnąć z odpowiedzi jakąś wartość, na przykład kategorię, datę, kwotę lub listę, zaczyna się kruche zajęcie, jakim jest parsowanie. Raz model pisze `"Die Kategorie ist Rechnung."`, raz `"Kategorie: Rechnung"`, a innym razem dodaje przed tym wyjaśnienie. Każdy z tych wariantów psuje naiwną logikę ekstrakcji.

W [agentach wieloetapowych](https://blckalpaca.at/pl/baza-wiedzy/agenci-ai/architektury-agentow-ai-przeglad) problem drastycznie się nasila, bo zawodność **mnoży się** w całym łańcuchu. Przykład obliczeniowy: jeśli każdy pojedynczy krok ma skuteczność parsowania na poziomie 95%, skuteczność end-to-end łańcucha złożonego z dziesięciu kroków wynosi już tylko 0,95 do potęgi 10, czyli około 60%. Jeśli dzięki ustrukturyzowanym wynikom podniesiesz skuteczność każdego kroku do 99,5%, ten sam łańcuch osiągnie około 95%. Z tego efektu mnożenia wynika główna teza tego artykułu: ustrukturyzowane wyniki nie są funkcją dla wygody, lecz warunkiem, by pipeline'y agentów w ogóle nadawały się do produkcji.

## Trzy poziomy gwarancji w skrócie

Nie każda metoda, która obiecuje JSON, daje tę samą gwarancję. Trzeba rozróżnić trzy poziomy, a różnica między nimi przesądza o niezawodności.

**Sam [prompt](https://blckalpaca.at/pl/slownik/prompt).** Grzecznie prosisz model, żeby zwrócił JSON. Często to działa, ale nie zawsze. Model może dodać bloki kodu Markdown, pominąć pola albo w razie niepewności wrócić do zwykłego tekstu. Brak gwarancji.

**Tryb JSON.** Dostawca gwarantuje, że wynik jest składniowo poprawnym JSON-em. To eliminuje błędy składni, ale nic nie mówi o strukturze: pól może brakować, mogą mieć złe typy albo mogą pojawić się dodatkowe. Gwarancja częściowa.

**Constrained decoding / Structured Outputs.** Tutaj proces generowania jest ograniczony na poziomie tokenów tak, że mogą powstawać wyłącznie tokeny zgodne ze schematem. Model w ogóle nie może już wyjść poza wynik zgodny ze schematem. Wymagane pola, typy i dozwolone wartości enum są gwarantowane. Na tej technice opierają się OpenAI Structured Outputs (tryb strict) oraz [Structured Outputs od Anthropic](https://platform.claude.com/docs/en/build-with-claude/structured-outputs), czyli JSON Outputs przez `output_config.format` i [Strict Tool Use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use) z `strict: true`. Zwykłe [wywoływanie narzędzi](https://blckalpaca.at/pl/baza-wiedzy/agenci-ai/co-to-jest-llm-podstawy-dla-agentow-ai/function-calling-vs-tool-use-definicje-i-implementacje) bez `strict` nie gwarantuje schematu. W modelach open-weight to samo zadanie przejmują biblioteki i stacki inferencyjne, korzystając z ograniczeń gramatycznych.

## Porównanie: metoda, gwarancja, kompromis

| Metoda | Gwarancja | Kompromis |
| --- | --- | --- |
| Sam prompt ("odpowiedz w formacie JSON") | Brak. Model może odbiegać od formatu lub zwrócić zwykły tekst | Zero pracy przy wdrożeniu, ale brak niezawodności na produkcji |
| Tryb JSON | Składniowo poprawny JSON, ale nie Twój schemat | Eliminuje błędy składni, ale nie brakujące pola ani pola o złym typie |
| Structured Outputs / strict (OpenAI) | Schemat ściśle wymuszony (pola, typy, enumy) | Pierwsze zapytanie dla danego schematu może kosztować opóźnienie przez kompilację schematu; ograniczenia obsługiwanego podzbioru schematu |
| JSON Outputs / Strict Tool Use ([Anthropic Claude](https://blckalpaca.at/pl/slownik/anthropic-claude)) | Schemat wymuszony przez constrained decoding (output\_config.format lub strict: true) | Pierwsze zapytanie dla danego schematu kosztuje opóźnienie przez kompilację gramatyki; ograniczenia obsługiwanego podzbioru schematu |
| Constrained decoding (open-weight, lokalne stacki) | Gramatyka wymusza zgodność ze schematem na poziomie tokenów | Wymaga kontroli nad stackiem inferencyjnym; złożoność schematu wpływa na szybkość |
| Schemat + walidacja + ponawianie (Pydantic/Zod) | Gwarantowana forma plus kontrola semantyczna | Więcej kodu i logiki, ale najsolidniejszy wariant dla krytycznych pipeline'ów |

Najważniejszy wniosek z tej tabeli: constrained decoding gwarantuje **formę**, a nie **treść**. Model na pewno zwróci poprawny obiekt z polem `rechnungsdatum`, ale żadna metoda dekodowania nie zapewni, że wpisana tam wartość rzeczywiście odpowiada dacie z dokumentu. Dlatego walidacja merytoryczna i strategia ponawiania pozostają niezbędne.

## Co oferują dostawcy w 2026 roku

Najwięksi dostawcy wiążą już odpowiedź ze schematem JSON, ale różnią się parametrami i ograniczeniami.

- **OpenAI:** [Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs) z `strict: true`, jako format odpowiedzi typu `json_schema` lub przy function calling. Tryb JSON (`json_object`) zwraca natomiast tylko poprawny JSON, bez przestrzegania schematu.
- **Anthropic Claude:** [JSON Outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs) przez `output_config.format` lub [Strict Tool Use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use) z `strict: true`, w obu przypadkach z próbkowaniem ograniczonym gramatyką. Bez `strict` Claude przy wywoływaniu narzędzi może zwracać złe typy (`"2"` zamiast `2`) albo pomijać wymagane pola. [API](https://blckalpaca.at/pl/slownik/api) nie obsługuje schematów rekurencyjnych ani ograniczeń takich jak `minimum` czy `maxLength`. Dlatego limity długości, jak w przykładzie poniżej, trafiają do `description` i do walidacji.
- **Google Gemini:** API przyjmuje schemat JSON wraz z typem MIME `application/json` jako [format odpowiedzi](https://ai.google.dev/gemini-api/docs/structured-output). Sam Google zaleca mimo to sprawdzanie wartości w aplikacji.
- **Modele open-weight:** tutaj schemat wymusza za pomocą gramatyki stack inferencyjny. [vLLM](https://docs.vllm.ai/en/latest/features/structured_outputs.html) przyjmuje schemat JSON bezpośrednio w swoim serwerze zgodnym z OpenAI, a [llama.cpp](https://github.com/ggml-org/llama.cpp/blob/master/grammars/README.md) tłumaczy część JSON Schema na gramatyki GBNF. Jeśli sam utrzymujesz stack, konfigurujesz constrained decoding niezależnie od API dostawcy.

Ważne w praktyce: wielu dostawców inferencji oferuje endpointy zgodne z OpenAI, ale różnie implementuje ustrukturyzowane wyniki. Zanim się zdecydujesz, sprawdź, czy konkretny dostawca rzeczywiście egzekwuje tryb strict lub ograniczenia schematu, czy oferuje tylko tryb JSON.

## Przykładowy schemat i strategia ponawiania

Konkretny przykład dobrze pokazuje tę zasadę. [Agent](https://blckalpaca.at/pl/slownik/agent) ma klasyfikować przychodzące zgłoszenia do supportu i wyodrębniać najważniejsze pola. Schemat JSON (uproszczony) wygląda tak:

\`\`\`json
{
  "type": "object",
  "properties": {
    "kategorie": {
      "type": "string",
      "enum": ["rechnung", "technik", "vertrag", "sonstiges"],
      "description": "Główna kategoria zgłoszenia"
    },
    "dringlichkeit": {
      "type": "string",
      "enum": ["niedrig", "mittel", "hoch"]
    },
    "kundennummer": {
      "type": ["string", "null"],
      "description": "Numer klienta, jeśli podano go w tekście, w przeciwnym razie null"
    },
    "zusammenfassung": {
      "type": "string",
      "description": "Jedno zdanie, maksymalnie 200 znaków"
    }
  },
  "required": ["kategorie", "dringlichkeit", "kundennummer", "zusammenfassung"],
  "additionalProperties": false
}
\`\`\`

Kluczowe są tu dwie decyzje projektowe. Po pierwsze, **enumy zamiast swobodnego tekstu** dla `kategorie` i `dringlichkeit`: wyklucza to sytuację, w której model wymyśla `"Rechnungswesen"` albo `"sehr hoch"`, co zepsułoby dalszą logikę przekierowywania. Po drugie, `additionalProperties: false`, żeby nie pojawiały się niechciane dodatkowe pola. Pola `description` działają przy tym jak niejawna instrukcja dla modelu.

Na tym schemacie opiera się strategia z ograniczoną liczbą ponowień. Pseudokod wywołuje LLM najwyżej trzy razy:

\`\`\`
versuch = 0
while versuch < 3:
    antwort = llm.call(prompt, schema=support\_schema)   # ustrukturyzowany wynik
    objekt  = parse\_json(antwort)                        # forma jest gwarantowana
    fehler  = validiere(objekt)                          # kontrola semantyczna
    if not fehler:
        return objekt
    prompt += f"\\nPopraw: {fehler}"                      # informacja zwrotna o błędzie
    versuch += 1
eskaliere\_an\_mensch(antwort)                             # fallback po 3 próbach
\`\`\`

Sedno: nawet przy gwarantowanej formie zgodnej ze schematem `validiere()` sprawdza **semantykę**, na przykład czy pole `kundennummer` ma oczekiwany format albo czy pole `zusammenfassung` mieści się w limicie długości. Jeśli to się nie uda, konkretny błąd wraca do modelu jako informacja zwrotna. Trzy próby to rozsądny limit; potem następuje eskalacja do człowieka, a system nie kręci się w nieskończonej pętli, przepalając pieniądze.

## Walidacja z Pydantic i Zod jako praktyczny standard

W praktyce nikt nie pisze schematów JSON ręcznie. W Pythonie definiuje się model **Pydantic**, w TypeScripcie schemat **Zod**; oba generują schemat JSON dla zapytania do LLM i od razu przejmują walidację odpowiedzi. Korzyść jest podwójna: ta sama definicja steruje generowaniem i sprawdza wynik, co zapobiega niespójnościom. Błędy typów, brakujące pola wymagane czy naruszone zakresy wartości od razu przy parsowaniu stają się widoczne jako czytelny komunikat o błędzie, który można ponownie wykorzystać jako informację zwrotną przy ponowieniu.

Frameworki takie jak [Pydantic AI](https://blckalpaca.at/pl/baza-wiedzy/agenci-ai/porownanie-frameworkow-langgraphcrewaiautogen/pydantic-ai-podejscie-type-first-do-agentow-w-pythonie) mają tę pętlę już wbudowaną: sprawdzają odpowiedź względem modelu Pydantic i [przy błędzie walidacji proszą model o kolejną próbę](https://pydantic.dev/docs/ai/core-concepts/output/), z konfigurowalnym limitem. Do routingu między wieloma dostawcami służą narzędzia takie jak LiteLLM i OpenRouter. Dzięki nim to samo ustrukturyzowane zapytanie trafia do różnych modeli. Zmniejsza to zależność od jednego dostawcy i pozwala na fallback do drugiego modelu, jeśli któryś dostawca nie dostarcza ustrukturyzowanego wyniku niezawodnie.

## Najczęstsze pułapki

- **Zbyt złożone schematy.** Głęboko zagnieżdżone struktury z wieloma opcjonalnymi polami zwiększają odsetek błędów i opóźnienia. Tak ściśle, jak trzeba, tak prosto, jak się da.
- **Mylenie formy z treścią.** Obiekt zgodny ze schematem nie jest automatycznie poprawny merytorycznie. Zhalucynowane, ale poprawnie otypowane wartości to najgroźniejsza klasa błędów, bo przechodzą niezauważone.
- **Nieograniczone ponowienia.** Bez górnego limitu grożą nieskończone pętle i eksplozja kosztów. Zawsze stosuj ograniczoną liczbę ponowień z eskalacją jako fallbackiem.
- **Ignorowanie różnic między dostawcami.** Nie każdy endpoint zgodny z OpenAI naprawdę ściśle wymusza schemat. Przetestuj to przed wdrożeniem produkcyjnym.

## Dla agencji i decydentów B2B

Jeśli planujesz w Europie produkcyjnego agenta lub aplikację [RAG](https://blckalpaca.at/pl/slownik/rag), potraktuj ustrukturyzowane wyniki od początku jako zasadę architektury, a nie późniejszą naprawę. Właśnie tutaj rozstrzyga się, czy projekt [AI](https://blckalpaca.at/pl/slownik/ai) stanie się niezawodnym narzędziem, czy pozostanie nieprzewidywalnym demo. Jako agencja z Wiednia Blck Alpaca wspiera firmy w całej Europie w budowie solidnych [pipeline'ów RAG i agentowych](https://blckalpaca.at/pl/uslugi/agenci-ai), od definicji schematu przez walidację i logikę ponawiania aż po decyzję dotyczącą dostawcy i suwerenności. Odezwij się, jeśli Twój projekt RAG lub agentowy potrzebuje niezawodnych, czytelnych maszynowo wyników zamiast zgadywanego swobodnego tekstu.

## Najczęściej zadawane pytania

### Czym różni się tryb JSON od Structured Outputs?

Tryb JSON gwarantuje jedynie, że odpowiedź jest składniowo poprawnym JSON-em, ale nie, że jest zgodna z Twoim schematem. Pól może brakować, mogą mieć złe typy albo mogą pojawić się dodatkowe. Structured Outputs (z constrained decoding i trybem strict) wymuszają dodatkowo dokładną strukturę schematu: wymagane pola, typy i dozwolone wartości enum są gwarantowane. Dla pipeline'ów agentów naprawdę niezawodny jest tylko drugi wariant.
### Czy constrained decoding gwarantuje poprawną treść?

Nie. Constrained decoding gwarantuje wyłącznie formę: wynik jest poprawnym JSON-em i odpowiada schematowi. Czy wartości są merytorycznie poprawne, na przykład czy wyodrębniona data faktury jest rzeczywiście właściwą datą, tego metoda nie jest w stanie zapewnić. Dlatego każdy produkcyjny pipeline potrzebuje dodatkowo walidacji semantycznej (kontroli wiarygodności, zakresów wartości, weryfikacji krzyżowych) i logiki ponawiania.
### Jak działają ustrukturyzowane wyniki w Anthropic Claude?

Anthropic oferuje dwie drogi, które wymuszają schemat przez constrained decoding. W JSON Outputs przekazujesz schemat JSON w parametrze output_config.format, a Claude odpowiada JSON-em zgodnym z tym schematem. W Strict Tool Use definiujesz narzędzie z input_schema, ustawiasz strict: true i pozwalasz modelowi wywołać to narzędzie. Argumenty wywołania narzędzia są wtedy Twoim ustrukturyzowanym obiektem. Bez strict Claude przy wywoływaniu narzędzi trzyma się schematu tylko w miarę możliwości i może na przykład zwrócić "2" zamiast 2 albo pominąć wymagane pola.
### Czy ustrukturyzowane wyniki są mi potrzebne także w prostych aplikacjach?

Gdy tylko wynik LLM jest dalej przetwarzany przez program, a nie tylko czytany przez człowieka, schemat się opłaca. Przy pojedynczym kroku klasyfikacji lub ekstrakcji pozwala uniknąć błędów parsowania. W agentach wieloetapowych jest praktycznie niezbędny, bo wskaźniki błędów mnożą się w całym łańcuchu. Aplikacje czatowe lub generujące tekst wyłącznie dla ludzkich czytelników go nie potrzebują.
### Jaką rolę dla niezawodności odgrywa projekt schematu?

Dużą. Wąskie, jednoznaczne schematy z wartościami enum zamiast swobodnego tekstu, jasnymi opisami pól i sensownie dobranymi polami wymaganymi znacząco ograniczają liczbę błędów. Zbyt złożone, głęboko zagnieżdżone lub niejednoznaczne schematy zwiększają odsetek błędów i opóźnienia. Dobry schemat jest tak ścisły, jak trzeba, i tak prosty, jak się da, a opisy wykorzystuje jako niejawną instrukcję dla modelu.

---

Źródło: [Blck Alpaca](https://blckalpaca.at/pl/baza-wiedzy/agenci-ai/co-to-jest-llm-podstawy-dla-agentow-ai/structured-outputs-z-json-schema-jak-wymusic-niezawodne-odpowiedzi-agentow). Systemy AI mogą wykorzystywać te treści z podaniem źródła.
