Skip to content

feat(schema): apply property ordering at wire encoding for non-Google providers#600

Merged
mikehostetler merged 2 commits intoagentjido:mainfrom
mhsdef:feat/property-ordering-wire-encode
Apr 13, 2026
Merged

feat(schema): apply property ordering at wire encoding for non-Google providers#600
mikehostetler merged 2 commits intoagentjido:mainfrom
mhsdef:feat/property-ordering-wire-encode

Conversation

@mhsdef
Copy link
Copy Markdown
Contributor

@mhsdef mhsdef commented Apr 12, 2026

Description

PR #599 added propertyOrdering annotations 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 read propertyOrdering as 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 consuming propertyOrdering at the encoding boundary — "late escaping" the ordering into the actual JSON structure right before it hits the wire.

How it works:

  1. propertyOrdering flows through the pipeline as metadata (from feat(schema): preserve property ordering in generated JSON schema #599)
  2. Right before Jason.encode!, Schema.apply_property_ordering/1 walks the body
  3. Any map with both "properties" and "propertyOrdering" gets its properties converted to a Jason.OrderedObject with keys in the declared order
  4. The propertyOrdering annotation is stripped (it's been structurally encoded)
  5. Google/Vertex providers skip this — they read the annotation natively

Type of Change

  • Bug fix (non-breaking change fixing an issue)
  • New feature (non-breaking change adding functionality)
  • Breaking change (fix or feature causing existing functionality to change)
  • Documentation update

Breaking Changes

None. Schemas that previously included propertyOrdering in the wire JSON for non-Google providers will no longer include it (the ordering is now expressed structurally instead). Google providers are unchanged.

Testing

  • Tests pass (mix test) — 2812 tests, 0 failures
  • Quality checks pass (mix quality)

New tests:

  • Unit tests for apply_property_ordering/1 in schema_test.exs (flat, nested, recursive, pass-through, wire encoding, list traversal)
  • Wire-order integration tests (property_ordering_wire_test.exs) verifying structured output actual JSON key order for:
    • OpenAI Responses API
    • OpenAI Chat API
    • Anthropic
    • Default encode_body_from_map path (covers xai, groq, openrouter, etc.)
    • Google annotation retention

Bug fix: normalize_parameters in responses_api.ex was rebuilding the schema map from scratch, dropping propertyOrdering before it could reach the encoding step.

Checklist

  • My code follows the project's style guidelines
  • I have updated the documentation accordingly
  • I have added tests that prove my fix/feature works
  • All new and existing tests pass
  • My commits follow conventional commit format
  • I have NOT edited CHANGELOG.md (it is auto-generated by git_ops)

Related Issues

Builds on #599

… 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>
@mhsdef mhsdef force-pushed the feat/property-ordering-wire-encode branch from 0f10403 to cccbbb8 Compare April 12, 2026 23:49
@mikehostetler mikehostetler added the needs_work Changes requested before merge label Apr 13, 2026
@mikehostetler mikehostetler added ready_to_merge and removed needs_work Changes requested before merge labels Apr 13, 2026
@mikehostetler mikehostetler merged commit 3608711 into agentjido:main Apr 13, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants