SPB Git

Repository Public

structured-outputs.md 133.1 KB 4,438 lines markdown

1# Structured model outputs23> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.45JSON is one of the most widely used formats in the world for applications to exchange data.67Structured Outputs is a feature that ensures the model will always generate responses that adhere to your supplied [JSON Schema](https://json-schema.org/overview/what-is-jsonschema), so you don't need to worry about the model omitting a required key, or hallucinating an invalid enum value.89Some benefits of Structured Outputs include:10111. **Reliable type-safety:** No need to validate or retry incorrectly formatted responses121. **Explicit refusals:** Safety-based model refusals are now programmatically detectable131. **Simpler prompting:** No need for strongly worded prompts to achieve consistent formatting1415In addition to supporting JSON Schema in the REST API, the OpenAI libraries for [Python](https://github.com/openai/openai-python/blob/main/helpers.md#structured-outputs-parsing-helpers) and [JavaScript](https://github.com/openai/openai-node/blob/master/helpers.md#structured-outputs-parsing-helpers) also let you define object schemas using [`pydantic.BaseModel`](https://docs.pydantic.dev/latest/) and [`z.object`](https://zod.dev/) respectively. Below, you can see how to extract information from unstructured text that conforms to a schema defined in code.1617The Ruby SDK supports schemas defined with Sorbet `T::Struct` and returns typed parsed results.18192021Getting a structured response2223```javascript24import OpenAI from "openai";25import { zodTextFormat } from "openai/helpers/zod";26import { z } from "zod";2728const openai = new OpenAI();2930const CalendarEvent = z.object({31  name: z.string(),32  date: z.string(),33  participants: z.array(z.string()),34});3536const response = await openai.responses.parse({37  model: "gpt-6-astra",38  input: [39    { role: "system", content: "Extract the event information." },40    {41      role: "user",42      content: "Alice and Bob are going to a science fair on Friday.",43    },44  ],45  text: {46    format: zodTextFormat(CalendarEvent, "event"),47  },48});4950const event = response.output_parsed;51```5253```python54from openai import OpenAI55from pydantic import BaseModel5657client = OpenAI()585960class CalendarEvent(BaseModel):61    name: str62    date: str63    participants: list[str]646566response = client.responses.parse(67    model="gpt-6-astra",68    input=[69        {"role": "system", "content": "Extract the event information."},70        {71            "role": "user",72            "content": "Alice and Bob are going to a science fair on Friday.",73        },74    ],75    text_format=CalendarEvent,76)7778event = response.output_parsed79```8081```go82package main8384import (85	"context"86	"fmt"8788	"github.com/openai/openai-go/v3"89	"github.com/openai/openai-go/v3/responses"90)9192func main() {93	client := openai.NewClient()94	schema := map[string]any{95		"type": "object",96		"properties": map[string]any{97			"name":         map[string]any{"type": "string"},98			"date":         map[string]any{"type": "string"},99			"participants": map[string]any{"type": "array", "items": map[string]any{"type": "string"}},100		},101		"required":             []string{"name", "date", "participants"},102		"additionalProperties": false,103	}104105	response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{106		Model: "gpt-6-astra",107		Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{108			responses.ResponseInputItemParamOfMessage(109				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("Extract the event information.")},110				responses.EasyInputMessageRoleSystem,111			),112			responses.ResponseInputItemParamOfMessage(113				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("Alice and Bob are going to a science fair on Friday.")},114				responses.EasyInputMessageRoleUser,115			),116		}},117		Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{118			OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "event", Schema: schema, Strict: openai.Bool(true)},119		}},120	})121	if err != nil {122		panic(err)123	}124125	fmt.Println(response.OutputText())126}127```128129```java130import com.openai.client.OpenAIClient;131import com.openai.client.okhttp.OpenAIOkHttpClient;132import com.openai.core.JsonValue;133import com.openai.models.responses.EasyInputMessage;134import com.openai.models.responses.ResponseCreateParams;135import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;136import com.openai.models.responses.ResponseInputItem;137import com.openai.models.responses.ResponseTextConfig;138import java.util.List;139import java.util.Map;140141Map<String, Object> schema =142    Map.of(143        "type",144        "object",145        "properties",146        Map.of(147            "name", Map.of("type", "string"),148            "date", Map.of("type", "string"),149            "participants", Map.of("type", "array", "items", Map.of("type", "string"))),150        "required",151        List.of("name", "date", "participants"),152        "additionalProperties",153        false);154155ResponseCreateParams params =156    ResponseCreateParams.builder()157        .model("gpt-6-astra")158        .inputOfResponse(159            List.of(160                ResponseInputItem.ofEasyInputMessage(161                    EasyInputMessage.builder()162                        .role(EasyInputMessage.Role.SYSTEM)163                        .content("Extract the event information.")164                        .build()),165                ResponseInputItem.ofEasyInputMessage(166                    EasyInputMessage.builder()167                        .role(EasyInputMessage.Role.USER)168                        .content("Alice and Bob are going to a science fair on Friday.")169                        .build())))170        .text(171            ResponseTextConfig.builder()172                .format(173                    ResponseFormatTextJsonSchemaConfig.builder()174                        .name("event")175                        .strict(true)176                        .schema(177                            JsonValue.from(schema)178                                .convert(ResponseFormatTextJsonSchemaConfig.Schema.class))179                        .build())180                .build())181        .build();182183client.responses().create(params).output().stream()184    .flatMap(item -> item.message().stream())185    .flatMap(message -> message.content().stream())186    .flatMap(content -> content.outputText().stream())187    .forEach(text -> System.out.println(text.text()));188```189190```csharp191using OpenAI.Responses;192#pragma warning disable OPENAI001193194string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;195ResponsesClient client = new(key);196197BinaryData schema = BinaryData.FromString(198    """199    {200      "type": "object",201      "properties": {202        "name": { "type": "string" },203        "date": { "type": "string" },204        "participants": {205          "type": "array",206          "items": { "type": "string" }207        }208      },209      "required": ["name", "date", "participants"],210      "additionalProperties": false211    }212    """213);214CreateResponseOptions options = new()215{216    Model = "gpt-6-astra",217    TextOptions = new ResponseTextOptions218    {219        TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(220            "event",221            schema,222            jsonSchemaIsStrict: true223        ),224    },225};226options.InputItems.Add(227    ResponseItem.CreateSystemMessageItem("Extract the event information.")228);229options.InputItems.Add(230    ResponseItem.CreateUserMessageItem(231        "Alice and Bob are going to a science fair on Friday."232    )233);234235ResponseResult response = await client.CreateResponseAsync(options);236237Console.WriteLine(response.GetOutputText());238```239240```ruby241# gem install openai sorbet-runtime242require "openai"243require "openai/helpers/sorbet"244245class CalendarEvent < T::Struct246  const :name, String247  const :date, String248  const :participants, T::Array[String]249end250251client = OpenAI::Client.new252schema = OpenAI::StructuredOutput.from_sorbet(CalendarEvent)253254response = client.responses.create(255  model: "gpt-6-astra",256  input: [257    {258      role: :system,259      content: "Extract the event information."260    },261    {262      role: :user,263      content: "Alice and Bob are going to a science fair on Friday."264    }265  ],266  text: schema267)268269raise "Response ended with status: #{response.status}" unless response.status == OpenAI::Responses::ResponseStatus::COMPLETED270271message = response.output.grep(OpenAI::Responses::ResponseOutputMessage).fetch(0)272output_text = message.content.grep(OpenAI::Responses::ResponseOutputText).first273raise "No structured output returned (the model may have refused)" unless output_text274275event = T.cast(output_text.parsed, CalendarEvent)276puts(event.name, event.date, event.participants.join(", "))277```278279280281### Supported models282283Structured Outputs is available in our [latest large language models](https://developers.openai.com/api/docs/models), starting with GPT-4o. For new projects, start with [`gpt-6-astra`](https://developers.openai.com/api/docs/models/gpt-6-astra). Older models like `gpt-4-turbo` and earlier may use [JSON mode](#json-mode) instead.284285286287288  289290When to use Structured Outputs via function calling vs via 291    292text.format293294295296297Structured Outputs is available in two forms in the OpenAI API:2982991. When using [function calling](https://developers.openai.com/api/docs/guides/function-calling)3002. When using a `json_schema` response format301302Function calling is useful when you are building an application that bridges the models and functionality of your application.303304For example, you can give the model access to functions that query a database in order to build an AI assistant that can help users with their orders, or functions that can interact with the UI.305306Conversely, Structured Outputs via `response_format` are more suitable when you want to indicate a structured schema for use when the model responds to the user, rather than when the model calls a tool.307308For example, if you are building a math tutoring application, you might want the assistant to respond to your user using a specific JSON Schema so that you can generate a UI that displays different parts of the model's output in distinct ways.309310In practice:311312313314315  - If you are connecting the model to tools, functions, data, etc. in your316  system, then you should use function calling - If you want to structure the317  model's output when it responds to the user, then you should use a structured318  `text.format`319320321322323324  The remainder of this guide will focus on non-function calling use cases in325    the Responses API. To learn more about how to use Structured Outputs with326    function calling, check out the 327    [Function Calling](https://developers.openai.com/api/docs/guides/function-calling#strict-mode) 328    guide.329330331### Structured Outputs vs JSON mode332333Structured Outputs is the evolution of [JSON mode](#json-mode). While both ensure valid JSON is produced, only Structured Outputs ensure schema adherence. Both Structured Outputs and JSON mode are supported in the Responses API, Chat Completions API, Assistants API, Fine-tuning API and Batch API.334335We recommend always using Structured Outputs instead of JSON mode when possible.336337However, Structured Outputs with `response_format: {type: "json_schema", ...}` is only supported with the `gpt-4o-mini`, `gpt-4o-mini-2024-07-18`, and `gpt-4o-2024-08-06` model snapshots and later.338339340341342|                                            | Structured Outputs                                                                                                             | JSON Mode                                  |343|--------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|344| **Outputs valid JSON**                     | Yes                                                                                                                            | Yes                                        |345| **Adheres to schema**                      | Yes (see [supported schemas](#supported-schemas))                                               | No                                         |346| **Compatible models**                      | `gpt-4o-mini`, `gpt-4o-2024-08-06`, and later                                                                                  | `gpt-3.5-turbo`, `gpt-4-*`, `gpt-4o-*`, and compatible GPT-5 models |347| **Enabling**                               | `text: { format: { type: "json_schema", "strict": true, "schema": ... } }`                                       | `text: { format: { type: "json_object" } }` |348349350## Examples351352353354Chain of thought355356    357358### Chain of thought359360You can ask the model to output an answer in a structured, step-by-step way, to guide the user through the solution.361362363364365  Structured Outputs for chain-of-thought math tutoring366367```javascript368import OpenAI from "openai";369import { zodTextFormat } from "openai/helpers/zod";370import { z } from "zod";371372const openai = new OpenAI();373374const Step = z.object({375  explanation: z.string(),376  output: z.string(),377});378379const MathReasoning = z.object({380  steps: z.array(Step),381  final_answer: z.string(),382});383384const response = await openai.responses.parse({385  model: "gpt-6-astra",386  input: [387    {388      role: "system",389      content:390        "You are a helpful math tutor. Guide the user through the solution step by step.",391    },392    { role: "user", content: "how can I solve 8x + 7 = -23" },393  ],394  text: {395    format: zodTextFormat(MathReasoning, "math_reasoning"),396  },397});398399const math_reasoning = response.output_parsed;400```401402```python403from openai import OpenAI404from pydantic import BaseModel405406client = OpenAI()407408409class Step(BaseModel):410    explanation: str411    output: str412413414class MathReasoning(BaseModel):415    steps: list[Step]416    final_answer: str417418419response = client.responses.parse(420    model="gpt-6-astra",421    input=[422        {423            "role": "system",424            "content": "You are a helpful math tutor. Guide the user through the solution step by step.",425        },426        {"role": "user", "content": "how can I solve 8x + 7 = -23"},427    ],428    text_format=MathReasoning,429)430431math_reasoning = response.output_parsed432```433434```go435package main436437import (438	"context"439	"fmt"440441	"github.com/openai/openai-go/v3"442	"github.com/openai/openai-go/v3/responses"443)444445func main() {446	client := openai.NewClient()447	step := map[string]any{448		"type": "object",449		"properties": map[string]any{450			"explanation": map[string]any{"type": "string"},451			"output":      map[string]any{"type": "string"},452		},453		"required":             []string{"explanation", "output"},454		"additionalProperties": false,455	}456	schema := map[string]any{457		"type": "object",458		"properties": map[string]any{459			"steps":        map[string]any{"type": "array", "items": step},460			"final_answer": map[string]any{"type": "string"},461		},462		"required":             []string{"steps", "final_answer"},463		"additionalProperties": false,464	}465466	response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{467		Model: "gpt-6-astra",468		Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{469			responses.ResponseInputItemParamOfMessage(470				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a helpful math tutor. Guide the user through the solution step by step.")},471				responses.EasyInputMessageRoleSystem,472			),473			responses.ResponseInputItemParamOfMessage(474				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("how can I solve 8x + 7 = -23")},475				responses.EasyInputMessageRoleUser,476			),477		}},478		Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{479			OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "math_reasoning", Schema: schema, Strict: openai.Bool(true)},480		}},481	})482	if err != nil {483		panic(err)484	}485486	fmt.Println(response.OutputText())487}488```489490```java491import com.openai.client.OpenAIClient;492import com.openai.client.okhttp.OpenAIOkHttpClient;493import com.openai.core.JsonValue;494import com.openai.models.responses.EasyInputMessage;495import com.openai.models.responses.ResponseCreateParams;496import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;497import com.openai.models.responses.ResponseInputItem;498import com.openai.models.responses.ResponseTextConfig;499import java.util.List;500import java.util.Map;501502Map<String, Object> schema =503    Map.of(504        "type",505        "object",506        "properties",507        Map.of(508            "steps",509                Map.of(510                    "type",511                    "array",512                    "items",513                    Map.of(514                        "type",515                        "object",516                        "properties",517                        Map.of(518                            "explanation", Map.of("type", "string"),519                            "output", Map.of("type", "string")),520                        "required",521                        List.of("explanation", "output"),522                        "additionalProperties",523                        false)),524            "final_answer", Map.of("type", "string")),525        "required",526        List.of("steps", "final_answer"),527        "additionalProperties",528        false);529530ResponseCreateParams params =531    ResponseCreateParams.builder()532        .model("gpt-6-astra")533        .inputOfResponse(534            List.of(535                ResponseInputItem.ofEasyInputMessage(536                    EasyInputMessage.builder()537                        .role(EasyInputMessage.Role.SYSTEM)538                        .content(539                            "You are a helpful math tutor. Guide the user through the solution step by step.")540                        .build()),541                ResponseInputItem.ofEasyInputMessage(542                    EasyInputMessage.builder()543                        .role(EasyInputMessage.Role.USER)544                        .content("How can I solve 8x + 7 = -23?")545                        .build())))546        .text(547            ResponseTextConfig.builder()548                .format(549                    ResponseFormatTextJsonSchemaConfig.builder()550                        .name("math_reasoning")551                        .strict(true)552                        .schema(553                            JsonValue.from(schema)554                                .convert(ResponseFormatTextJsonSchemaConfig.Schema.class))555                        .build())556                .build())557        .build();558559client.responses().create(params).output().stream()560    .flatMap(item -> item.message().stream())561    .flatMap(message -> message.content().stream())562    .flatMap(content -> content.outputText().stream())563    .forEach(text -> System.out.println(text.text()));564```565566```csharp567using System.Text.Json;568using OpenAI.Responses;569#pragma warning disable OPENAI001570571string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;572ResponsesClient client = new(key);573574BinaryData schema = BinaryData.FromString(575    """576    {577      "type": "object",578      "properties": {579        "steps": {580          "type": "array",581          "items": {582            "type": "object",583            "properties": {584              "explanation": { "type": "string" },585              "output": { "type": "string" }586            },587            "required": ["explanation", "output"],588            "additionalProperties": false589          }590        },591        "final_answer": { "type": "string" }592      },593      "required": ["steps", "final_answer"],594      "additionalProperties": false595    }596    """597);598CreateResponseOptions options = new()599{600    Model = "gpt-6-astra",601    TextOptions = new ResponseTextOptions602    {603        TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(604            "math_response",605            schema,606            jsonSchemaIsStrict: true607        ),608    },609};610options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a helpful math tutor. Guide the user through the solution step by step."));611options.InputItems.Add(ResponseItem.CreateUserMessageItem("How can I solve 8x + 7 = -23?"));612613ResponseResult response = await client.CreateResponseAsync(options);614using JsonDocument parsed = JsonDocument.Parse(response.GetOutputText());615Console.WriteLine(parsed.RootElement);616```617618```ruby619require "openai"620621client = OpenAI::Client.new622step_schema = {623  type: :object,624  properties: {625    explanation: { type: :string },626    output: { type: :string }627  },628  required: %w[explanation output],629  additionalProperties: false630}631math_schema = {632  type: :object,633  properties: {634    steps: {635      type: :array,636      items: step_schema637    },638    final_answer: { type: :string }639  },640  required: %w[steps final_answer],641  additionalProperties: false642}643644response = client.responses.create(645  model: "gpt-6-astra",646  input: [647    {648      role: :system,649      content: "You are a helpful math tutor. Guide the user through the solution step by step."650    },651    {652      role: :user,653      content: "How can I solve 8x + 7 = -23?"654    }655  ],656  text: {657    format: {658      type: :json_schema,659      name: "math_reasoning",660      strict: true,661      schema: math_schema662    }663  }664)665666puts(response.output_text)667```668669```bash670curl https://api.openai.com/v1/responses \671  -H "Authorization: Bearer $OPENAI_API_KEY" \672  -H "Content-Type: application/json" \673  -d '{674    "model": "gpt-6-astra",675    "input": [676      {677        "role": "system",678        "content": "You are a helpful math tutor. Guide the user through the solution step by step."679      },680      {681        "role": "user",682        "content": "how can I solve 8x + 7 = -23"683      }684    ],685    "text": {686      "format": {687        "type": "json_schema",688        "name": "math_reasoning",689        "schema": {690          "type": "object",691          "properties": {692            "steps": {693              "type": "array",694              "items": {695                "type": "object",696                "properties": {697                  "explanation": { "type": "string" },698                  "output": { "type": "string" }699                },700                "required": ["explanation", "output"],701                "additionalProperties": false702              }703            },704            "final_answer": { "type": "string" }705          },706          "required": ["steps", "final_answer"],707          "additionalProperties": false708        },709        "strict": true710      }711    }712  }'713```714715716717#### Example response718719```json720{721  "steps": [722    {723      "explanation": "Start with the equation 8x + 7 = -23.",724      "output": "8x + 7 = -23"725    },726    {727      "explanation": "Subtract 7 from both sides to isolate the term with the variable.",728      "output": "8x = -23 - 7"729    },730    {731      "explanation": "Simplify the right side of the equation.",732      "output": "8x = -30"733    },734    {735      "explanation": "Divide both sides by 8 to solve for x.",736      "output": "x = -30 / 8"737    },738    {739      "explanation": "Simplify the fraction.",740      "output": "x = -15 / 4"741    }742  ],743  "final_answer": "x = -15 / 4"744}745```746747748  749750  751752    753Structured data extraction754755    756757### Structured data extraction758759You can define structured fields to extract from unstructured input data, such as research papers.760761762763  Extracting data from research papers using Structured Outputs764765```javascript766import OpenAI from "openai";767import { zodTextFormat } from "openai/helpers/zod";768import { z } from "zod";769770const openai = new OpenAI();771772const ResearchPaperExtraction = z.object({773  title: z.string(),774  authors: z.array(z.string()),775  abstract: z.string(),776  keywords: z.array(z.string()),777});778779const response = await openai.responses.parse({780  model: "gpt-6-astra",781  input: [782    {783      role: "system",784      content:785        "You are an expert at structured data extraction. You will be given unstructured text from a research paper and should convert it into the given structure.",786    },787    { role: "user", content: "..." },788  ],789  text: {790    format: zodTextFormat(ResearchPaperExtraction, "research_paper_extraction"),791  },792});793794const research_paper = response.output_parsed;795```796797```python798from openai import OpenAI799from pydantic import BaseModel800801client = OpenAI()802803804class ResearchPaperExtraction(BaseModel):805    title: str806    authors: list[str]807    abstract: str808    keywords: list[str]809810811response = client.responses.parse(812    model="gpt-6-astra",813    input=[814        {815            "role": "system",816            "content": "You are an expert at structured data extraction. You will be given unstructured text from a research paper and should convert it into the given structure.",817        },818        {819            "role": "user",820            "content": (821                "Attention Is All You Need by Ashish Vaswani, Noam Shazeer, "822                "Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, "823                "Łukasz Kaiser, and Illia Polosukhin. We propose the "824                "Transformer, a sequence transduction architecture based "825                "entirely on attention. Keywords: transformers, attention, "826                "sequence transduction."827            ),828        },829    ],830    text_format=ResearchPaperExtraction,831)832833research_paper = response.output_parsed834```835836```go837package main838839import (840	"context"841	"fmt"842843	"github.com/openai/openai-go/v3"844	"github.com/openai/openai-go/v3/responses"845)846847const researchPaperText = "Attention Is All You Need by Ashish Vaswani, Noam Shazeer, " +848	"Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, " +849	"Łukasz Kaiser, and Illia Polosukhin. We propose the Transformer, " +850	"a sequence transduction architecture based entirely on attention. " +851	"Keywords: transformers, attention, sequence transduction."852853func main() {854	client := openai.NewClient()855	schema := map[string]any{856		"type": "object",857		"properties": map[string]any{858			"title":    map[string]any{"type": "string"},859			"authors":  map[string]any{"type": "array", "items": map[string]any{"type": "string"}},860			"abstract": map[string]any{"type": "string"},861			"keywords": map[string]any{"type": "array", "items": map[string]any{"type": "string"}},862		},863		"required":             []string{"title", "authors", "abstract", "keywords"},864		"additionalProperties": false,865	}866867	response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{868		Model: "gpt-6-astra",869		Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{870			responses.ResponseInputItemParamOfMessage(871				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are an expert at structured data extraction. You will be given unstructured text from a research paper and should convert it into the given structure.")},872				responses.EasyInputMessageRoleSystem,873			),874			responses.ResponseInputItemParamOfMessage(875				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText(researchPaperText)},876				responses.EasyInputMessageRoleUser,877			),878		}},879		Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{880			OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "research_paper_extraction", Schema: schema, Strict: openai.Bool(true)},881		}},882	})883	if err != nil {884		panic(err)885	}886887	fmt.Println(response.OutputText())888}889```890891```java892import com.openai.client.OpenAIClient;893import com.openai.client.okhttp.OpenAIOkHttpClient;894import com.openai.core.JsonValue;895import com.openai.models.responses.EasyInputMessage;896import com.openai.models.responses.ResponseCreateParams;897import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;898import com.openai.models.responses.ResponseInputItem;899import com.openai.models.responses.ResponseTextConfig;900import java.util.List;901import java.util.Map;902903Map<String, Object> schema =904    Map.of(905        "type",906        "object",907        "properties",908        Map.of(909            "title", Map.of("type", "string"),910            "authors", Map.of("type", "array", "items", Map.of("type", "string")),911            "abstract", Map.of("type", "string"),912            "keywords", Map.of("type", "array", "items", Map.of("type", "string"))),913        "required",914        List.of("title", "authors", "abstract", "keywords"),915        "additionalProperties",916        false);917918ResponseCreateParams params =919    ResponseCreateParams.builder()920        .model("gpt-6-astra")921        .inputOfResponse(922            List.of(923                ResponseInputItem.ofEasyInputMessage(924                    EasyInputMessage.builder()925                        .role(EasyInputMessage.Role.SYSTEM)926                        .content(927                            "You are an expert at structured data extraction. You will be given"928                                + " unstructured text from a research paper and should convert"929                                + " it into the given structure.")930                        .build()),931                ResponseInputItem.ofEasyInputMessage(932                    EasyInputMessage.builder()933                        .role(EasyInputMessage.Role.USER)934                        .content(935                            "Attention Is All You Need by Ashish Vaswani, Noam Shazeer,"936                                + " Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez,"937                                + " Łukasz Kaiser, and Illia Polosukhin. We propose the"938                                + " Transformer, a"939                                + " sequence transduction architecture based entirely on"940                                + " attention. Keywords: transformers, attention, sequence"941                                + " transduction.")942                        .build())))943        .text(944            ResponseTextConfig.builder()945                .format(946                    ResponseFormatTextJsonSchemaConfig.builder()947                        .name("research_paper_extraction")948                        .strict(true)949                        .schema(950                            JsonValue.from(schema)951                                .convert(ResponseFormatTextJsonSchemaConfig.Schema.class))952                        .build())953                .build())954        .build();955956client.responses().create(params).output().stream()957    .flatMap(item -> item.message().stream())958    .flatMap(message -> message.content().stream())959    .flatMap(content -> content.outputText().stream())960    .forEach(text -> System.out.println(text.text()));961```962963```csharp964using System.Text.Json;965using OpenAI.Responses;966#pragma warning disable OPENAI001967968string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;969ResponsesClient client = new(key);970971BinaryData schema = BinaryData.FromString(972    """973    {974      "type": "object",975      "properties": {976        "title": { "type": "string" },977        "authors": { "type": "array", "items": { "type": "string" } },978        "abstract": { "type": "string" },979        "keywords": { "type": "array", "items": { "type": "string" } }980      },981      "required": ["title", "authors", "abstract", "keywords"],982      "additionalProperties": false983    }984    """985);986CreateResponseOptions options = new()987{988    Model = "gpt-6-astra",989    TextOptions = new ResponseTextOptions990    {991        TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(992            "research_paper",993            schema,994            jsonSchemaIsStrict: true995        ),996    },997};998options.InputItems.Add(ResponseItem.CreateSystemMessageItem("Extract the title, authors, abstract, and keywords from the research paper."));999options.InputItems.Add(1000    ResponseItem.CreateUserMessageItem(1001        """1002        Attention Is All You Need by Ashish Vaswani, Noam Shazeer,1003        Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez,1004        Łukasz Kaiser, and Illia Polosukhin. We propose the1005        Transformer, a sequence transduction architecture based1006        entirely on attention. Keywords: transformers, attention,1007        sequence transduction.1008        """1009    )1010);10111012ResponseResult response = await client.CreateResponseAsync(options);1013using JsonDocument parsed = JsonDocument.Parse(response.GetOutputText());1014Console.WriteLine(parsed.RootElement);1015```10161017```ruby1018require "openai"10191020client = OpenAI::Client.new1021research_paper = <<~TEXT1022  Attention Is All You Need by Ashish Vaswani, Noam Shazeer, Niki Parmar,1023  Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Łukasz Kaiser, and Illia1024  Polosukhin. We propose the Transformer, a sequence transduction architecture1025  based entirely on attention. Keywords: transformers, attention, sequence1026  transduction.1027TEXT1028paper_schema = {1029  type: :object,1030  properties: {1031    title: { type: :string },1032    authors: {1033      type: :array,1034      items: { type: :string }1035    },1036    abstract: { type: :string },1037    keywords: {1038      type: :array,1039      items: { type: :string }1040    }1041  },1042  required: %w[title authors abstract keywords],1043  additionalProperties: false1044}10451046response = client.responses.create(1047  model: "gpt-6-astra",1048  input: [1049    {1050      role: :system,1051      content: "Extract structured data from the supplied research paper text."1052    },1053    {1054      role: :user,1055      content: research_paper1056    }1057  ],1058  text: {1059    format: {1060      type: :json_schema,1061      name: "research_paper_extraction",1062      strict: true,1063      schema: paper_schema1064    }1065  }1066)10671068puts(response.output_text)1069```10701071```bash1072curl https://api.openai.com/v1/responses \1073  -H "Authorization: Bearer $OPENAI_API_KEY" \1074  -H "Content-Type: application/json" \1075  -d '{1076    "model": "gpt-6-astra",1077    "input": [1078      {1079        "role": "system",1080        "content": "You are an expert at structured data extraction. You will be given unstructured text from a research paper and should convert it into the given structure."1081      },1082      {1083        "role": "user",1084        "content": "..."1085      }1086    ],1087    "text": {1088      "format": {1089        "type": "json_schema",1090        "name": "research_paper_extraction",1091        "schema": {1092          "type": "object",1093          "properties": {1094            "title": { "type": "string" },1095            "authors": {1096              "type": "array",1097              "items": { "type": "string" }1098            },1099            "abstract": { "type": "string" },1100            "keywords": {1101              "type": "array",1102              "items": { "type": "string" }1103            }1104          },1105          "required": ["title", "authors", "abstract", "keywords"],1106          "additionalProperties": false1107        },1108        "strict": true1109      }1110    }1111  }'1112```1113111411151116#### Example response11171118```json1119{1120  "title": "Application of Quantum Algorithms in Interstellar Navigation: A New Frontier",1121  "authors": ["Dr. Stella Voyager", "Dr. Nova Star", "Dr. Lyra Hunter"],1122  "abstract": "This paper investigates the utilization of quantum algorithms to improve interstellar navigation systems. By leveraging quantum superposition and entanglement, our proposed navigation system can calculate optimal travel paths through space-time anomalies more efficiently than classical methods. Experimental simulations suggest a significant reduction in travel time and fuel consumption for interstellar missions.",1123  "keywords": [1124    "Quantum algorithms",1125    "interstellar navigation",1126    "space-time anomalies",1127    "quantum superposition",1128    "quantum entanglement",1129    "space travel"1130  ]1131}1132```113311341135  11361137  11381139    1140UI generation11411142    11431144### UI Generation11451146You can generate valid HTML by representing it as recursive data structures with constraints, like enums.11471148114911501151  Generating HTML using Structured Outputs11521153```javascript1154import OpenAI from "openai";1155import { zodTextFormat } from "openai/helpers/zod";1156import { z } from "zod";11571158const openai = new OpenAI();11591160const UI = z.lazy(() =>1161  z.object({1162    type: z.enum(["div", "button", "header", "section", "field", "form"]),1163    label: z.string(),1164    children: z.array(UI),1165    attributes: z.array(1166      z.object({1167        name: z.string(),1168        value: z.string(),1169      })1170    ),1171  })1172);11731174const response = await openai.responses.parse({1175  model: "gpt-6-astra",1176  input: [1177    {1178      role: "system",1179      content: "You are a UI generator AI. Convert the user input into a UI.",1180    },1181    {1182      role: "user",1183      content: "Make a User Profile Form",1184    },1185  ],1186  text: {1187    format: zodTextFormat(UI, "ui"),1188  },1189});11901191const ui = response.output_parsed;1192```11931194```python1195from enum import Enum11961197from openai import OpenAI1198from pydantic import BaseModel11991200client = OpenAI()120112021203class UIType(str, Enum):1204    div = "div"1205    button = "button"1206    header = "header"1207    section = "section"1208    field = "field"1209    form = "form"121012111212class Attribute(BaseModel):1213    name: str1214    value: str121512161217class UI(BaseModel):1218    type: UIType1219    label: str1220    children: list["UI"]1221    attributes: list[Attribute]122212231224UI.model_rebuild()  # This is required to enable recursive types122512261227class Response(BaseModel):1228    ui: UI122912301231response = client.responses.parse(1232    model="gpt-6-astra",1233    input=[1234        {1235            "role": "system",1236            "content": "You are a UI generator AI. Convert the user input into a UI.",1237        },1238        {"role": "user", "content": "Make a User Profile Form"},1239    ],1240    text_format=Response,1241)12421243ui = response.output_parsed1244```12451246```go1247package main12481249import (1250	"context"1251	"fmt"12521253	"github.com/openai/openai-go/v3"1254	"github.com/openai/openai-go/v3/responses"1255)12561257func main() {1258	client := openai.NewClient()1259	schema := map[string]any{1260		"type": "object",1261		"properties": map[string]any{1262			"type":       map[string]any{"type": "string", "enum": []string{"div", "button", "header", "section", "field", "form"}},1263			"label":      map[string]any{"type": "string"},1264			"children":   map[string]any{"type": "array", "items": map[string]any{"$ref": "#"}},1265			"attributes": map[string]any{"type": "array", "items": map[string]any{"type": "object", "properties": map[string]any{"name": map[string]any{"type": "string"}, "value": map[string]any{"type": "string"}}, "required": []string{"name", "value"}, "additionalProperties": false}},1266		},1267		"required":             []string{"type", "label", "children", "attributes"},1268		"additionalProperties": false,1269	}12701271	response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{1272		Model: "gpt-6-astra",1273		Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{1274			responses.ResponseInputItemParamOfMessage(1275				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a UI generator AI. Convert the user input into a UI.")},1276				responses.EasyInputMessageRoleSystem,1277			),1278			responses.ResponseInputItemParamOfMessage(1279				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("Make a User Profile Form")},1280				responses.EasyInputMessageRoleUser,1281			),1282		}},1283		Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{1284			OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "ui", Description: openai.String("Dynamically generated UI"), Schema: schema, Strict: openai.Bool(true)},1285		}},1286	})1287	if err != nil {1288		panic(err)1289	}12901291	fmt.Println(response.OutputText())1292}1293```12941295```java1296import com.openai.client.OpenAIClient;1297import com.openai.client.okhttp.OpenAIOkHttpClient;1298import com.openai.core.JsonValue;1299import com.openai.models.responses.EasyInputMessage;1300import com.openai.models.responses.ResponseCreateParams;1301import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;1302import com.openai.models.responses.ResponseInputItem;1303import com.openai.models.responses.ResponseTextConfig;1304import java.util.List;1305import java.util.Map;13061307ResponseCreateParams params =1308    ResponseCreateParams.builder()1309        .model("gpt-6-astra")1310        .inputOfResponse(1311            List.of(1312                ResponseInputItem.ofEasyInputMessage(1313                    EasyInputMessage.builder()1314                        .role(EasyInputMessage.Role.SYSTEM)1315                        .content("Convert the user request into a UI definition.")1316                        .build()),1317                ResponseInputItem.ofEasyInputMessage(1318                    EasyInputMessage.builder()1319                        .role(EasyInputMessage.Role.USER)1320                        .content("Make a user profile form.")1321                        .build())))1322        .text(1323            ResponseTextConfig.builder()1324                .format(1325                    ResponseFormatTextJsonSchemaConfig.builder()1326                        .name("ui")1327                        .description("A dynamically generated UI")1328                        .strict(true)1329                        .schema(1330                            ResponseFormatTextJsonSchemaConfig.Schema.builder()1331                                .putAdditionalProperty("type", JsonValue.from("object"))1332                                .putAdditionalProperty(1333                                    "properties",1334                                    JsonValue.from(1335                                        Map.of(1336                                            "type",1337                                                Map.of(1338                                                    "type",1339                                                    "string",1340                                                    "enum",1341                                                    List.of(1342                                                        "div", "button", "header", "section",1343                                                        "field", "form")),1344                                            "label", Map.of("type", "string"),1345                                            "children",1346                                                Map.of(1347                                                    "type",1348                                                    "array",1349                                                    "items",1350                                                    Map.of("$ref", "#")),1351                                            "attributes",1352                                                Map.of(1353                                                    "type",1354                                                    "array",1355                                                    "items",1356                                                    Map.of(1357                                                        "type",1358                                                        "object",1359                                                        "properties",1360                                                        Map.of(1361                                                            "name", Map.of("type", "string"),1362                                                            "value", Map.of("type", "string")),1363                                                        "required",1364                                                        List.of("name", "value"),1365                                                        "additionalProperties",1366                                                        false)))))1367                                .putAdditionalProperty(1368                                    "required",1369                                    JsonValue.from(1370                                        List.of("type", "label", "children", "attributes")))1371                                .putAdditionalProperty(1372                                    "additionalProperties", JsonValue.from(false))1373                                .build())1374                        .build())1375                .build())1376        .build();13771378client.responses().create(params).output().stream()1379    .flatMap(item -> item.message().stream())1380    .flatMap(message -> message.content().stream())1381    .flatMap(content -> content.outputText().stream())1382    .forEach(text -> System.out.println(text.text()));1383```13841385```csharp1386using System.Text.Json;1387using OpenAI.Responses;1388#pragma warning disable OPENAI00113891390string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;1391ResponsesClient client = new(key);13921393BinaryData schema = BinaryData.FromString(1394    """1395    {1396      "type": "object",1397      "properties": {1398        "ui": { "$ref": "#/$defs/component" }1399      },1400      "required": ["ui"],1401      "additionalProperties": false,1402      "$defs": {1403        "component": {1404          "type": "object",1405          "properties": {1406            "type": { "type": "string", "enum": ["div", "button", "header", "section", "field", "form"] },1407            "label": { "type": "string" },1408            "children": { "type": "array", "items": { "$ref": "#/$defs/component" } },1409            "attributes": {1410              "type": "array",1411              "items": {1412                "type": "object",1413                "properties": { "name": { "type": "string" }, "value": { "type": "string" } },1414                "required": ["name", "value"],1415                "additionalProperties": false1416              }1417            }1418          },1419          "required": ["type", "label", "children", "attributes"],1420          "additionalProperties": false1421        }1422      }1423    }1424    """1425);1426CreateResponseOptions options = new()1427{1428    Model = "gpt-6-astra",1429    TextOptions = new ResponseTextOptions1430    {1431        TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(1432            "ui",1433            schema,1434            jsonSchemaIsStrict: true1435        ),1436    },1437};1438options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a UI generator. Convert the user request into a component tree."));1439options.InputItems.Add(ResponseItem.CreateUserMessageItem("Make a User Profile Form"));14401441ResponseResult response = await client.CreateResponseAsync(options);1442using JsonDocument parsed = JsonDocument.Parse(response.GetOutputText());1443Console.WriteLine(parsed.RootElement);1444```14451446```ruby1447require "openai"14481449client = OpenAI::Client.new1450ui_schema = {1451  type: :object,1452  properties: {1453    type: {1454      type: :string,1455      enum: %w[div button header section field form]1456    },1457    label: { type: :string },1458    children: {1459      type: :array,1460      items: { "$ref" => "#" }1461    },1462    attributes: {1463      type: :array,1464      items: {1465        type: :object,1466        properties: {1467          name: { type: :string },1468          value: { type: :string }1469        },1470        required: %w[name value],1471        additionalProperties: false1472      }1473    }1474  },1475  required: %w[type label children attributes],1476  additionalProperties: false1477}14781479response = client.responses.create(1480  model: "gpt-6-astra",1481  input: [1482    {1483      role: :system,1484      content: "Convert the user request into a UI definition."1485    },1486    {1487      role: :user,1488      content: "Make a user profile form."1489    }1490  ],1491  text: {1492    format: {1493      type: :json_schema,1494      name: "ui",1495      description: "A dynamically generated UI",1496      strict: true,1497      schema: ui_schema1498    }1499  }1500)15011502puts(response.output_text)1503```15041505```bash1506curl https://api.openai.com/v1/responses \1507  -H "Authorization: Bearer $OPENAI_API_KEY" \1508  -H "Content-Type: application/json" \1509  -d '{1510    "model": "gpt-6-astra",1511    "input": [1512      {1513        "role": "system",1514        "content": "You are a UI generator AI. Convert the user input into a UI."1515      },1516      {1517        "role": "user",1518        "content": "Make a User Profile Form"1519      }1520    ],1521    "text": {1522      "format": {1523        "type": "json_schema",1524        "name": "ui",1525        "description": "Dynamically generated UI",1526        "schema": {1527          "type": "object",1528          "properties": {1529            "type": {1530              "type": "string",1531              "description": "The type of the UI component",1532              "enum": ["div", "button", "header", "section", "field", "form"]1533            },1534            "label": {1535              "type": "string",1536              "description": "The label of the UI component, used for buttons or form fields"1537            },1538            "children": {1539              "type": "array",1540              "description": "Nested UI components",1541              "items": {"$ref": "#"}1542            },1543            "attributes": {1544              "type": "array",1545              "description": "Arbitrary attributes for the UI component, suitable for any element",1546              "items": {1547                "type": "object",1548                "properties": {1549                  "name": {1550                    "type": "string",1551                    "description": "The name of the attribute, for example onClick or className"1552                  },1553                  "value": {1554                    "type": "string",1555                    "description": "The value of the attribute"1556                  }1557                },1558                "required": ["name", "value"],1559                "additionalProperties": false1560              }1561            }1562          },1563          "required": ["type", "label", "children", "attributes"],1564          "additionalProperties": false1565        },1566        "strict": true1567      }1568    }1569  }'1570```1571157215731574#### Example response15751576```json1577{1578  "type": "form",1579  "label": "User Profile Form",1580  "children": [1581    {1582      "type": "div",1583      "label": "",1584      "children": [1585        {1586          "type": "field",1587          "label": "First Name",1588          "children": [],1589          "attributes": [1590            {1591              "name": "type",1592              "value": "text"1593            },1594            {1595              "name": "name",1596              "value": "firstName"1597            },1598            {1599              "name": "placeholder",1600              "value": "Enter your first name"1601            }1602          ]1603        },1604        {1605          "type": "field",1606          "label": "Last Name",1607          "children": [],1608          "attributes": [1609            {1610              "name": "type",1611              "value": "text"1612            },1613            {1614              "name": "name",1615              "value": "lastName"1616            },1617            {1618              "name": "placeholder",1619              "value": "Enter your last name"1620            }1621          ]1622        }1623      ],1624      "attributes": []1625    },1626    {1627      "type": "button",1628      "label": "Submit",1629      "children": [],1630      "attributes": [1631        {1632          "name": "type",1633          "value": "submit"1634        }1635      ]1636    }1637  ],1638  "attributes": [1639    {1640      "name": "method",1641      "value": "post"1642    },1643    {1644      "name": "action",1645      "value": "/submit-profile"1646    }1647  ]1648}1649```165016511652  16531654  16551656    1657Moderation16581659    16601661### Moderation16621663You can classify inputs on multiple categories, which is a common way of doing moderation.16641665166616671668  Moderation using Structured Outputs16691670```javascript1671import OpenAI from "openai";1672import { zodTextFormat } from "openai/helpers/zod";1673import { z } from "zod";16741675const openai = new OpenAI();16761677const ContentCompliance = z.object({1678  is_violating: z.boolean(),1679  category: z.enum(["violence", "sexual", "self_harm"]).nullable(),1680  explanation_if_violating: z.string().nullable(),1681});16821683const response = await openai.responses.parse({1684  model: "gpt-6-astra",1685  input: [1686    {1687      role: "system",1688      content:1689        "Determine if the user input violates specific guidelines and explain if they do.",1690    },1691    {1692      role: "user",1693      content: "How do I prepare for a job interview?",1694    },1695  ],1696  text: {1697    format: zodTextFormat(ContentCompliance, "content_compliance"),1698  },1699});17001701const compliance = response.output_parsed;1702```17031704```python1705from enum import Enum17061707from openai import OpenAI1708from pydantic import BaseModel17091710client = OpenAI()171117121713class Category(str, Enum):1714    violence = "violence"1715    sexual = "sexual"1716    self_harm = "self_harm"171717181719class ContentCompliance(BaseModel):1720    is_violating: bool1721    category: Category | None1722    explanation_if_violating: str | None172317241725response = client.responses.parse(1726    model="gpt-6-astra",1727    input=[1728        {1729            "role": "system",1730            "content": "Determine if the user input violates specific guidelines and explain if they do.",1731        },1732        {"role": "user", "content": "How do I prepare for a job interview?"},1733    ],1734    text_format=ContentCompliance,1735)17361737compliance = response.output_parsed1738```17391740```go1741package main17421743import (1744	"context"1745	"fmt"17461747	"github.com/openai/openai-go/v3"1748	"github.com/openai/openai-go/v3/responses"1749)17501751func main() {1752	client := openai.NewClient()1753	schema := contentComplianceSchema()1754	response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{1755		Model: "gpt-6-astra",1756		Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{1757			responses.ResponseInputItemParamOfMessage("Determine if the user input violates specific guidelines and explain if they do.", responses.EasyInputMessageRoleSystem),1758			responses.ResponseInputItemParamOfMessage("How do I prepare for a job interview?", responses.EasyInputMessageRoleUser),1759		}},1760		Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{1761			OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{1762				Name: "content_compliance", Description: openai.String("Determines if content is violating specific moderation rules"), Schema: schema, Strict: openai.Bool(true),1763			},1764		}},1765	})1766	if err != nil {1767		panic(err)1768	}1769	fmt.Println(response.OutputText())1770}17711772func contentComplianceSchema() map[string]any {1773	return map[string]any{1774		"type": "object",1775		"properties": map[string]any{1776			"is_violating":             map[string]any{"type": "boolean", "description": "Indicates if the content is violating guidelines"},1777			"category":                 map[string]any{"type": []string{"string", "null"}, "description": "Type of violation, if the content is violating guidelines. Null otherwise.", "enum": []any{"violence", "sexual", "self_harm", nil}},1778			"explanation_if_violating": map[string]any{"type": []string{"string", "null"}, "description": "Explanation of why the content is violating"},1779		},1780		"required":             []string{"is_violating", "category", "explanation_if_violating"},1781		"additionalProperties": false,1782	}1783}1784```17851786```java1787import com.openai.client.OpenAIClient;1788import com.openai.client.okhttp.OpenAIOkHttpClient;1789import com.openai.core.JsonValue;1790import com.openai.models.responses.EasyInputMessage;1791import com.openai.models.responses.ResponseCreateParams;1792import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;1793import com.openai.models.responses.ResponseInputItem;1794import com.openai.models.responses.ResponseTextConfig;1795import java.util.Arrays;1796import java.util.List;1797import java.util.Map;17981799Map<String, Object> schema =1800    Map.of(1801        "type",1802        "object",1803        "properties",1804        Map.of(1805            "is_violating",1806                Map.of(1807                    "type", "boolean",1808                    "description", "Whether the content violates the guidelines"),1809            "category",1810                Map.of(1811                    "type", List.of("string", "null"),1812                    "enum", Arrays.asList("violence", "sexual", "self_harm", null),1813                    "description", "The violation category, or null when content is allowed"),1814            "explanation_if_violating",1815                Map.of(1816                    "type",1817                    List.of("string", "null"),1818                    "description",1819                    "Why the content violates the guidelines, or null")),1820        "required",1821        List.of("is_violating", "category", "explanation_if_violating"),1822        "additionalProperties",1823        false);18241825ResponseCreateParams params =1826    ResponseCreateParams.builder()1827        .model("gpt-6-astra")1828        .inputOfResponse(1829            List.of(1830                ResponseInputItem.ofEasyInputMessage(1831                    EasyInputMessage.builder()1832                        .role(EasyInputMessage.Role.SYSTEM)1833                        .content(1834                            "Determine whether the user input violates the guidelines and explain any violation.")1835                        .build()),1836                ResponseInputItem.ofEasyInputMessage(1837                    EasyInputMessage.builder()1838                        .role(EasyInputMessage.Role.USER)1839                        .content("How do I prepare for a job interview?")1840                        .build())))1841        .text(1842            ResponseTextConfig.builder()1843                .format(1844                    ResponseFormatTextJsonSchemaConfig.builder()1845                        .name("content_compliance")1846                        .description("Determines whether content violates moderation rules")1847                        .strict(true)1848                        .schema(1849                            JsonValue.from(schema)1850                                .convert(ResponseFormatTextJsonSchemaConfig.Schema.class))1851                        .build())1852                .build())1853        .build();18541855client.responses().create(params).output().stream()1856    .flatMap(item -> item.message().stream())1857    .flatMap(message -> message.content().stream())1858    .flatMap(content -> content.outputText().stream())1859    .forEach(text -> System.out.println(text.text()));1860```18611862```csharp1863using System.Text.Json;1864using OpenAI.Responses;1865#pragma warning disable OPENAI00118661867string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;1868ResponsesClient client = new(key);18691870BinaryData schema = BinaryData.FromString(1871    """1872    {1873      "type": "object",1874      "properties": {1875        "is_violating": { "type": "boolean" },1876        "category": {1877          "type": ["string", "null"],1878          "enum": ["violence", "sexual", "self_harm", null]1879        },1880        "explanation_if_violating": { "type": ["string", "null"] }1881      },1882      "required": ["is_violating", "category", "explanation_if_violating"],1883      "additionalProperties": false1884    }1885    """1886);1887CreateResponseOptions options = new()1888{1889    Model = "gpt-6-astra",1890    TextOptions = new ResponseTextOptions1891    {1892        TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(1893            "content_compliance",1894            schema,1895            jsonSchemaIsStrict: true1896        ),1897    },1898};1899options.InputItems.Add(ResponseItem.CreateSystemMessageItem("Determine whether the user input violates content guidelines."));1900options.InputItems.Add(ResponseItem.CreateUserMessageItem("How do I prepare for a job interview?"));19011902ResponseResult response = await client.CreateResponseAsync(options);1903using JsonDocument parsed = JsonDocument.Parse(response.GetOutputText());1904Console.WriteLine(parsed.RootElement);1905```19061907```ruby1908require "openai"19091910client = OpenAI::Client.new1911compliance_schema = {1912  type: :object,1913  properties: {1914    is_violating: {1915      type: :boolean,1916      description: "Whether the content violates the guidelines"1917    },1918    category: {1919      type: %i[string null],1920      enum: ["violence", "sexual", "self_harm", nil],1921      description: "The violation category, or null when the content is allowed"1922    },1923    explanation_if_violating: {1924      type: %i[string null],1925      description: "Why the content violates the guidelines, or null"1926    }1927  },1928  required: %w[is_violating category explanation_if_violating],1929  additionalProperties: false1930}19311932response = client.responses.create(1933  model: "gpt-6-astra",1934  input: [1935    {1936      role: :system,1937      content: "Determine whether the user input violates the guidelines and explain any violation."1938    },1939    {1940      role: :user,1941      content: "How do I prepare for a job interview?"1942    }1943  ],1944  text: {1945    format: {1946      type: :json_schema,1947      name: "content_compliance",1948      description: "Determines whether content violates moderation rules",1949      strict: true,1950      schema: compliance_schema1951    }1952  }1953)19541955puts(response.output_text)1956```19571958```bash1959curl https://api.openai.com/v1/responses \1960  -H "Authorization: Bearer $OPENAI_API_KEY" \1961  -H "Content-Type: application/json" \1962  -d '{1963    "model": "gpt-6-astra",1964    "input": [1965      {1966        "role": "system",1967        "content": "Determine if the user input violates specific guidelines and explain if they do."1968      },1969      {1970        "role": "user",1971        "content": "How do I prepare for a job interview?"1972      }1973    ],1974    "text": {1975      "format": {1976        "type": "json_schema",1977        "name": "content_compliance",1978        "description": "Determines if content is violating specific moderation rules",1979        "schema": {1980          "type": "object",1981          "properties": {1982            "is_violating": {1983              "type": "boolean",1984              "description": "Indicates if the content is violating guidelines"1985            },1986            "category": {1987              "type": ["string", "null"],1988              "description": "Type of violation, if the content is violating guidelines. Null otherwise.",1989              "enum": ["violence", "sexual", "self_harm"]1990            },1991            "explanation_if_violating": {1992              "type": ["string", "null"],1993              "description": "Explanation of why the content is violating"1994            }1995          },1996          "required": ["is_violating", "category", "explanation_if_violating"],1997          "additionalProperties": false1998        },1999        "strict": true2000      }2001    }2002  }'2003```2004200520062007#### Example response20082009```json2010{2011  "is_violating": false,2012  "category": null,2013  "explanation_if_violating": null2014}2015```201620172018201920202021202220232024How to use Structured Outputs with 2025text.format20262027202820292030## Step 1: Define your schema2031203220332034First you must design the JSON Schema that the model should be constrained to follow. See the [examples](https://developers.openai.com/api/docs/guides/structured-outputs#examples) at the top of this guide for reference.20352036While Structured Outputs supports much of JSON Schema, some features are unavailable either for performance or technical reasons. See [here](https://developers.openai.com/api/docs/guides/structured-outputs#supported-schemas) for more details.20372038#### Tips for your JSON Schema20392040To maximize the quality of model generations, we recommend the following:20412042- Name keys clearly and intuitively2043- Create clear titles and descriptions for important keys in your structure2044- Create and use evals to determine the structure that works best for your use case20452046204720482049205020512052## Step 2: Supply your schema in the API call205320542055205620572058To use Structured Outputs, simply specify20592060206120622063```json2064text: { format: { type: "json_schema", "strict": true, "schema": … } }2065```206620672068For example:20692070207120722073```javascript2074const response = await openai.responses.create({2075  model: "gpt-6-astra",2076  input: [2077    {2078      role: "system",2079      content:2080        "You are a helpful math tutor. Guide the user through the solution step by step.",2081    },2082    { role: "user", content: "how can I solve 8x + 7 = -23" },2083  ],2084  text: {2085    format: {2086      type: "json_schema",2087      name: "math_response",2088      schema: {2089        type: "object",2090        properties: {2091          steps: {2092            type: "array",2093            items: {2094              type: "object",2095              properties: {2096                explanation: { type: "string" },2097                output: { type: "string" },2098              },2099              required: ["explanation", "output"],2100              additionalProperties: false,2101            },2102          },2103          final_answer: { type: "string" },2104        },2105        required: ["steps", "final_answer"],2106        additionalProperties: false,2107      },2108      strict: true,2109    },2110  },2111});21122113console.log(response.output_text);2114```21152116```python2117response = client.responses.create(2118    model="gpt-6-astra",2119    input=[2120        {2121            "role": "system",2122            "content": "You are a helpful math tutor. Guide the user through the solution step by step.",2123        },2124        {"role": "user", "content": "how can I solve 8x + 7 = -23"},2125    ],2126    text={2127        "format": {2128            "type": "json_schema",2129            "name": "math_response",2130            "schema": {2131                "type": "object",2132                "properties": {2133                    "steps": {2134                        "type": "array",2135                        "items": {2136                            "type": "object",2137                            "properties": {2138                                "explanation": {"type": "string"},2139                                "output": {"type": "string"},2140                            },2141                            "required": ["explanation", "output"],2142                            "additionalProperties": False,2143                        },2144                    },2145                    "final_answer": {"type": "string"},2146                },2147                "required": ["steps", "final_answer"],2148                "additionalProperties": False,2149            },2150            "strict": True,2151        },2152    },2153)21542155print(response.output_text)2156```21572158```go2159package main21602161import (2162	"context"2163	"fmt"21642165	"github.com/openai/openai-go/v3"2166	"github.com/openai/openai-go/v3/responses"2167)21682169func main() {2170	client := openai.NewClient()2171	response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{2172		Model: "gpt-6-astra",2173		Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{2174			responses.ResponseInputItemParamOfMessage(2175				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a helpful math tutor. Guide the user through the solution step by step.")},2176				responses.EasyInputMessageRoleSystem,2177			),2178			responses.ResponseInputItemParamOfMessage(2179				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("how can I solve 8x + 7 = -23")},2180				responses.EasyInputMessageRoleUser,2181			),2182		}},2183		Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{2184			OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "math_response", Schema: mathSchema(), Strict: openai.Bool(true)},2185		}},2186	})2187	if err != nil {2188		panic(err)2189	}2190	fmt.Println(response.OutputText())2191}21922193func mathSchema() map[string]any {2194	return map[string]any{2195		"type": "object",2196		"properties": map[string]any{2197			"steps":        map[string]any{"type": "array", "items": map[string]any{"type": "object", "properties": map[string]any{"explanation": map[string]any{"type": "string"}, "output": map[string]any{"type": "string"}}, "required": []string{"explanation", "output"}, "additionalProperties": false}},2198			"final_answer": map[string]any{"type": "string"},2199		},2200		"required":             []string{"steps", "final_answer"},2201		"additionalProperties": false,2202	}2203}2204```22052206```java2207import com.openai.client.OpenAIClient;2208import com.openai.client.okhttp.OpenAIOkHttpClient;2209import com.openai.core.JsonValue;2210import com.openai.models.responses.EasyInputMessage;2211import com.openai.models.responses.ResponseCreateParams;2212import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;2213import com.openai.models.responses.ResponseInputItem;2214import com.openai.models.responses.ResponseTextConfig;2215import java.util.List;2216import java.util.Map;22172218Map<String, Object> schema =2219    Map.of(2220        "type",2221        "object",2222        "properties",2223        Map.of(2224            "steps",2225                Map.of(2226                    "type",2227                    "array",2228                    "items",2229                    Map.of(2230                        "type",2231                        "object",2232                        "properties",2233                        Map.of(2234                            "explanation", Map.of("type", "string"),2235                            "output", Map.of("type", "string")),2236                        "required",2237                        List.of("explanation", "output"),2238                        "additionalProperties",2239                        false)),2240            "final_answer", Map.of("type", "string")),2241        "required",2242        List.of("steps", "final_answer"),2243        "additionalProperties",2244        false);22452246ResponseCreateParams params =2247    ResponseCreateParams.builder()2248        .model("gpt-6-astra")2249        .inputOfResponse(2250            List.of(2251                ResponseInputItem.ofEasyInputMessage(2252                    EasyInputMessage.builder()2253                        .role(EasyInputMessage.Role.SYSTEM)2254                        .content(2255                            "You are a helpful math tutor. Guide the user through the solution step by step.")2256                        .build()),2257                ResponseInputItem.ofEasyInputMessage(2258                    EasyInputMessage.builder()2259                        .role(EasyInputMessage.Role.USER)2260                        .content("How can I solve 8x + 7 = -23?")2261                        .build())))2262        .text(2263            ResponseTextConfig.builder()2264                .format(2265                    ResponseFormatTextJsonSchemaConfig.builder()2266                        .name("math_response")2267                        .strict(true)2268                        .schema(2269                            JsonValue.from(schema)2270                                .convert(ResponseFormatTextJsonSchemaConfig.Schema.class))2271                        .build())2272                .build())2273        .build();22742275client.responses().create(params).output().stream()2276    .flatMap(item -> item.message().stream())2277    .flatMap(message -> message.content().stream())2278    .flatMap(content -> content.outputText().stream())2279    .forEach(text -> System.out.println(text.text()));2280```22812282```csharp2283using System.Text.Json;2284using OpenAI.Responses;2285#pragma warning disable OPENAI00122862287string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;2288ResponsesClient client = new(key);22892290BinaryData schema = BinaryData.FromString(2291    """2292    {2293      "type": "object",2294      "properties": {2295        "steps": {2296          "type": "array",2297          "items": {2298            "type": "object",2299            "properties": {2300              "explanation": { "type": "string" },2301              "output": { "type": "string" }2302            },2303            "required": ["explanation", "output"],2304            "additionalProperties": false2305          }2306        },2307        "final_answer": { "type": "string" }2308      },2309      "required": ["steps", "final_answer"],2310      "additionalProperties": false2311    }2312    """2313);2314CreateResponseOptions options = new()2315{2316    Model = "gpt-6-astra",2317    TextOptions = new ResponseTextOptions2318    {2319        TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(2320            "math_response",2321            schema,2322            jsonSchemaIsStrict: true2323        ),2324    },2325};2326options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a helpful math tutor. Guide the user through the solution step by step."));2327options.InputItems.Add(ResponseItem.CreateUserMessageItem("How can I solve 8x + 7 = -23?"));23282329ResponseResult response = await client.CreateResponseAsync(options);2330using JsonDocument parsed = JsonDocument.Parse(response.GetOutputText());2331Console.WriteLine(parsed.RootElement);2332```23332334```ruby2335require "openai"23362337client = OpenAI::Client.new2338math_schema = {2339  type: :object,2340  properties: {2341    steps: {2342      type: :array,2343      items: {2344        type: :object,2345        properties: {2346          explanation: { type: :string },2347          output: { type: :string }2348        },2349        required: %w[explanation output],2350        additionalProperties: false2351      }2352    },2353    final_answer: { type: :string }2354  },2355  required: %w[steps final_answer],2356  additionalProperties: false2357}23582359response = client.responses.create(2360  model: "gpt-6-astra",2361  input: [2362    {2363      role: :system,2364      content: "You are a helpful math tutor. Guide the user through the solution step by step."2365    },2366    {2367      role: :user,2368      content: "How can I solve 8x + 7 = -23?"2369    }2370  ],2371  text: {2372    format: {2373      type: :json_schema,2374      name: "math_response",2375      strict: true,2376      schema: math_schema2377    }2378  }2379)23802381puts(response.output_text)2382```23832384```bash2385curl https://api.openai.com/v1/responses \2386  -H "Authorization: Bearer $OPENAI_API_KEY" \2387  -H "Content-Type: application/json" \2388  -d '{2389    "model": "gpt-6-astra",2390    "input": [2391      {2392        "role": "system",2393        "content": "You are a helpful math tutor. Guide the user through the solution step by step."2394      },2395      {2396        "role": "user",2397        "content": "how can I solve 8x + 7 = -23"2398      }2399    ],2400    "text": {2401      "format": {2402        "type": "json_schema",2403        "name": "math_response",2404        "schema": {2405          "type": "object",2406          "properties": {2407            "steps": {2408              "type": "array",2409              "items": {2410                "type": "object",2411                "properties": {2412                  "explanation": { "type": "string" },2413                  "output": { "type": "string" }2414                },2415                "required": ["explanation", "output"],2416                "additionalProperties": false2417              }2418            },2419            "final_answer": { "type": "string" }2420          },2421          "required": ["steps", "final_answer"],2422          "additionalProperties": false2423        },2424        "strict": true2425      }2426    }2427  }'2428```2429243024312432**Note:** the first request you make with any schema will have additional latency as our API processes the schema, but subsequent requests with the same schema will not have additional latency.24332434243524362437243824392440## Step 3: Handle edge cases244124422443244424452446In some cases, the model might not generate a valid response that matches the provided JSON schema.24472448This can happen in the case of a refusal, if the model refuses to answer for safety reasons, or if for example you reach a max tokens limit and the response is incomplete.24492450245124522453```javascript2454try {2455  const response = await openai.responses.create({2456    model: "gpt-6-astra",2457    input: [2458      {2459        role: "system",2460        content:2461          "You are a helpful math tutor. Guide the user through the solution step by step.",2462      },2463      {2464        role: "user",2465        content: "how can I solve 8x + 7 = -23",2466      },2467    ],2468    max_output_tokens: 50,2469    text: {2470      format: {2471        type: "json_schema",2472        name: "math_response",2473        schema: {2474          type: "object",2475          properties: {2476            steps: {2477              type: "array",2478              items: {2479                type: "object",2480                properties: {2481                  explanation: {2482                    type: "string",2483                  },2484                  output: {2485                    type: "string",2486                  },2487                },2488                required: ["explanation", "output"],2489                additionalProperties: false,2490              },2491            },2492            final_answer: {2493              type: "string",2494            },2495          },2496          required: ["steps", "final_answer"],2497          additionalProperties: false,2498        },2499        strict: true,2500      },2501    },2502  });25032504  if (2505    response.status === "incomplete" &&2506    response.incomplete_details.reason === "max_output_tokens"2507  ) {2508    // Handle the case where the model did not return a complete response2509    throw new Error("Incomplete response");2510  }25112512  const message = response.output.find((item) => item.type === "message");2513  const math_response = message?.content[0];25142515  if (!math_response) {2516    throw new Error("No response content");2517  }25182519  if (math_response.type === "refusal") {2520    // handle refusal2521    console.log(math_response.refusal);2522  } else if (math_response.type === "output_text") {2523    console.log(math_response.text);2524  } else {2525    throw new Error("No response content");2526  }2527} catch (e) {2528  // Handle edge cases2529  console.error(e);2530}2531```25322533```python2534try:2535    response = client.responses.create(2536        model="gpt-6-astra",2537        input=[2538            {2539                "role": "system",2540                "content": "You are a helpful math tutor. Guide the user through the solution step by step.",2541            },2542            {"role": "user", "content": "how can I solve 8x + 7 = -23"},2543        ],2544        text={2545            "format": {2546                "type": "json_schema",2547                "name": "math_response",2548                "strict": True,2549                "schema": {2550                    "type": "object",2551                    "properties": {2552                        "steps": {2553                            "type": "array",2554                            "items": {2555                                "type": "object",2556                                "properties": {2557                                    "explanation": {"type": "string"},2558                                    "output": {"type": "string"},2559                                },2560                                "required": ["explanation", "output"],2561                                "additionalProperties": False,2562                            },2563                        },2564                        "final_answer": {"type": "string"},2565                    },2566                    "required": ["steps", "final_answer"],2567                    "additionalProperties": False,2568                },2569            },2570        },2571        max_output_tokens=50,2572    )25732574    if (2575        response.status == "incomplete"2576        and response.incomplete_details.reason == "max_output_tokens"2577    ):2578        raise Exception("Incomplete response")25792580    message = next((item for item in response.output if item.type == "message"), None)2581    math_response = message.content[0] if message and message.content else None25822583    if not math_response:2584        raise Exception("No response content")25852586    if math_response.type == "refusal":2587        print(math_response.refusal)2588    elif math_response.type == "output_text":2589        print(math_response.text)2590    else:2591        raise Exception("No response content")2592except Exception as e:2593    # handle errors like finish_reason, refusal, content_filter, etc.2594    print(e)2595```25962597```go2598package main25992600import (2601	"context"2602	"errors"2603	"fmt"26042605	"github.com/openai/openai-go/v3"2606	"github.com/openai/openai-go/v3/responses"2607)26082609func main() {2610	client := openai.NewClient()2611	response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{2612		Model: "gpt-6-astra",2613		Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{2614			responses.ResponseInputItemParamOfMessage(2615				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a helpful math tutor. Guide the user through the solution step by step.")},2616				responses.EasyInputMessageRoleSystem,2617			),2618			responses.ResponseInputItemParamOfMessage(2619				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("how can I solve 8x + 7 = -23")},2620				responses.EasyInputMessageRoleUser,2621			),2622		}},2623		MaxOutputTokens: openai.Int(1024),2624		Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{2625			OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "math_response", Schema: mathSchema(), Strict: openai.Bool(true)},2626		}},2627	})2628	if err != nil {2629		panic(err)2630	}2631	if response.Status == "incomplete" {2632		panic(errors.New("incomplete response"))2633	}26342635	for _, output := range response.Output {2636		if output.Type != "message" {2637			continue2638		}2639		for _, content := range output.AsMessage().Content {2640			if content.Type == "refusal" {2641				fmt.Println(content.AsRefusal().Refusal)2642				return2643			}2644			if content.Type == "output_text" {2645				fmt.Println(content.AsOutputText().Text)2646				return2647			}2648		}2649	}2650	panic(errors.New("no response content"))2651}26522653func mathSchema() map[string]any {2654	return map[string]any{2655		"type": "object",2656		"properties": map[string]any{2657			"steps":        map[string]any{"type": "array", "items": map[string]any{"type": "object", "properties": map[string]any{"explanation": map[string]any{"type": "string"}, "output": map[string]any{"type": "string"}}, "required": []string{"explanation", "output"}, "additionalProperties": false}},2658			"final_answer": map[string]any{"type": "string"},2659		},2660		"required":             []string{"steps", "final_answer"},2661		"additionalProperties": false,2662	}2663}2664```26652666```java2667import com.openai.client.OpenAIClient;2668import com.openai.client.okhttp.OpenAIOkHttpClient;2669import com.openai.core.JsonValue;2670import com.openai.models.responses.EasyInputMessage;2671import com.openai.models.responses.ResponseCreateParams;2672import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;2673import com.openai.models.responses.ResponseInputItem;2674import com.openai.models.responses.ResponseStatus;2675import com.openai.models.responses.ResponseTextConfig;2676import java.util.List;2677import java.util.Map;26782679ResponseCreateParams params =2680    ResponseCreateParams.builder()2681        .model("gpt-6-astra")2682        .inputOfResponse(2683            List.of(2684                ResponseInputItem.ofEasyInputMessage(2685                    EasyInputMessage.builder()2686                        .role(EasyInputMessage.Role.SYSTEM)2687                        .content(2688                            "You are a helpful math tutor. Guide the user through the solution step by step.")2689                        .build()),2690                ResponseInputItem.ofEasyInputMessage(2691                    EasyInputMessage.builder()2692                        .role(EasyInputMessage.Role.USER)2693                        .content("How can I solve 8x + 7 = -23?")2694                        .build())))2695        .text(2696            ResponseTextConfig.builder()2697                .format(2698                    ResponseFormatTextJsonSchemaConfig.builder()2699                        .name("math_response")2700                        .strict(true)2701                        .schema(2702                            ResponseFormatTextJsonSchemaConfig.Schema.builder()2703                                .putAdditionalProperty("type", JsonValue.from("object"))2704                                .putAdditionalProperty(2705                                    "properties",2706                                    JsonValue.from(2707                                        Map.of(2708                                            "steps",2709                                            Map.of(2710                                                "type",2711                                                "array",2712                                                "items",2713                                                Map.of(2714                                                    "type",2715                                                    "object",2716                                                    "properties",2717                                                    Map.of(2718                                                        "explanation",2719                                                        Map.of("type", "string"),2720                                                        "output",2721                                                        Map.of("type", "string")),2722                                                    "required",2723                                                    List.of("explanation", "output"),2724                                                    "additionalProperties",2725                                                    false)),2726                                            "final_answer",2727                                            Map.of("type", "string"))))2728                                .putAdditionalProperty(2729                                    "required",2730                                    JsonValue.from(List.of("steps", "final_answer")))2731                                .putAdditionalProperty(2732                                    "additionalProperties", JsonValue.from(false))2733                                .build())2734                        .build())2735                .build())2736        .maxOutputTokens(1_024L)2737        .build();27382739var response = client.responses().create(params);2740if (response.status().filter(ResponseStatus.INCOMPLETE::equals).isPresent()) {2741  throw new IllegalStateException("Incomplete response");2742}27432744var content =2745    response.output().stream()2746        .flatMap(item -> item.message().stream())2747        .flatMap(message -> message.content().stream())2748        .findFirst()2749        .orElseThrow(() -> new IllegalStateException("No response content"));27502751if (content.refusal().isPresent()) {2752  System.out.println(content.refusal().orElseThrow().refusal());2753} else {2754  System.out.println(2755      content2756          .outputText()2757          .orElseThrow(() -> new IllegalStateException("No response content"))2758          .text());2759}2760```27612762```csharp2763using OpenAI.Responses;2764#pragma warning disable OPENAI00127652766string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;2767ResponsesClient client = new(key);27682769BinaryData schema = BinaryData.FromString(2770    """2771    {2772      "type": "object",2773      "properties": {2774        "steps": {2775          "type": "array",2776          "items": {2777            "type": "object",2778            "properties": {2779              "explanation": { "type": "string" },2780              "output": { "type": "string" }2781            },2782            "required": ["explanation", "output"],2783            "additionalProperties": false2784          }2785        },2786        "final_answer": { "type": "string" }2787      },2788      "required": ["steps", "final_answer"],2789      "additionalProperties": false2790    }2791    """2792);2793CreateResponseOptions options = new()2794{2795    Model = "gpt-6-astra",2796    MaxOutputTokenCount = 300,2797    TextOptions = new ResponseTextOptions2798    {2799        TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(2800            "math_response",2801            schema,2802            jsonSchemaIsStrict: true2803        ),2804    },2805};2806options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a helpful math tutor. Guide the user through the solution step by step."));2807options.InputItems.Add(ResponseItem.CreateUserMessageItem("How can I solve 8x + 7 = -23?"));28082809ResponseResult response = await client.CreateResponseAsync(options);2810if (2811    response.Status == ResponseStatus.Incomplete2812    && response.IncompleteStatusDetails?.Reason == ResponseIncompleteStatusReason.MaxOutputTokens2813)2814{2815    throw new InvalidOperationException("The structured response was incomplete.");2816}2817if (2818    response.Status == ResponseStatus.Incomplete2819    && response.IncompleteStatusDetails?.Reason == ResponseIncompleteStatusReason.ContentFilter2820)2821{2822    throw new InvalidOperationException("The structured response was interrupted by the content filter.");2823}2824MessageResponseItem message = response.OutputItems.OfType<MessageResponseItem>().FirstOrDefault()2825    ?? throw new InvalidOperationException("The response did not include an output message.");2826ResponseContentPart content = message.Content.FirstOrDefault()2827    ?? throw new InvalidOperationException("The response did not include output content.");2828Console.WriteLine(2829    content.Kind == ResponseContentPartKind.Refusal ? content.Refusal : content.Text2830);2831```28322833```ruby2834require "openai"28352836client = OpenAI::Client.new2837step_schema = {2838  type: :object,2839  properties: {2840    explanation: { type: :string },2841    output: { type: :string }2842  },2843  required: %w[explanation output],2844  additionalProperties: false2845}2846math_schema = {2847  type: :object,2848  properties: {2849    steps: {2850      type: :array,2851      items: step_schema2852    },2853    final_answer: { type: :string }2854  },2855  required: %w[steps final_answer],2856  additionalProperties: false2857}28582859response = client.responses.create(2860  model: "gpt-6-astra",2861  input: [2862    {2863      role: :system,2864      content: "You are a helpful math tutor. Guide the user through the solution step by step."2865    },2866    {2867      role: :user,2868      content: "How can I solve 8x + 7 = -23?"2869    }2870  ],2871  max_output_tokens: 1_024,2872  text: {2873    format: {2874      type: :json_schema,2875      name: "math_response",2876      strict: true,2877      schema: math_schema2878    }2879  }2880)28812882if response.status == OpenAI::Responses::ResponseStatus::INCOMPLETE2883  raise "Incomplete response"2884end28852886message = response.output.find do |item|2887  item.is_a?(OpenAI::Models::Responses::ResponseOutputMessage)2888end2889unless message.is_a?(OpenAI::Models::Responses::ResponseOutputMessage)2890  raise "No response message"2891end28922893content = message.content.fetch(0)2894if content.is_a?(OpenAI::Models::Responses::ResponseOutputRefusal)2895  puts(content.refusal)2896else2897  puts(content.text)2898end2899```29002901290229032904290529062907Refusals with Structured Outputs2908290929102911When using Structured Outputs with user-generated input, OpenAI models may occasionally refuse to fulfill the request for safety reasons. Since a refusal does not necessarily follow the schema you have supplied in `response_format`, the API response will include a new field called `refusal` to indicate that the model refused to fulfill the request.29122913When the `refusal` property appears in your output object, you might present the refusal in your UI, or include conditional logic in code that consumes the response to handle the case of a refused request.29142915291629172918```javascript2919const Step = z.object({2920  explanation: z.string(),2921  output: z.string(),2922});29232924const MathReasoning = z.object({2925  steps: z.array(Step),2926  final_answer: z.string(),2927});29282929const response = await openai.responses.parse({2930  model: "gpt-6-astra",2931  input: [2932    {2933      role: "system",2934      content:2935        "You are a helpful math tutor. Guide the user through the solution step by step.",2936    },2937    { role: "user", content: "how can I solve 8x + 7 = -23" },2938  ],2939  text: {2940    format: zodTextFormat(MathReasoning, "math_response"),2941  },2942});29432944for (const output of response.output) {2945  if (output.type !== "message") {2946    continue;2947  }29482949  for (const item of output.content) {2950    if (item.type == "refusal") {2951      // If the model refuses to respond, you will get a refusal message2952      console.log(item.refusal);2953      continue;2954    }29552956    if (!item.parsed) {2957      throw new Error("Could not parse response");2958    }29592960    console.log(item.parsed);2961  }2962}2963```29642965```python2966class Step(BaseModel):2967    explanation: str2968    output: str296929702971class MathReasoning(BaseModel):2972    steps: list[Step]2973    final_answer: str297429752976response = client.responses.parse(2977    model="gpt-6-astra",2978    input=[2979        {2980            "role": "system",2981            "content": "You are a helpful math tutor. Guide the user through the solution step by step.",2982        },2983        {"role": "user", "content": "how can I solve 8x + 7 = -23"},2984    ],2985    text_format=MathReasoning,2986)29872988for output in response.output:2989    if output.type != "message":2990        continue29912992    for item in output.content:2993        if item.type == "refusal":2994            # If the model refuses to respond, you will get a refusal message2995            print(item.refusal)2996            continue29972998        if not item.parsed:2999            raise Exception("Could not parse response")30003001        print(item.parsed)3002```30033004```go3005package main30063007import (3008	"context"3009	"fmt"30103011	"github.com/openai/openai-go/v3"3012	"github.com/openai/openai-go/v3/responses"3013)30143015func main() {3016	client := openai.NewClient()3017	response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{3018		Model: "gpt-6-astra",3019		Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{3020			responses.ResponseInputItemParamOfMessage(3021				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a helpful math tutor. Guide the user through the solution step by step.")},3022				responses.EasyInputMessageRoleSystem,3023			),3024			responses.ResponseInputItemParamOfMessage(3025				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("how can I solve 8x + 7 = -23")},3026				responses.EasyInputMessageRoleUser,3027			),3028		}},3029		Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{3030			OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "math_response", Schema: mathSchema(), Strict: openai.Bool(true)},3031		}},3032	})3033	if err != nil {3034		panic(err)3035	}30363037	for _, output := range response.Output {3038		if output.Type != "message" {3039			continue3040		}3041		for _, content := range output.AsMessage().Content {3042			if content.Type == "refusal" {3043				fmt.Println(content.AsRefusal().Refusal)3044				continue3045			}3046			fmt.Println(content.AsOutputText().Text)3047		}3048	}3049}30503051func mathSchema() map[string]any {3052	return map[string]any{3053		"type": "object",3054		"properties": map[string]any{3055			"steps":        map[string]any{"type": "array", "items": map[string]any{"type": "object", "properties": map[string]any{"explanation": map[string]any{"type": "string"}, "output": map[string]any{"type": "string"}}, "required": []string{"explanation", "output"}, "additionalProperties": false}},3056			"final_answer": map[string]any{"type": "string"},3057		},3058		"required":             []string{"steps", "final_answer"},3059		"additionalProperties": false,3060	}3061}3062```30633064```java3065import com.openai.client.OpenAIClient;3066import com.openai.client.okhttp.OpenAIOkHttpClient;3067import com.openai.core.JsonValue;3068import com.openai.models.responses.EasyInputMessage;3069import com.openai.models.responses.ResponseCreateParams;3070import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;3071import com.openai.models.responses.ResponseInputItem;3072import com.openai.models.responses.ResponseTextConfig;3073import java.util.List;3074import java.util.Map;30753076Map<String, Object> schema =3077    Map.of(3078        "type",3079        "object",3080        "properties",3081        Map.of(3082            "steps",3083                Map.of(3084                    "type",3085                    "array",3086                    "items",3087                    Map.of(3088                        "type",3089                        "object",3090                        "properties",3091                        Map.of(3092                            "explanation", Map.of("type", "string"),3093                            "output", Map.of("type", "string")),3094                        "required",3095                        List.of("explanation", "output"),3096                        "additionalProperties",3097                        false)),3098            "final_answer", Map.of("type", "string")),3099        "required",3100        List.of("steps", "final_answer"),3101        "additionalProperties",3102        false);31033104ResponseCreateParams params =3105    ResponseCreateParams.builder()3106        .model("gpt-6-astra")3107        .inputOfResponse(3108            List.of(3109                ResponseInputItem.ofEasyInputMessage(3110                    EasyInputMessage.builder()3111                        .role(EasyInputMessage.Role.SYSTEM)3112                        .content(3113                            "You are a helpful math tutor. Guide the user through the solution step by step.")3114                        .build()),3115                ResponseInputItem.ofEasyInputMessage(3116                    EasyInputMessage.builder()3117                        .role(EasyInputMessage.Role.USER)3118                        .content("How can I solve 8x + 7 = -23?")3119                        .build())))3120        .text(3121            ResponseTextConfig.builder()3122                .format(3123                    ResponseFormatTextJsonSchemaConfig.builder()3124                        .name("math_reasoning")3125                        .strict(true)3126                        .schema(3127                            JsonValue.from(schema)3128                                .convert(ResponseFormatTextJsonSchemaConfig.Schema.class))3129                        .build())3130                .build())3131        .build();31323133var response = client.responses().create(params);3134for (var output : response.output()) {3135  if (output.message().isEmpty()) continue;3136  for (var content : output.message().orElseThrow().content()) {3137    if (content.refusal().isPresent()) {3138      System.out.println(content.refusal().orElseThrow().refusal());3139    } else {3140      content.outputText().ifPresent(text -> System.out.println(text.text()));3141    }3142  }3143}3144```31453146```csharp3147using OpenAI.Responses;3148#pragma warning disable OPENAI00131493150string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;3151ResponsesClient client = new(key);31523153BinaryData schema = BinaryData.FromString(3154    """3155    {3156      "type": "object",3157      "properties": {3158        "steps": {3159          "type": "array",3160          "items": {3161            "type": "object",3162            "properties": {3163              "explanation": { "type": "string" },3164              "output": { "type": "string" }3165            },3166            "required": ["explanation", "output"],3167            "additionalProperties": false3168          }3169        },3170        "final_answer": { "type": "string" }3171      },3172      "required": ["steps", "final_answer"],3173      "additionalProperties": false3174    }3175    """3176);3177CreateResponseOptions options = new()3178{3179    Model = "gpt-6-astra",3180    TextOptions = new ResponseTextOptions3181    {3182        TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(3183            "math_response",3184            schema,3185            jsonSchemaIsStrict: true3186        ),3187    },3188};3189options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a helpful math tutor. Guide the user through the solution step by step."));3190options.InputItems.Add(ResponseItem.CreateUserMessageItem("How can I solve 8x + 7 = -23?"));31913192ResponseResult response = await client.CreateResponseAsync(options);3193foreach (MessageResponseItem message in response.OutputItems.OfType<MessageResponseItem>())3194{3195    foreach (ResponseContentPart content in message.Content)3196    {3197        Console.WriteLine(3198            content.Kind == ResponseContentPartKind.Refusal ? content.Refusal : content.Text3199        );3200    }3201}3202```32033204```ruby3205require "openai"32063207client = OpenAI::Client.new3208math_schema = {3209  type: :object,3210  properties: {3211    steps: {3212      type: :array,3213      items: {3214        type: :object,3215        properties: {3216          explanation: { type: :string },3217          output: { type: :string }3218        },3219        required: %w[explanation output],3220        additionalProperties: false3221      }3222    },3223    final_answer: { type: :string }3224  },3225  required: %w[steps final_answer],3226  additionalProperties: false3227}32283229response = client.responses.create(3230  model: "gpt-6-astra",3231  input: [3232    {3233      role: :system,3234      content: "You are a helpful math tutor. Guide the user through the solution step by step."3235    },3236    {3237      role: :user,3238      content: "How can I solve 8x + 7 = -23?"3239    }3240  ],3241  text: {3242    format: {3243      type: :json_schema,3244      name: "math_response",3245      strict: true,3246      schema: math_schema3247    }3248  }3249)32503251response.output.each do |item|3252  next unless item.is_a?(OpenAI::Models::Responses::ResponseOutputMessage)32533254  item.content.each do |content|3255    case content3256    when OpenAI::Models::Responses::ResponseOutputRefusal3257      puts(content.refusal)3258    when OpenAI::Models::Responses::ResponseOutputText3259      puts(content.text)3260    end3261  end3262end3263```3264326532663267The API response from a refusal will look something like this:32683269327032713272```json3273{3274  "id": "resp_1234567890",3275  "object": "response",3276  "created_at": 1721596428,3277  "status": "completed",3278  "completed_at": 1721596429,3279  "error": null,3280  "incomplete_details": null,3281  "input": [],3282  "instructions": null,3283  "max_output_tokens": null,3284  "model": "gpt-4o-2024-08-06",3285  "output": [{3286    "id": "msg_1234567890",3287    "type": "message",3288    "role": "assistant",3289    "content": [3290      // highlight-start3291      {3292        "type": "refusal",3293        "refusal": "I'm sorry, I cannot assist with that request."3294      }3295      // highlight-end3296    ]3297  }],3298  "usage": {3299    "input_tokens": 81,3300    "output_tokens": 11,3301    "total_tokens": 92,3302    "output_tokens_details": {3303      "reasoning_tokens": 0,3304    }3305  },3306}3307```33083309331033113312Tips and best practices3313331433153316#### Handling user-generated input33173318If your application is using user-generated input, make sure your prompt includes instructions on how to handle situations where the input cannot result in a valid response.33193320The model will always try to adhere to the provided schema, which can result in hallucinations if the input is completely unrelated to the schema.33213322You could include language in your prompt to specify that you want to return empty parameters, or a specific sentence, if the model detects that the input is incompatible with the task.33233324#### Handling mistakes33253326Structured Outputs can still contain mistakes. If you see mistakes, try adjusting your instructions, providing examples in the system instructions, or splitting tasks into simpler subtasks. Refer to the [prompt engineering guide](https://developers.openai.com/api/docs/guides/prompt-engineering) for more guidance on how to tweak your inputs.33273328#### Avoid JSON schema divergence33293330To prevent your JSON Schema and corresponding types in your programming language from diverging, we strongly recommend using native SDK schema helpers where available.33313332If you prefer to specify the JSON schema directly, you could add CI rules that flag when either the JSON schema or underlying data objects are edited, or add a CI step that automatically generates the JSON Schema from type definitions (or vice-versa).33333334## Streaming3335333633373338You can use streaming to process model responses or function call arguments as they are being generated, and parse them as structured data.33393340That way, you don't have to wait for the entire response to complete before handling it.3341This is particularly useful if you would like to display JSON fields one by one, or handle function call arguments as soon as they are available.33423343We recommend relying on the SDKs to handle streaming with Structured Outputs.33443345334633473348```javascript3349import { OpenAI } from "openai";3350import { zodTextFormat } from "openai/helpers/zod";3351import { z } from "zod";33523353const EntitiesSchema = z.object({3354  attributes: z.array(z.string()),3355  colors: z.array(z.string()),3356  animals: z.array(z.string()),3357});33583359const openai = new OpenAI();3360const stream = openai.responses3361  .stream({3362    model: "gpt-6-astra",3363    input: [3364      { role: "user", content: "What's the weather like in Paris today?" },3365    ],3366    text: {3367      format: zodTextFormat(EntitiesSchema, "entities"),3368    },3369  })3370  .on("response.refusal.delta", (event) => {3371    process.stdout.write(event.delta);3372  })3373  .on("response.output_text.delta", (event) => {3374    process.stdout.write(event.delta);3375  })3376  .on("response.output_text.done", () => {3377    process.stdout.write("\n");3378  })3379  .on("error", (error) => {3380    console.error(error);3381  });33823383const result = await stream.finalResponse();33843385console.log(result);3386```33873388```python3389from openai import OpenAI3390from pydantic import BaseModel339133923393class EntitiesModel(BaseModel):3394    attributes: list[str]3395    colors: list[str]3396    animals: list[str]339733983399client = OpenAI()34003401with client.responses.stream(3402    model="gpt-6-astra",3403    input=[3404        {"role": "system", "content": "Extract entities from the input text"},3405        {3406            "role": "user",3407            "content": "The quick brown fox jumps over the lazy dog with piercing blue eyes",3408        },3409    ],3410    text_format=EntitiesModel,3411) as stream:3412    for event in stream:3413        if event.type == "response.refusal.delta":3414            print(event.delta, end="")3415        elif event.type == "response.output_text.delta":3416            print(event.delta, end="")3417        elif event.type == "response.error":3418            print(event.error, end="")3419        elif event.type == "response.completed":3420            print("Completed")  # print(event.response.output)34213422    final_response = stream.get_final_response()3423    print(final_response)3424```34253426```java3427import com.openai.client.OpenAIClient;3428import com.openai.client.okhttp.OpenAIOkHttpClient;3429import com.openai.core.JsonValue;3430import com.openai.core.http.StreamResponse;3431import com.openai.models.responses.EasyInputMessage;3432import com.openai.models.responses.ResponseCreateParams;3433import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;3434import com.openai.models.responses.ResponseInputItem;3435import com.openai.models.responses.ResponseStreamEvent;3436import com.openai.models.responses.ResponseTextConfig;3437import java.util.List;3438import java.util.Map;34393440ResponseCreateParams params =3441    ResponseCreateParams.builder()3442        .model("gpt-6-astra")3443        .inputOfResponse(3444            List.of(3445                ResponseInputItem.ofEasyInputMessage(3446                    EasyInputMessage.builder()3447                        .role(EasyInputMessage.Role.SYSTEM)3448                        .content("Extract entities from the input text")3449                        .build()),3450                ResponseInputItem.ofEasyInputMessage(3451                    EasyInputMessage.builder()3452                        .role(EasyInputMessage.Role.USER)3453                        .content(3454                            "The quick brown fox jumps over the lazy dog with piercing blue eyes")3455                        .build())))3456        .text(3457            ResponseTextConfig.builder()3458                .format(3459                    ResponseFormatTextJsonSchemaConfig.builder()3460                        .name("entities")3461                        .strict(true)3462                        .schema(3463                            ResponseFormatTextJsonSchemaConfig.Schema.builder()3464                                .putAdditionalProperty("type", JsonValue.from("object"))3465                                .putAdditionalProperty(3466                                    "properties",3467                                    JsonValue.from(3468                                        Map.of(3469                                            "attributes",3470                                            Map.of(3471                                                "type",3472                                                "array",3473                                                "items",3474                                                Map.of("type", "string")),3475                                            "colors",3476                                            Map.of(3477                                                "type",3478                                                "array",3479                                                "items",3480                                                Map.of("type", "string")),3481                                            "animals",3482                                            Map.of(3483                                                "type",3484                                                "array",3485                                                "items",3486                                                Map.of("type", "string")))))3487                                .putAdditionalProperty(3488                                    "required",3489                                    JsonValue.from(List.of("attributes", "colors", "animals")))3490                                .putAdditionalProperty(3491                                    "additionalProperties", JsonValue.from(false))3492                                .build())3493                        .build())3494                .build())3495        .build();34963497try (StreamResponse<ResponseStreamEvent> stream = client.responses().createStreaming(params)) {3498  stream.stream()3499      .forEach(3500          event -> {3501            event.outputTextDelta().ifPresent(delta -> System.out.print(delta.delta()));3502            event.refusalDelta().ifPresent(refusal -> System.out.print(refusal.delta()));3503            event.error().ifPresent(error -> System.out.println(error.message()));3504            event3505                .completed()3506                .ifPresent(3507                    completed -> {3508                      System.out.println("Completed");3509                      System.out.println(completed.response());3510                    });3511          });3512}3513```35143515```ruby3516require "openai"35173518client = OpenAI::Client.new3519entities_schema = {3520  type: :object,3521  properties: {3522    attributes: {3523      type: :array,3524      items: { type: :string }3525    },3526    colors: {3527      type: :array,3528      items: { type: :string }3529    },3530    animals: {3531      type: :array,3532      items: { type: :string }3533    }3534  },3535  required: %w[attributes colors animals],3536  additionalProperties: false3537}35383539stream = client.responses.stream(3540  model: "gpt-6-astra",3541  input: [3542    {3543      role: :system,3544      content: "Extract entities from the input text."3545    },3546    {3547      role: :user,3548      content: "The quick brown fox jumps over the lazy dog with piercing blue eyes."3549    }3550  ],3551  text: {3552    format: {3553      type: :json_schema,3554      name: "entities",3555      strict: true,3556      schema: entities_schema3557    }3558  }3559)35603561stream.each do |event|3562  case event3563  when OpenAI::Models::Responses::ResponseRefusalDeltaEvent,3564       OpenAI::Models::Responses::ResponseTextDeltaEvent3565    print(event.delta)3566  when OpenAI::Models::Responses::ResponseErrorEvent3567    warn(event.message)3568  when OpenAI::Models::Responses::ResponseCompletedEvent3569    puts("\nCompleted")3570  end3571end3572```3573357435753576## Supported schemas3577357835793580Structured Outputs supports a subset of the [JSON Schema](https://json-schema.org/docs) language.35813582#### Supported types35833584The following types are supported for Structured Outputs:35853586- String3587- Number3588- Boolean3589- Integer3590- Object3591- Array3592- Enum3593- anyOf35943595#### Supported properties35963597In addition to specifying the type of a property, you can specify a selection of additional constraints:35983599**Supported `string` properties:**36003601- `pattern` — A regular expression that the string must match.3602- `format` — Predefined formats for strings. Currently supported:3603  - `date-time`3604  - `time`3605  - `date`3606  - `duration`3607  - `email`3608  - `hostname`3609  - `ipv4`3610  - `ipv6`3611  - `uuid`36123613**Supported `number` properties:**36143615- `multipleOf` — The number must be a multiple of this value.3616- `maximum` — The number must be less than or equal to this value.3617- `exclusiveMaximum` — The number must be less than this value.3618- `minimum` — The number must be greater than or equal to this value.3619- `exclusiveMinimum` — The number must be greater than this value.36203621**Supported `array` properties:**36223623- `minItems` — The array must have at least this many items.3624- `maxItems` — The array must have at most this many items.36253626Here are some examples on how you can use these type restrictions:3627362836293630String Restrictions36313632```json3633{3634    "name": "user_data",3635    "strict": true,3636    "schema": {3637        "type": "object",3638        "properties": {3639            "name": {3640                "type": "string",3641                "description": "The name of the user"3642            },3643            "username": {3644                "type": "string",3645                "description": "The username of the user. Must start with @",3646                // highlight-start3647                "pattern": "^@[a-zA-Z0-9_]+$"3648                // highlight-end3649            },3650            "email": {3651                "type": "string",3652                "description": "The email of the user",3653                // highlight-start3654                "format": "email"3655                // highlight-end3656            }3657        },3658        "additionalProperties": false,3659        "required": [3660            "name", "username", "email"3661        ]3662    }3663}3664```36653666  36673668  36693670    3671Number Restrictions36723673```json3674{3675    "name": "weather_data",3676    "strict": true,3677    "schema": {3678        "type": "object",3679        "properties": {3680            "location": {3681                "type": "string",3682                "description": "The location to get the weather for"3683            },3684            "unit": {3685                "type": ["string", "null"],3686                "description": "The unit to return the temperature in",3687                "enum": ["F", "C"]3688            },3689            "value": {3690                "type": "number",3691                "description": "The actual temperature value in the location",3692                // highlight-start3693                "minimum": -130,3694                "maximum": 1303695                // highlight-end3696            }3697        },3698        "additionalProperties": false,3699        "required": [3700            "location", "unit", "value"3701        ]3702    }3703}3704```3705370637073708Note these constraints are [not yet supported for fine-tuned3709  models](#some-type-specific-keywords-are-not-yet-supported).37103711#### Root objects must not be `anyOf` and must be an object37123713Note that the root level object of a schema must be an object, and not use `anyOf`. A pattern that appears in Zod (as one example) is using a discriminated union, which produces an `anyOf` at the top level. So code such as the following won't work:37143715```javascript3716import { z } from "zod";3717import { zodResponseFormat } from "openai/helpers/zod";37183719const BaseResponseSchema = z.object({3720  /* ... */3721});3722const UnsuccessfulResponseSchema = z.object({3723  /* ... */3724});37253726const finalSchema = z.discriminatedUnion("status", [3727  BaseResponseSchema,3728  UnsuccessfulResponseSchema,3729]);37303731// Invalid JSON Schema for Structured Outputs3732const json = zodResponseFormat(finalSchema, "final_schema");3733```373437353736#### All fields must be `required`37373738To use Structured Outputs, all fields or function parameters must be specified as `required`.37393740```json3741{3742    "name": "get_weather",3743    "description": "Fetches the weather in the given location",3744    "strict": true,3745    "parameters": {3746        "type": "object",3747        "properties": {3748            "location": {3749                "type": "string",3750                "description": "The location to get the weather for"3751            },3752            "unit": {3753                "type": "string",3754                "description": "The unit to return the temperature in",3755                "enum": ["F", "C"]3756            }3757        },3758        "additionalProperties": false,3759        // highlight-start3760        "required": ["location", "unit"]3761        // highlight-end3762    }3763}3764```376537663767Although all fields must be required (and the model will return a value for each parameter), it is possible to emulate an optional parameter by using a union type with `null`.37683769```json3770{3771    "name": "get_weather",3772    "description": "Fetches the weather in the given location",3773    "strict": true,3774    "parameters": {3775        "type": "object",3776        "properties": {3777            "location": {3778                "type": "string",3779                "description": "The location to get the weather for"3780            },3781            "unit": {3782                // highlight-start3783                "type": ["string", "null"],3784                // highlight-end3785                "description": "The unit to return the temperature in",3786                "enum": ["F", "C"]3787            }3788        },3789        "additionalProperties": false,3790        "required": [3791            "location", "unit"3792        ]3793    }3794}3795```379637973798#### Objects have limitations on nesting depth and size37993800A schema may have up to 5000 object properties total, with up to 10 levels of nesting.38013802#### Limitations on total string size38033804In a schema, total string length of all property names, definition names, enum values, and const values cannot exceed 120,000 characters.38053806#### Limitations on enum size38073808A schema may have up to 1000 enum values across all enum properties.38093810For a single enum property with string values, the total string length of all enum values cannot exceed 15,000 characters when there are more than 250 enum values.38113812#### `additionalProperties: false` must always be set in objects38133814`additionalProperties` controls whether it is allowable for an object to contain additional keys / values that were not defined in the JSON Schema.38153816Structured Outputs only supports generating specified keys / values, so we require developers to set `additionalProperties: false` to opt into Structured Outputs.38173818```json3819{3820    "name": "get_weather",3821    "description": "Fetches the weather in the given location",3822    "strict": true,3823    "schema": {3824        "type": "object",3825        "properties": {3826            "location": {3827                "type": "string",3828                "description": "The location to get the weather for"3829            },3830            "unit": {3831                "type": "string",3832                "description": "The unit to return the temperature in",3833                "enum": ["F", "C"]3834            }3835        },3836        // highlight-start3837        "additionalProperties": false,3838        // highlight-end3839        "required": [3840            "location", "unit"3841        ]3842    }3843}3844```384538463847#### Key ordering38483849When using Structured Outputs, outputs will be produced in the same order as the ordering of keys in the schema.38503851#### Some type-specific keywords are not yet supported38523853- **Composition:** `allOf`, `not`, `dependentRequired`, `dependentSchemas`, `if`, `then`, `else`38543855For fine-tuned models, we additionally do not support the following:38563857- **For strings:** `minLength`, `maxLength`, `pattern`, `format`3858- **For numbers:** `minimum`, `maximum`, `multipleOf`3859- **For objects:** `patternProperties`3860- **For arrays:** `minItems`, `maxItems`38613862If you turn on Structured Outputs by supplying `strict: true` and call the API with an unsupported JSON Schema, you will receive an error.38633864#### For `anyOf`, the nested schemas must each be a valid JSON Schema per this subset38653866Here's an example supported anyOf schema:38673868```json3869{3870    "type": "object",3871    "properties": {3872        "item": {3873            "anyOf": [3874                {3875                    "type": "object",3876                    "description": "The user object to insert into the database",3877                    "properties": {3878                        "name": {3879                            "type": "string",3880                            "description": "The name of the user"3881                        },3882                        "age": {3883                            "type": "number",3884                            "description": "The age of the user"3885                        }3886                    },3887                    "additionalProperties": false,3888                    "required": [3889                        "name",3890                        "age"3891                    ]3892                },3893                {3894                    "type": "object",3895                    "description": "The address object to insert into the database",3896                    "properties": {3897                        "number": {3898                            "type": "string",3899                            "description": "The number of the address. Eg. for 123 main st, this would be 123"3900                        },3901                        "street": {3902                            "type": "string",3903                            "description": "The street name. Eg. for 123 main st, this would be main st"3904                        },3905                        "city": {3906                            "type": "string",3907                            "description": "The city of the address"3908                        }3909                    },3910                    "additionalProperties": false,3911                    "required": [3912                        "number",3913                        "street",3914                        "city"3915                    ]3916                }3917            ]3918        }3919    },3920    "additionalProperties": false,3921    "required": [3922        "item"3923    ]3924}3925```392639273928#### Definitions are supported39293930You can use definitions to define subschemas which are referenced throughout your schema. The following is a simple example.39313932```json3933{3934    "type": "object",3935    "properties": {3936        "steps": {3937            "type": "array",3938            "items": {3939                "$ref": "#/$defs/step"3940            }3941        },3942        "final_answer": {3943            "type": "string"3944        }3945    },3946    "$defs": {3947        "step": {3948            "type": "object",3949            "properties": {3950                "explanation": {3951                    "type": "string"3952                },3953                "output": {3954                    "type": "string"3955                }3956            },3957            "required": [3958                "explanation",3959                "output"3960            ],3961            "additionalProperties": false3962        }3963    },3964    "required": [3965        "steps",3966        "final_answer"3967    ],3968    "additionalProperties": false3969}3970```397139723973#### Recursive schemas are supported39743975Sample recursive schema using `#` to indicate root recursion.39763977```json3978{3979    "name": "ui",3980    "description": "Dynamically generated UI",3981    "strict": true,3982    "schema": {3983        "type": "object",3984        "properties": {3985            "type": {3986                "type": "string",3987                "description": "The type of the UI component",3988                "enum": ["div", "button", "header", "section", "field", "form"]3989            },3990            "label": {3991                "type": "string",3992                "description": "The label of the UI component, used for buttons or form fields"3993            },3994            "children": {3995                "type": "array",3996                "description": "Nested UI components",3997                "items": {3998                    "$ref": "#"3999                }4000            },4001            "attributes": {4002                "type": "array",4003                "description": "Arbitrary attributes for the UI component, suitable for any element",4004                "items": {4005                    "type": "object",4006                    "properties": {4007                        "name": {4008                            "type": "string",4009                            "description": "The name of the attribute, for example onClick or className"4010                        },4011                        "value": {4012                            "type": "string",4013                            "description": "The value of the attribute"4014                        }4015                    },4016                    "additionalProperties": false,4017                    "required": ["name", "value"]4018                }4019            }4020        },4021        "required": ["type", "label", "children", "attributes"],4022        "additionalProperties": false4023    }4024}4025```402640274028Sample recursive schema using explicit recursion:40294030```json4031{4032    "type": "object",4033    "properties": {4034        "linked_list": {4035            "$ref": "#/$defs/linked_list_node"4036        }4037    },4038    "$defs": {4039        "linked_list_node": {4040            "type": "object",4041            "properties": {4042                "value": {4043                    "type": "number"4044                },4045                "next": {4046                    "anyOf": [4047                        {4048                            "$ref": "#/$defs/linked_list_node"4049                        },4050                        {4051                            "type": "null"4052                        }4053                    ]4054                }4055            },4056            "additionalProperties": false,4057            "required": [4058                "next",4059                "value"4060            ]4061        }4062    },4063    "additionalProperties": false,4064    "required": [4065        "linked_list"4066    ]4067}4068```4069407040714072## JSON mode40734074JSON mode is a more basic version of the Structured Outputs feature. While4075  JSON mode ensures that model output is valid JSON, Structured Outputs reliably4076  matches the model's output to the schema you specify. We recommend you use4077  Structured Outputs if it is supported for your use case.40784079When JSON mode is turned on, the model's output is ensured to be valid JSON, except for in some edge cases that you should detect and handle appropriately.40804081408240834084To turn on JSON mode with the Responses API you can set the `text.format` to `{ "type": "json_object" }`. If you are using function calling, JSON mode is always turned on.408540864087Important notes:40884089- When using JSON mode, you must always instruct the model to produce JSON via some message in the conversation, for example via your system message. If you don't include an explicit instruction to generate JSON, the model may generate an unending stream of whitespace and the request may run continually until it reaches the token limit. To help ensure you don't forget, the API will throw an error if the string "JSON" does not appear somewhere in the context.4090- JSON mode will not guarantee the output matches any specific schema, only that it is valid and parses without errors. You should use Structured Outputs to ensure it matches your schema, or if that is not possible, you should use a validation library and potentially retries to ensure that the output matches your desired schema.4091- Your application must detect and handle the edge cases that can result in the model output not being a complete JSON object (see below)4092409340944095### Handling edge cases409640974098409941004101```javascript4102const we_did_not_specify_stop_tokens = true;41034104try {4105  const response = await openai.responses.create({4106    model: "gpt-6-astra",4107    input: [4108      {4109        role: "system",4110        content: "You are a helpful assistant designed to output JSON.",4111      },4112      {4113        role: "user",4114        content:4115          "Who won the world series in 2020? Please respond in the format {winner: ...}",4116      },4117    ],4118    text: { format: { type: "json_object" } },4119  });41204121  const message = response.output.find((item) => item.type === "message");4122  const messageContent = message?.content[0];41234124  // Check if the conversation was too long for the context window, resulting in incomplete JSON4125  if (4126    response.status === "incomplete" &&4127    response.incomplete_details.reason === "max_output_tokens"4128  ) {4129    // your code should handle this error case4130  }41314132  // Check if the OpenAI safety system refused the request and generated a refusal instead4133  if (messageContent?.type === "refusal") {4134    // your code should handle this error case4135    // In this case, the .content field will contain the explanation (if any) that the model generated for why it is refusing4136    console.log(messageContent.refusal);4137  }41384139  // Check if the model's output included restricted content, so the generation of JSON was halted and may be partial4140  if (4141    response.status === "incomplete" &&4142    response.incomplete_details.reason === "content_filter"4143  ) {4144    // your code should handle this error case4145  }41464147  if (response.status === "completed") {4148    // In this case the model has either successfully finished generating the JSON object according to your schema, or the model generated one of the tokens you provided as a "stop token"41494150    if (we_did_not_specify_stop_tokens) {4151      // If you didn't specify any stop tokens, then the generation is complete and the content key will contain the serialized JSON object4152      // This will parse successfully and should now contain  {"winner": "Los Angeles Dodgers"}4153      console.log(JSON.parse(response.output_text));4154    } else {4155      // Check if the response.output_text ends with one of your stop tokens and handle appropriately4156    }4157  }4158} catch (e) {4159  // Your code should handle errors here, for example a network error calling the API4160  console.error(e);4161}4162```41634164```python4165we_did_not_specify_stop_tokens = True41664167try:4168    response = client.responses.create(4169        model="gpt-6-astra",4170        input=[4171            {4172                "role": "system",4173                "content": "You are a helpful assistant designed to output JSON.",4174            },4175            {4176                "role": "user",4177                "content": 'Who won the World Series in 2020? Respond as {"winner": "team name"}.',4178            },4179        ],4180        text={"format": {"type": "json_object"}},4181    )41824183    message = next((item for item in response.output if item.type == "message"), None)4184    message_content = message.content[0] if message and message.content else None41854186    # Check if the conversation was too long for the context window, resulting in incomplete JSON4187    if (4188        response.status == "incomplete"4189        and response.incomplete_details.reason == "max_output_tokens"4190    ):4191        raise RuntimeError("The response was truncated before the JSON completed.")41924193    # Check if the OpenAI safety system refused the request and generated a refusal instead4194    if message_content and message_content.type == "refusal":4195        # your code should handle this error case4196        # In this case, the .content field will contain the explanation (if any) that the model generated for why it is refusing4197        print(message_content.refusal)41984199    # Check if the model's output included restricted content, so the generation of JSON was halted and may be partial4200    if (4201        response.status == "incomplete"4202        and response.incomplete_details.reason == "content_filter"4203    ):4204        raise RuntimeError("The response was interrupted by the content filter.")42054206    if response.status == "completed":4207        # In this case the model has either successfully finished generating the JSON object according to your schema, or the model generated one of the tokens you provided as a "stop token"42084209        if we_did_not_specify_stop_tokens:4210            # If you didn't specify any stop tokens, then the generation is complete and the content key will contain the serialized JSON object4211            # This will parse successfully and should now contain  "{"winner": "Los Angeles Dodgers"}"4212            print(response.output_text)4213except Exception as e:4214    # Your code should handle errors here, for example a network error calling the API4215    print(e)4216```42174218```go4219package main42204221import (4222	"context"4223	"encoding/json"4224	"fmt"42254226	"github.com/openai/openai-go/v3"4227	"github.com/openai/openai-go/v3/responses"4228	"github.com/openai/openai-go/v3/shared"4229)42304231func main() {4232	client := openai.NewClient()4233	response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{4234		Model: "gpt-6-astra",4235		Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{4236			responses.ResponseInputItemParamOfMessage(4237				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a helpful assistant designed to output JSON.")},4238				responses.EasyInputMessageRoleSystem,4239			),4240			responses.ResponseInputItemParamOfMessage(4241				responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("Who won the world series in 2020? Please respond in the format {winner: ...}")},4242				responses.EasyInputMessageRoleUser,4243			),4244		}},4245		Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{4246			OfJSONObject: &shared.ResponseFormatJSONObjectParam{},4247		}},4248	})4249	if err != nil {4250		panic(err)4251	}42524253	if response.Status == "incomplete" {4254		fmt.Println("The JSON response is incomplete.")4255		return4256	}4257	for _, output := range response.Output {4258		if output.Type != "message" {4259			continue4260		}4261		for _, content := range output.AsMessage().Content {4262			if content.Type == "refusal" {4263				fmt.Println(content.AsRefusal().Refusal)4264				return4265			}4266		}4267	}4268	if response.Status == "completed" {4269		var value map[string]any4270		if err := json.Unmarshal([]byte(response.OutputText()), &value); err != nil {4271			panic(err)4272		}4273		fmt.Println(value)4274	}4275}4276```42774278```java4279import com.openai.client.OpenAIClient;4280import com.openai.client.okhttp.OpenAIOkHttpClient;4281import com.openai.errors.OpenAIServiceException;4282import com.openai.models.ResponseFormatJsonObject;4283import com.openai.models.responses.EasyInputMessage;4284import com.openai.models.responses.ResponseCreateParams;4285import com.openai.models.responses.ResponseInputItem;4286import com.openai.models.responses.ResponseStatus;4287import com.openai.models.responses.ResponseTextConfig;4288import java.util.List;42894290ResponseCreateParams params =4291    ResponseCreateParams.builder()4292        .model("gpt-6-astra")4293        .inputOfResponse(4294            List.of(4295                ResponseInputItem.ofEasyInputMessage(4296                    EasyInputMessage.builder()4297                        .role(EasyInputMessage.Role.SYSTEM)4298                        .content("You are a helpful assistant designed to output JSON.")4299                        .build()),4300                ResponseInputItem.ofEasyInputMessage(4301                    EasyInputMessage.builder()4302                        .role(EasyInputMessage.Role.USER)4303                        .content(4304                            "Who won the World Series in 2020? Respond in the format {winner: ...}.")4305                        .build())))4306        .text(4307            ResponseTextConfig.builder()4308                .format(ResponseFormatJsonObject.builder().build())4309                .build())4310        .build();43114312try {4313  var response = client.responses().create(params);4314  if (response.status().filter(ResponseStatus.INCOMPLETE::equals).isPresent()) {4315    String reason =4316        response4317            .incompleteDetails()4318            .flatMap(details -> details.reason())4319            .map(Object::toString)4320            .orElse("unknown");4321    System.out.println("The JSON response is incomplete. Reason: " + reason);4322    return;4323  }43244325  for (var output : response.output()) {4326    if (output.message().isEmpty()) continue;4327    for (var content : output.message().orElseThrow().content()) {4328      if (content.refusal().isPresent()) {4329        System.out.println(content.refusal().orElseThrow().refusal());4330        return;4331      }4332      if (response.status().filter(ResponseStatus.COMPLETED::equals).isPresent()) {4333        content.outputText().ifPresent(text -> System.out.println(text.text()));4334      }4335    }4336  }4337} catch (OpenAIServiceException error) {4338  System.out.println("Request failed: " + error.getMessage());4339}4340```43414342```csharp4343using OpenAI.Responses;4344#pragma warning disable OPENAI00143454346string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;4347ResponsesClient client = new(key);43484349CreateResponseOptions options = new()4350{4351    Model = "gpt-6-astra",4352    TextOptions = new ResponseTextOptions4353    {4354        TextFormat = ResponseTextFormat.CreateJsonObjectFormat(),4355    },4356};4357options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a helpful assistant designed to output JSON."));4358options.InputItems.Add(ResponseItem.CreateUserMessageItem("Who won the World Series in 2020? Respond with the winner in JSON."));43594360ResponseResult response = await client.CreateResponseAsync(options);4361if (4362    response.Status == ResponseStatus.Incomplete4363    && response.IncompleteStatusDetails?.Reason == ResponseIncompleteStatusReason.MaxOutputTokens4364)4365{4366    Console.WriteLine("The response was truncated before the JSON completed.");4367}4368else if (4369    response.Status == ResponseStatus.Incomplete4370    && response.IncompleteStatusDetails?.Reason == ResponseIncompleteStatusReason.ContentFilter4371)4372{4373    Console.WriteLine("The response was interrupted by the content filter.");4374}4375else if (response.Status == ResponseStatus.Completed)4376{4377    MessageResponseItem message = response.OutputItems.OfType<MessageResponseItem>().FirstOrDefault()4378        ?? throw new InvalidOperationException("The response did not include an output message.");4379    ResponseContentPart content = message.Content.FirstOrDefault()4380        ?? throw new InvalidOperationException("The response did not include output content.");4381    Console.WriteLine(4382        content.Kind == ResponseContentPartKind.Refusal ? content.Refusal : content.Text4383    );4384}4385else4386{4387    throw new InvalidOperationException($"The response ended with status: {response.Status}");4388}4389```43904391```ruby4392require "json"4393require "openai"43944395client = OpenAI::Client.new4396response = client.responses.create(4397  model: "gpt-6-astra",4398  input: [4399    {4400      role: :system,4401      content: "You are a helpful assistant designed to output JSON."4402    },4403    {4404      role: :user,4405      content: "Who won the World Series in 2020? Respond in the format {winner: ...}."4406    }4407  ],4408  text: { format: { type: :json_object } }4409)44104411if response.status == OpenAI::Responses::ResponseStatus::INCOMPLETE4412  warn("The JSON response is incomplete.")4413else4414  refusal = response.output4415                    .grep(OpenAI::Models::Responses::ResponseOutputMessage)4416                    .flat_map(&:content)4417                    .find { |content| content.is_a?(OpenAI::Models::Responses::ResponseOutputRefusal) }44184419  if refusal.is_a?(OpenAI::Models::Responses::ResponseOutputRefusal)4420    puts(refusal.refusal)4421  elsif response.status == OpenAI::Responses::ResponseStatus::COMPLETED4422    puts(JSON.pretty_generate(JSON.parse(response.output_text)))4423  end4424end4425```44264427442844294430443144324433## Resources44344435To learn more about Structured Outputs, we recommend browsing the following resources:44364437- Check out our [introductory cookbook](https://developers.openai.com/cookbook/examples/structured_outputs_intro) on Structured Outputs4438- Learn [how to build multi-agent systems](https://developers.openai.com/cookbook/examples/structured_outputs_multi_agent) with Structured Outputs
Files main
Menu

Theme