Pull requests / #810

#810 serve: accept json_schema roots that are unions of object schemas

closed · @canfieldjuan · 0 commentaires · Sur GitHub

Setup & installServer & APISecurityDocumentationLinux

Description

## Problem

`response_format: {"type":"json_schema", ...}` returns 400 `response_format schema must have type object at its root`
for a root `anyOf`/`oneOf` of object schemas, for example:

```json
{"anyOf": [
  {"type": "object", "properties": {"claim_text": {"type": "string"}}, "required": ["claim_text"], "additionalProperties": false},
  {"type": "object", "properties": {"outcome": {"type": "string", "enum": ["no_substantive_content"]}}, "required": ["outcome"], "additionalProperties": false}
]}
```

llama.cpp's server accepts this schema (it compiles it to a grammar), so apps written against it send it. On Strata
those apps fail, although every answer the schema allows is one JSON object.

## Change

- `serve/structured.py`: `_only_objects()` decides whether a root can only ever be a JSON object:
  - `"type":"object"`;
  - an `anyOf`/`oneOf` whose branches all qualify;
  - an `allOf` with a qualifying member;
  - a local `$ref` to one of these. A `$ref` cycle never qualifies.

  `prepare_format` uses it instead of the literal `type == "object"` check, so two things stay true: the "return
  exactly one JSON object" directive, and the object check when `jsonschema` is not installed. A root that also
  allows an array, string, number, boolean or null is still refused with a 400 before the engine loads. That
  includes `"type":["object","null"]` and a schema without a `type`.
- `docs/DETAILS.md`: the root rule.

## Tests

- `serve/test_structured.py` has two new tests:
  - root unions (`anyOf`, `oneOf`, `allOf`, `$ref`, nested) are accepted, and a non-object answer to them is still refused (502);
  - 11 roots that allow non-objects are refused with 400, and the engine is never loaded.
- `python -m unittest serve.test_structured`: 10 OK.
  - Without `jsonschema`: 2 skipped, as before.
  - With `jsonschema` 4.x installed: 0 skipped.
- `python -m unittest serve.test_server serve.test_security serve.test_lifecycle serve.test_detok serve.test_mcp serve.test_monitor serve.test_winjob`:
  214 OK (7 skipped). Run on Linux (Ubuntu 24.04, Python 3.13) against current `main`.

Also checked end to end: a document-summarizer app that sends a schema like the one above now gets its answers from
Strata instead of a 400.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Sur le site

Liens install, modèles, releases.