Core
Structured output
JSON mode and json_schema, and why the list of models that support it is shorter than any supplier's catalogue says.
Pass response_format, in either of OpenAI’s two forms.
reply = client.chat.completions.create(
model="gpt-oss-120b",
messages=[{"role": "user", "content": "Nairobi, Kenya. Population about 5.5 million."}],
response_format={
"type": "json_schema",
"json_schema": {
"name": "city",
"strict": True,
"schema": {
"type": "object",
"properties": {
"city": {"type": "string"},
"country": {"type": "string"},
"population": {"type": "integer"},
},
"required": ["city", "country", "population"],
"additionalProperties": False,
},
},
},
)
import json
print(json.loads(reply.choices[0].message.content))reply = client.chat.completions.create(
model="gpt-oss-120b",
messages=[
{"role": "system", "content": "Reply with JSON only."},
{"role": "user", "content": "Nairobi, Kenya. Population about 5.5 million."},
],
response_format={"type": "json_object"},
)json_object needs the word JSON somewhere in your messages, same as OpenAI. Prefer json_schema
where the model supports it: it constrains the shape rather than asking politely.
The supported list is shorter than suppliers claim
Check Can do on Models or supported_parameters on GET /v1/models. Asking a
model that does not declare it is a 400:
{
"error": {
"message": "Model \"llama-3.3-70b\" does not support `response_format`.",
"type": "invalid_request_error",
"param": "response_format",
"code": "unsupported_parameter"
}
}
An error before any billable work, rather than a paid-for answer in the wrong shape.
Reasoning models
They think before producing the JSON, and the thinking is billed. Give them room: a max_tokens
sized for the JSON alone can be consumed entirely by reasoning, leaving you an empty string. See
Models.