Structured outputs
Purpose and Scope
Structured Outputs are the OpenAI API feature for asking a model to produce data that conforms to a supplied JSON Schema rather than only loosely following natural-language formatting instructions. In application code, this matters because downstream services usually need predictable keys, valid enum values, and stable object shapes. The official platform documentation frames this as a reliability feature with type-safety, programmatically detectable refusals, and simpler prompting. In the JavaScript SDK workflow, the usual reader task is to define the target shape in TypeScript-friendly code, send it with a model request, and consume the parsed result without writing a custom retry loop for malformed JSON.
This page focuses on the SDK-facing constraints that surround structured output usage: model selection, evaluation graders that require structured-output-capable models, project-level model permissions, and provider or identity configuration that can affect where requests are sent. The supplied source paths do not expose the helper implementation itself, but they do show the generated contracts and runtime boundaries that determine whether a structured-output request can be made successfully. Treat Structured Outputs as a request pattern layered on top of the SDK's generated resources, rather than as a separate client.
Sources: src/resources/graders/grader-models.ts, src/resources/models.ts, src/resources/admin/organization/projects/model-permissions.ts
Relevant Source Files
src/resources/graders/grader-models.ts- defines grader input shapes and theLabelModelGradercontract, including the requirement that the grader model must support structured outputs.src/resources/models.ts- defines the generatedModelsresource used to list, retrieve, and delete model objects by model identifier.src/resources/admin/organization/projects/model-permissions.ts- defines project-level model permission retrieval, updates, and deletion for allow-list or deny-list policies.src/auth/subject-token-providers.ts- defines subject token providers for workload identity flows that may be used in automated deployments that call structured-output endpoints.src/internal/provider.ts- defines the opaque provider mechanism used to configure provider-specific runtimes with a base URL and request preparation hook.src/providers/bedrock.ts- defines thebedrock()provider factory for routing the standard OpenAI client through Amazon Bedrock bearer authentication.
Core Primitives
A structured-output workflow has three practical primitives. The first is the schema: the JSON Schema supplied to the API, or a schema defined in code and converted by SDK helpers such as the Zod-based helper described in the official JavaScript documentation. The second is the model: the model named in the request must support Structured Outputs, and generated SDK types make model identifiers ordinary strings that flow through resource calls. The third is the result contract: application code should consume the structured result as typed data and handle explicit refusals separately from valid schema-conforming output.
The source-backed example of a structured-output dependency appears in the graders resource. LabelModelGrader is a model-backed evaluation grader that assigns labels to items, and its model field is documented as a model that must support structured outputs. That makes eval configuration a useful concrete mental model: the schema-like label set is not only prompt guidance; the grader's model is expected to produce a constrained label from the allowed labels, and passing_labels must be a subset of those labels. Its input messages also preserve instruction hierarchy through developer, system, user, and assistant roles.
Sources: src/resources/graders/grader-models.ts
Zod and JSON Schema Flow
In JavaScript and TypeScript projects, Zod is commonly used to express an object shape close to the application domain model, then convert that shape into the JSON Schema used by a model request. The official docs describe this as the JavaScript SDK counterpart to Python's Pydantic parsing helpers. The point is not only syntactic convenience: defining the schema in code keeps the schema, inferred TypeScript type, and runtime parsing expectation near each other. A typical flow is to define a Zod object, pass it through the SDK's structured-output helper for the response format or function parameters, then read the parsed value after the request completes.
A minimal conceptual pattern looks like this: define the object you need, choose a model that supports Structured Outputs, and make refusal handling explicit before trusting the parsed object. The exact helper entry point depends on whether the structured shape is used for text.format style responses or function calling. Function calling is appropriate when the model should select or call application functionality; a json_schema response format is appropriate when the model should return a structured answer for your application to consume directly. Both forms rely on the same discipline: keep the schema narrow, mark required fields intentionally, and prefer enums when the output space is known.
import { z } from 'zod';
const Ticket = z.object({
category: z.enum(['billing', 'technical', 'account']),
priority: z.enum(['low', 'medium', 'high']),
summary: z.string(),
});
// Use the SDK structured-output helper documented for JavaScript to
// convert this schema into a response format or function schema, then
// call a structured-output-capable model and handle refusals separately.The generated source in this evidence set reinforces one important design constraint: model identifiers are explicit data, not hidden SDK magic. The Models resource retrieves a model by identifier, lists available models, and deletes fine-tuned models when permitted. The returned Model object includes id, created, object, and owned_by, which are useful for inventory and administration, but capability choice still belongs to the request author and platform documentation. For Structured Outputs, use the docs-supported model family for new work and avoid assuming that every listed model supports schema-constrained generation.
Sources: src/resources/models.ts
System-to-Code Mapping
The SDK is generated from the OpenAPI specification, so resource classes mostly expose endpoint methods and typed request or response objects. In src/resources/models.ts, the Models class maps retrieve(model), list(), and delete(model) to /models endpoints with bearer authentication. That resource helps applications discover and reference model IDs, which are the same values passed to structured-output requests, grader definitions, and other model-backed operations. Because Model only describes basic model metadata, the application should combine SDK model inventory with platform guidance about Structured Outputs support.
Project governance is represented separately by ModelPermissions. Its retrieve(projectID), update(projectID, body), and delete(projectID) methods operate on /organization/projects/{projectID}/model_permissions with admin API key security. The policy object uses mode: 'allow_list' | 'deny_list' plus model_ids. In structured-output deployments, this is a control plane concern: even if application code names a capable model, project policy can determine whether that model is available to the project that owns the request. Keep schema design and permission design separate so production failures are easier to diagnose.
Provider configuration is another boundary around structured-output calls. src/internal/provider.ts defines an opaque Provider, a ProviderRuntime with name, baseURL, and optional prepareRequest, plus createProvider() and configureProvider(). The registry uses a global symbol and WeakMap so providers created by one package copy can work with another copy across CommonJS and ESM installations. For structured-output users, the main implication is that provider routing and request signing are configured before the generated resource call; they do not change the JSON Schema contract, but they can change authentication, endpoint, and availability behavior.
Sources: src/resources/models.ts, src/resources/admin/organization/projects/model-permissions.ts, src/internal/provider.ts
Runtime and Authentication Considerations
Structured Outputs are often used in production automation, eval pipelines, and service-to-service workflows, so authentication deserves the same care as schema design. src/auth/subject-token-providers.ts defines token providers for workload identity patterns. The Kubernetes provider reads and trims a service account token from a configurable path and raises SubjectTokenProviderError when the file cannot be read or is empty. The Azure managed identity provider calls the IMDS endpoint with resource, API version, optional identity selectors, timeout handling, and a required access_token field in the JSON response.
These providers are not structured-output helpers, but they support the environments where structured outputs are valuable: scheduled evaluators, internal services, cloud workloads, and CI-style agents that should avoid hard-coded secrets. If a structured-output request fails before model execution, inspect the identity layer before changing the schema. Empty token files, IMDS timeouts, missing access tokens, or provider-specific request preparation failures are transport and authentication problems. Keeping those failures distinct from schema refusals or validation errors makes incident response much faster.
Amazon Bedrock integration is represented by src/providers/bedrock.ts. The bedrock(options) factory resolves an endpoint and bearer authentication, then returns a provider runtime named bedrock with a configured baseURL and prepareRequest hook. It throws an OpenAIError if bearer authentication cannot be resolved from apiKey, tokenProvider, or AWS_BEARER_TOKEN_BEDROCK, and directs AWS credential authentication users to the AWS-specific provider import. When routing structured-output requests through Bedrock, confirm both the provider authentication path and the target model capability before debugging the schema itself.
Sources: src/auth/subject-token-providers.ts, src/internal/provider.ts, src/providers/bedrock.ts
Compact Reference
| Area | Source-level contract | Structured-output relevance |
|---|---|---|
| Model inventory | Models.retrieve(model), Models.list(), Models.delete(model) | Use model IDs deliberately and verify that the selected model supports Structured Outputs before relying on schema adherence. |
| Model object | Model.id, Model.created, Model.object, Model.owned_by | Basic metadata helps administration, but capability support is not encoded in this object shape. |
| Project permissions | ModelPermissions.update(projectID, { mode, model_ids }) | Allow-list or deny-list policies can permit or block the model used by a structured-output request. |
| Eval graders | LabelModelGrader.model, labels, passing_labels, input, type: 'label_model' | The grader explicitly requires a model that supports structured outputs and constrains labels for scoring. |
| Provider runtime | ProviderRuntime.name, baseURL, prepareRequest() | Provider routing and request preparation happen around the API call without changing the JSON Schema contract. |
| Bedrock provider | bedrock(options) | Configures Bedrock endpoint and bearer auth for the standard client; authentication must be valid before structured-output behavior can be observed. |
| Workload identity | k8sServiceAccountTokenProvider(), azureManagedIdentityTokenProvider() | Enables non-interactive deployments that call model endpoints without embedding static credentials. |
Implementation Guidance and Next Steps
Start by deciding whether the structured value is the final answer or an instruction to call application code. Use a direct JSON Schema response format when your application needs a typed extraction, classification, or transformation result. Use function calling when the model should select a tool and provide typed arguments for code you will execute. In both cases, design the schema as an interface between the model and your code: keep fields meaningful, avoid ambiguous unions where possible, define enums for closed choices, and make refusal handling part of the control flow rather than an afterthought.
Before shipping, verify three operational assumptions. First, the request names a model that supports Structured Outputs; generated model listing is useful for inventory, but the platform docs define capability guidance. Second, the project policy allows that model, especially in organizations using admin model permissions. Third, the runtime provider and token source are configured correctly for the deployment environment. If a workflow is part of an evaluation system, review LabelModelGrader closely because its labels, passing labels, input roles, and structured-output-capable model requirement mirror the same constraints that production classification systems usually need.
Next, read the Responses API and function-calling pages for request-level examples, the Evals pages for grader workflows, and the provider/authentication pages if your structured-output workload runs outside the default OpenAI endpoint. For implementation work, keep schema definitions near the TypeScript types that consume them, add tests for refusal and invalid-environment cases, and log enough model ID, project, and provider metadata to distinguish schema issues from authentication or permission failures.
Sources: src/resources/graders/grader-models.ts, src/resources/models.ts, src/resources/admin/organization/projects/model-permissions.ts, src/auth/subject-token-providers.ts, src/internal/provider.ts, src/providers/bedrock.ts