So far you asked for JSON and then defended yourself: cut out the fences, catch the error, validate, retry. With structured outputs you stop asking. You send a JSON schema, a description of the JSON you want, and the API makes the reply's text valid JSON that fits it, every time.
A schema is a dictionary. It says the answer is an object, names each key with its type, lists the keys that must be there, and forbids any others. Here is one for a hotel booking with a single key:
booking_schema = {
"type": "object",
"properties": {
"city": {"type": "string"},
},
"required": ["city"],
"additionalProperties": False,
}
The schema travels with the request, in the output_config argument of messages.create. The reply is then pure JSON: no fences and no extra sentence, so json.loads reads it without a try.
A schema knows shapes: which keys, which types. It knows nothing about your data. Order 77 is a perfectly valid whole number, but the shop has no order 77, so that check stays in your code.
The finished program prints this. The last four lines come from the check: what your requests sent.
Reply: {"order_id": 4, "sentiment": "negative"}
Order 4 is delivered | sentiment: negative
Reply: {"order_id": 77, "sentiment": "negative"}
No order 77 in the shop: ask the customer to check the number.
Reply: {"order_id": 6, "sentiment": "positive"}
Order 6 is delivered | sentiment: positive
Model calls: 3
Calls that sent the schema: 3
Schema fields: order_id (integer), sentiment (string)
Required: order_id, sentiment
Your task: the program already asks the model about three customer messages, and it crashes on the first fenced reply. Write a schema with an integer order_id and a string sentiment, send it with every request, then check each order id against ORDERS and print the right line.
Assignment
Follow the Coding Tutorial to build the schema, send it with output_config, and check that each order exists in the shop.
Hint
The schema changes nothing until the request sends it: the program keeps crashing until the output_config line is in messages.create. Python writes False with a capital F, and not in with a dictionary looks at its keys.
Free plan: 30 tutor messages. PRO is unlimited.
