Atlas Inference

JSON Schema subset

atlas-json-schema-subset-v1 — every keyword accepted, every keyword refused, and every violation code.

Structured output schemas are validated against a published, versioned subset of JSON Schema. Its identifier is atlas-json-schema-subset-v1, and each model reports the subset it uses as capabilities.json_schema_subset on GET /v1/models.

The subset is published rather than discovered so you can validate a schema in your own build, before it ever reaches Atlas. A schema outside it is refused at request validation — never answered with unvalidated content.

Accepted keywords

Structural

type · properties · required · additionalProperties · items · enum · const · anyOf · $defs · $ref

Annotations

title · description · examples · default · $comment · $schema · $id

Annotations are carried and never enforced. They are safe precisely because they constrain nothing — default is accepted for that reason, so a schema emitted by a zod .default() is not rejected.

Accepted types

object · array · string · number · integer · boolean · null

Refused keywords

Refused by name, so the error says pattern is not in the subset — a sentence you can act on — rather than "unknown keyword", which reads like an Atlas bug.

GroupKeywords
Stringsformat, pattern, minLength, maxLength
Numbersminimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf
ObjectspatternProperties, propertyNames, minProperties, maxProperties, unevaluatedProperties, dependentRequired, dependentSchemas
ArraysprefixItems, contains, minContains, maxContains, minItems, maxItems, uniqueItems, unevaluatedItems
CompositionallOf, oneOf, not, if, then, else

anyOf is the only composition keyword in the subset. Anything else in that group has to be restructured — usually into an anyOf of fully-specified object branches.

Any keyword that is neither accepted nor listed above is also refused; the two lists are not the same thing, and the error message tells you which case you hit.

Structural rules

Root must be an object schemaroot_not_object

The document's root type must be object.

Every property is requiredoptional_property

Every key in properties must appear in required. Model optionality as a type union including null, and require the property.

Objects must closeadditional_properties

Every object schema must set additionalProperties: false — at every level, not only the root.

Maximum nesting depth is 5depth_limit

Counted from the root.

References must be local and resolvableunresolvable_ref

A $ref must be #/$defs/<name> and must name a def that exists in the same document.

Violation codes

Every refusal carries a code from a closed set, so you can branch on it:

CodeMeaning
root_not_objectThe document is not an object schema at its root.
unsupported_keywordA keyword the subset does not accept.
optional_propertyA property that required does not list.
additional_propertiesAn object that does not forbid additional properties.
depth_limitNesting past 5 levels.
unsupported_typeA type outside the accepted list.
unresolvable_refA $ref that is not a local #/$defs/<name>, or names no such def.
malformed_schemaStructurally not a schema: a non-object node, a missing type, a bad items.

Each violation also carries an RFC 6901 pointer into your schema document ("" for the root), with ~0 and ~1 escaping applied, so a property named a/b cannot forge a pointer segment.

Working within it

Versioning

The identifier atlas-json-schema-subset-v1 is part of the published catalog. If the accepted set changes in a way that would reject a schema this version accepts, it is published under a new identifier — the same rule model identifiers follow. Read capabilities.json_schema_subset from the catalog rather than hard-coding the string.

On this page