Format output_schema: $ref "#" fails, a $defs self-reference works
Sume rejects root recursion via $ref "#" in output_schema as unsupported_ref but accepts a $defs entry that references itself. How to write a tree.

For a recursive result such as a scene tree, put the repeating shape in a root-level $defs entry and let that entry $ref itself. Sume's Format output_schema accepts that, but it refuses the shortcut "$ref": "#" that points at the whole document, with 400 output_schema_invalid and the rule unsupported_ref.
The facts come from the Structured output page. OpenAI's Structured model outputs page, read 2026-10-03, shows recursive schemas using $ref and $defs, so the named-definition style travels between the two.
Which $ref targets resolve?
Only two targets resolve in Sume. Anything else, including a URL or a path under #/components, is rejected.
| Target | Use | Notes |
|---|---|---|
#/$defs/* | Your own definitions | $defs must be declared at the root of the schema document |
SumeMediaFile# | Sume's media shape | For video, image, audio or file fields in output |
# | Not accepted | Root recursion is permitted by OpenAI strict mode; Sume does not allow it |
| External URL or sibling document | Not accepted | unsupported_ref |
Why does a nested $defs block fail?
A #/$defs/* target with no matching entry at the root is rejected too. That catches a $defs block tucked inside a sub-schema, which is the usual mistake when a schema is assembled from fragments. Move it to the top level, next to type and properties.
$ref and anyOf also short-circuit the node they sit on. Sibling keywords are checked against the allowlist but carry no meaning, so put constraints inside the $defs entry or the anyOf branches, not beside the $ref.
How do I write a recursive definition that is accepted?
The docs state that recursion through a named definition is fine: a $defs entry may $ref itself. Because a self-reference is not literal nesting, it does not consume the 10-level depth limit.
The sketch below describes a section that holds a title and a list of child sections. The recursion is the children array, whose items point back at the same definition; an empty array ends it, so no property needs to be optional. Every property stays required and every object stays closed. Treat it as a starting point and send it to a test run before depending on it.
{
"type": "object",
"additionalProperties": false,
"required": ["root"],
"properties": { "root": { "$ref": "#/$defs/section" } },
"$defs": {
"section": {
"type": "object",
"additionalProperties": false,
"required": ["title", "children"],
"properties": {
"title": { "type": "string" },
"children": { "type": "array", "items": { "$ref": "#/$defs/section" } }
}
}
}
}What still limits a recursive schema?
The size limits apply to the document you send, not to the runs it permits: 10 levels of literal nesting, 5000 properties and 120,000 characters of strings, summed across the document. They report as max_depth, max_properties and max_string_length.
Sume does not publish a cap on how deep the run's own tree may go, so keep recursive output shallow in the instruction. If a run cannot fill the shape, the failure arrives later on the receipt as output_schema_unsatisfied, with the media still in artifacts[].
What does the rejection look like?
A schema that uses "$ref": "#" returns 400 output_schema_invalid with a violation whose rule is unsupported_ref. The rule's definition in the docs covers any $ref that is neither #/$defs/<name> nor SumeMediaFile#, and also one that names a definition that does not exist.
The fix is mechanical: lift the repeating shape into root $defs, give it a name, and point both the entry point and the recursive property at #/$defs/<name>. Nothing else in the schema needs to change.
Sources
Related posts
More in Formats
- Format output_schema root must be an object: wrap an array root
A Sume Format run rejects an output_schema whose root is an array or type union with 400 and rule root_must_be_object. Wrap it in a named key.
- Format output_schema strict false: no loose JSON mode on Sume
Sending strict: false with a Sume Format output_schema is accepted but relaxes nothing, and there is no json_object mode. Bind a schema or use the built-in.
- Format run media URLs are public: copy on webhook or proxy
Sume Format run media lives at durable public media.sume.com URLs. If customer A must not see customer B's video, copy it at receipt time or proxy it.
- Format run spend cap: above the Format cap is honored, null is $500
generation_spend_cap_usd on a Sume Format run may exceed the Format's cap and is not clamped; null runs at the $500 maximum; 0 or over 500 is a 400.
Written by Sume