The August 2024 announcement made output shape more dependable. A worked repairs enquiry shows why structure, evidence and diary availability still need different checks.
A date can arrive in precisely the right field and still be the wrong day. That is a useful place to start when deciding what structured model output buys an application. Having dependable JSON removes the work of stripping introductions, repairing trailing commas and persuading a paragraph to become a record. It also leaves us with a much easier object to inspect when the proposed appointment disagrees with the customer’s message.
OpenAI announced Structured Outputs on 6 August 2024, describing schema-constrained outputs for supported API use [1]. For software consuming the response, the stronger contract reduced the guesses needed to parse it. The checks that remain after parsing concern whether the values reflect the enquiry and whether the business can act on them. Those questions require evidence beyond the shape of the response.
Take an invented repairs enquiry asking for a visit on 13 August at 9 Pine Road. The accompanying checker uses hand-written candidate records, rather than calling a model, to separate the decisions an application must make. One candidate changes the day; another changes the house number. Both look orderly. Putting the message beside them reveals the disagreement immediately, which is more helpful than asking a single validation result to stand for parsing, faithful extraction and permission to book.
Four fields, three different questions
The source message says: Please visit on 13 August 2024 at 9 Pine Road. A useful draft keeps the requested date and address beside the words supporting them. Here those four fields are requested_date, date_evidence, requested_address and address_evidence, each accepting text or an explicit null. The faithful candidate pairs 2024-08-13 with 13 August 2024 and preserves 9 Pine Road. The office can inspect both the proposed value and the part of the message it claims to represent.
A second candidate uses 2024-08-14 but keeps the same evidence phrase. It is still JSON, still an object, and still has four permitted string values. A third changes the proposed address to 99 Pine Road. A shape validator accepting either object has done its own job correctly. It was asked about keys and value types, not whether those values corresponded to the message.
JSON Schema’s object documentation distinguishes property definitions, required properties and restrictions on additional properties [2]. Those choices need to be explicit in a real contract. Declaring that a property can contain text does not require it to appear; defining known properties does not by itself reject extra ones. A superficially strict-looking schema may therefore be looser than its author intended, even before semantic accuracy enters the discussion.
A production integration needs a complete JSON Schema validator and the request configuration appropriate to its API version. The downloadable checker only enforces this four-field nullable-string contract. The August announcement explains the feature as released; current documentation covers implementation and failure handling [3]. Keeping those responsibilities clear matters when replacing this small checker: a stricter validator can reject extra fields or a missing property, but it still needs a separate way to discover that the customer asked for the thirteenth and the record proposes the fourteenth.
Which part of the response can be checked?
The repairs example separates API response handling from four-field interpretation.
Follow the labelled arrows. On a narrow screen, scroll sideways if needed.
The local checker implements only the stated tiny shape contract, not a complete provider integration.
Put evidence next to the value
The date and address comparisons use an answer key labelled by hand. The wrong-day and wrong-house candidates pass the shape check, then fail against those expected facts. For an explicit message, that disagreement is straightforward to explain: the retained phrase names 13 August, while the proposed value names 14 August. A reviewer can correct the value without wondering whether the diary caused the rejection. Less explicit messages require a different response, because there may be no single date in the source to compare with the draft.
In production, the evidence stage might combine deterministic checks with review. A clearly stated date can be compared with a parsed source phrase. A reference to the usual address may require an authorised customer lookup and still remain ambiguous if several addresses exist. Do not give every extracted value the same apparent status merely because each occupies a column. Stated, resolved from another record and inferred are different reasons to believe a value.
Consider a second constructed message: Tuesday afternoon would be ideal; use the same address as before. A record with unresolved date and address can be a faithful intermediate result. The message contains preferences, but this contract has not established which date or which address. Converting absence into a fabricated completed record would improve the spreadsheet’s appearance while worsening its account of what the customer actually supplied.
An unresolved record therefore passes the small structure contract and goes to clarification. An unsupported value goes to review for a different reason: it proposes something the evidence does not justify. An office colleague needs that distinction. Asking which Tuesday the customer means is ordinary missing-information work; discovering that the record says Wednesday when the message says Tuesday is a different problem. Keeping the stopping reason with the record saves them from reopening the whole workflow just to work out which conversation to have.
A correct request can still be unavailable
Return to the explicit 13 August message and suppose both the date and address are represented correctly, with the address inside the service area. The diary may still have no available slot. Extraction quality cannot answer that question because availability depends on current business state. The application needs to check the diary after interpreting the request, while keeping a proposed visit separate from a reserved appointment.
Check that same faithful candidate against two invented diary states. When slot_available is false, it stays draft-only and needs an alternative; when true, it becomes an eligible draft awaiting separate approval. The source message is unchanged. A person can therefore see why a perfectly extracted request still cannot be booked, and avoid sending it back for another extraction. If the diary changes between that check and reservation, the reservation operation must still establish whether the slot is available when it commits.
Calendar validity belongs earlier in the process. A string such as 2024-02-31 fits an unrestricted text field but cannot name an appointment day. Python’s date parser rejects that candidate in the checker. A constrained schema or format validator could catch it sooner. That would save the office an impossible-date review, while leaving the Wednesday-versus-Tuesday problem untouched: both days can be real dates. The choice of validator should make an error easier to locate rather than turn every rejected draft into another unexplained extraction failure.
This suggests a practical processing order: confirm the response is usable, validate its structure, establish evidence support, then apply the rules and current state that govern the proposed action. Preserve the reasons for stopping. The operator needs to distinguish missing customer information from an unavailable diary slot; otherwise both become an unexplained failed item and the automation merely moves the investigation into a queue.
The same shape can lead to different work
Nine local assertions passed for constructed records separating structure, source support and diary conditions. No model calls or bookings were made.
Scroll sideways to see all columns.
Constructed case
Shape
Source support
Business check
Next action
Date 14; source says 13
Pass
Fail
Not run
Review unsupported value
Address 99; source says 9
Pass
Fail
Not run
Review unsupported value
Correct source; full diary
Pass
Pass
No slot
Offer alternative
Correct source; free slot
Pass
Pass
Slot available
Eligible draft
Date and address unresolved
Pass
Pass
Missing details
Clarify
2024-02-31
Pass
Not checked
Invalid date
Review date
Refusal / incomplete
Not parsed
Not checked
Not run
Keep original enquiry
The checker compares hand-labelled expected facts with constructed candidates. A shape pass can leave an unsupported date, an unavailable slot or a response that still needs approval.
Some responses should never reach the field checker
The original announcement also described refusal and unfinished generation as cases requiring handling [1]. A response that stops before completing the object is not an extraction with several empty fields. It is an incomplete response. A refusal is not a successful object whose contents happen to say no. Check those outcomes through the documented API response information rather than manufacture an empty success record because downstream code expects one.
The example translates API outcomes into three internal kinds: output, refusal and incomplete. Only output reaches the field checks. A refusal keeps its reason; an incomplete response leaves the enquiry waiting for a usable result. This translation belongs in an adapter tied to the chosen API version, rather than in assumptions scattered through the booking code. The office should not see four empty fields when the actual problem is that no complete record arrived. Otherwise it may ask the customer for information the customer already supplied.
What the trial should measure next
A live trial would add representative messages and independently agreed expected outcomes. Corrected dates, forwarded threads, multiple addresses and enquiries that are not booking requests belong there if they occur in the real workload. Keep source agreement separate from schema compliance, and record how much time reviewers spend resolving each stopping reason. A parser improvement may be valuable even when autonomous booking remains inappropriate.
There is a cost to retaining evidence: more fields, more review context and potentially more personal information. Keep only what the task needs, control access and establish retention. If every draft still requires a full reread, simplify the task before adding more elaborate metadata. For a very small inbox, a clearer enquiry form or a few deterministic checks may do more useful work than an extraction model.
I would want the person using this workflow to see whether the record describes the customer’s request, an available proposal or a reserved appointment. The distinction should survive export as well as the original screen. If availability is the obstacle, show that beside the supported date instead of discarding a good extraction. If the date is unsupported, keep the message visible for correction. A dependable structure makes these records easier to handle; the stopping reason tells the office which part of the job still needs doing.
Working on a workflow like this? Hamsa helps finance and operations teams connect their tools and handle the exceptions, starting with one workflow.
A saved replacement, a running service and an attacker’s existing access can change at different times. Railway’s guidance explains why that matters; PingCAP and PHP show where the next job differs.