OpenAI response_format json_schema to a Sume output_schema
Moving a json_schema from OpenAI structured outputs to a Sume Format run: the field name, what transfers, no JSON mode, and why output comes once, post-run.

Send your schema to a Sume Format run as output_schema, or paste the OpenAI-shaped response_format object unchanged. Most of the strict-mode rules you already follow carry over. The difference is where the schema applies: OpenAI constrains what the model says, while Sume constrains how a finished run is read back.
Sume's structured output docs have a table for this move. This post walks through it.
What does the request look like?
response_format is accepted as an alias for output_schema, in the Chat Completions spelling only. Sending both fields is 400 invalid_request, and the text.format spelling from the Responses API is not accepted. The name is required in both places; Sume says to namespace it, because it lands on every receipt.
{
"instruction": "Write the headline and render a hero image.",
"input": { "product_url": "https://shop.example.com/p/8823" },
"output_schema": {
"name": "acme/hero/v1",
"strict": true,
"schema": {
"type": "object",
"additionalProperties": false,
"required": ["headline", "hero_image"],
"properties": {
"headline": { "type": "string" },
"hero_image": { "$ref": "SumeMediaFile#" }
}
}
}
}Which rules are the same?
The OpenAI guide requires the root to be an object, additionalProperties: false, and every field declared required, with optional fields written as a union with null. Sume enforces the same ones, and goes further with an allowlist: a keyword not on it is a violation rather than silently ignored. oneOf is rejected, so use anyOf; allOf is rejected, so flatten the branches. See how to make a field optional.
What is different?
Check this table before porting code.
| Topic | OpenAI | Sume Format run |
|---|---|---|
| Loose JSON | JSON mode exists beside schema mode | No equivalent of json_object; bind a schema or take the built-in one |
strict | Enforces schema adherence | Accepted and defaults true, but changes nothing: the subset is always enforced |
| Who emits the JSON | The model | A post-run projection |
| Refusals | A refusal field | output_error on the receipt, a failed projection rather than a safety refusal |
| Streaming | Partial JSON can stream | output appears once, on the terminal receipt |
| Root recursion | Permitted via $ref: "#" | Rejected; recurse through a named #/$defs/* entry |
| Media | Not applicable | SumeMediaFile# plus the URL gate |
What about the built-in shape?
Bind nothing and output is projected onto sume/action-run-output/v1: a nullable text and four arrays, images, videos, audio and files. It is filled deterministically from the run's media and final text, with no model involved, so it cannot fail the way a custom schema can. If you want the media without designing a schema, that is enough to ship on.
What should I change in my code?
Stop expecting the JSON in a message. Create the run, take the webhook or poll, check output_error, then read output. Reserve a field for each media file and use SumeMediaFile# rather than a bare string. Set primary_output_key to the field your UI shows.
Do not expect values you sent in input to come back in output: the projection never sees them. For a longer tour of the subset, see Sume Format structured output.
What does a failed projection look like compared with a refusal?
There is no safety refusal to detect. When a run completes but its result does not fit your schema, the receipt carries output_error with a code such as output_schema_unsatisfied, and over the API the run is failed, so status is the first branch. The media is still in artifacts[]. Handle output: null on both a failed and a completed receipt, as the docs' checklist says.
Sources
Related posts
More in Formats
- Sume agent_reported_failure: the three reasons and what to do
agent_reported_failure on a Sume run means the run's own receipt said it did not deliver. Its details.reason tells you which of three cases it was.
- Sume primary_output_missing: schema satisfied, run still failed
A Sume run can match your output_schema and still end failed with primary_output_missing. It means the key named in primary_output_key had no value.
- Sume output_extraction_failed: the run stays completed, reread it
output_extraction_failed with reason harvest_unavailable is transient. The Sume run stays completed and fills in on your next read; retry only if it persists.
- Pick a Format from the list: io profile and showcase before you run
GET /v1/formats returns each Format with an io profile (input_kind and output_kind) and a showcase output, so you can choose one without paying for a trial run.
Written by Sume