feat(schema): apply property ordering at wire encoding for non-Google providers#600
Merged
mikehostetler merged 2 commits intoagentjido:mainfrom Apr 13, 2026
Merged
Conversation
… providers Consume propertyOrdering at the encoding boundary by converting properties maps to Jason.OrderedObject before Jason.encode!, then strip the annotation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0f10403 to
cccbbb8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
PR #599 added
propertyOrderingannotations to generated JSON schemas, which gave us a solid foundation — Google/Gemini reads the annotation natively, and the ordering metadata flows through the pipeline correctly. However, for OpenAI and most other providers, what actually matters is the byte order of keys in the"properties"JSON object on the wire. They don't readpropertyOrderingas an annotation.Since Elixir maps are unordered and
Jason.encode!produces arbitrary key order, the annotation alone was decorative for non-Google providers. This PR builds on #599 by consumingpropertyOrderingat the encoding boundary — "late escaping" the ordering into the actual JSON structure right before it hits the wire.How it works:
propertyOrderingflows through the pipeline as metadata (from feat(schema): preserve property ordering in generated JSON schema #599)Jason.encode!,Schema.apply_property_ordering/1walks the body"properties"and"propertyOrdering"gets its properties converted to aJason.OrderedObjectwith keys in the declared orderpropertyOrderingannotation is stripped (it's been structurally encoded)Type of Change
Breaking Changes
None. Schemas that previously included
propertyOrderingin the wire JSON for non-Google providers will no longer include it (the ordering is now expressed structurally instead). Google providers are unchanged.Testing
mix test) — 2812 tests, 0 failuresmix quality)New tests:
apply_property_ordering/1in schema_test.exs (flat, nested, recursive, pass-through, wire encoding, list traversal)property_ordering_wire_test.exs) verifying structured output actual JSON key order for:encode_body_from_mappath (covers xai, groq, openrouter, etc.)Bug fix:
normalize_parametersinresponses_api.exwas rebuilding the schema map from scratch, droppingpropertyOrderingbefore it could reach the encoding step.Checklist
CHANGELOG.md(it is auto-generated by git_ops)Related Issues
Builds on #599