Gemini recursive schema with $ref "#": what Sume accepts instead

Gemini's docs show an org-chart schema that recurses with $ref "#". Sume rejects that root reference; recurse through a named $defs entry instead.

4 min readSume
All posts

A Gemini schema that recurses with "$ref": "#" will not pass Sume's output_schema check. Sume rejects $ref: "#" with 400 output_schema_invalid; the same recursion works if you move the node into a named $defs entry at the root and point $ref at #/$defs/<name>.

Google's Structured outputs page includes a "Recursive Structures" example, an organization chart where each employee has a reports array whose items is { "$ref": "#" } (read 2026-10-02). Porting that schema to a Sume Format run or an Agent Completion needs three edits, listed below. Nothing runs and nothing is charged when the schema is rejected, so a mistake costs one request.

What does the Gemini example do?

The page defines name, employee_id and reports, lists all three in required, and makes reports an array whose items refer back to the whole schema with $ref: "#". The Python version generates the schema from a Pydantic model with a self-referencing Employee type.

That shape is legal on Gemini's side. It is not legal on Sume's, because Sume's Structured output page lists exactly two $ref targets: #/$defs/* and SumeMediaFile#. It says $ref: "#" is rejected even though OpenAI's strict mode permits root recursion that way.

How do I write the same tree on Sume?

Declare the node once under $defs at the root of the schema document, then let that definition refer to itself. Sume's page says recursion through a named definition is fine, and that the depth limit counts literal nesting in the document, so a self-referential definition does not consume it.

Two further rules apply to every object in the schema, including the one inside $defs: additionalProperties must be false, and every declared property must be in required. The root type must be exactly object, so the tree sits under a property such as team.

{
  "name": "acme/org-chart/v1",
  "strict": true,
  "schema": {
    "type": "object",
    "additionalProperties": false,
    "required": ["team"],
    "properties": { "team": { "$ref": "#/$defs/employee" } },
    "$defs": {
      "employee": {
        "type": "object",
        "additionalProperties": false,
        "required": ["name", "employee_id", "reports"],
        "properties": {
          "name": { "type": "string" },
          "employee_id": { "type": "integer" },
          "reports": { "type": "array", "items": { "$ref": "#/$defs/employee" } }
        }
      }
    }
  }
}

How do the two schema dialects compare?

The rows below compare only what each page states.

Gemini row from the Structured outputs page (read 2026-10-02); Sume row from the Structured output docs page (read 2026-10-02).
RuleGemini pageSume docs
Root recursionExample uses $ref: "#" in items$ref: "#" rejected
Named recursionNot shown on the pageAllowed through #/$defs/*
Root typeExample root is an objectMust be exactly object
Closed objectsadditionalProperties accepts a boolean or a schemaadditionalProperties: false on every object
Optional fieldsAdd "null" to the type arrayNullable union; every property stays in required

What else should I check before sending it?

Sume describes output_schema as a contract for how a finished run is read back, not a constraint on the run itself. A recursive tree is therefore filled from the run's closing text and media, or by the run submitting the object itself; the receipt's filled_by says which. If a field is something only your input contained, the projection path cannot see it.

Read the details.violations[] array on a 400. Each entry has a path, a stable rule token and a message, and every problem is reported in one response, so one failed request is enough to fix the schema.

  • Move the recursive node under root $defs.
  • Replace each $ref: "#" with #/$defs/<name>.
  • Add additionalProperties: false to every object, and list every property in required.
  • Wrap the tree so the root is an object.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume