Pull requests / #810
#810 serve: accept json_schema roots that are unions of object schemas
closed · @canfieldjuan · 0 comentários · No GitHub
Setup & installServer & APISecurityDocumentationLinux
Descrição
## 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)
No site
Links install, modelos, releases.