Skip to content

fix: use json.RawMessage for JSONOutputFormatParam.Schema to preserve key ordering#271

Open
xiaolin593 wants to merge 2 commits intoanthropics:mainfrom
xiaolin593:fix/json-output-format-schema-key-ordering
Open

fix: use json.RawMessage for JSONOutputFormatParam.Schema to preserve key ordering#271
xiaolin593 wants to merge 2 commits intoanthropics:mainfrom
xiaolin593:fix/json-output-format-schema-key-ordering

Conversation

@xiaolin593
Copy link
Copy Markdown

The change is to preserve user's input key order in honor of model's chain of thoughts.

The SDK's internal JSON encoder sorts map keys alphabetically for
deterministic output (internal/apijson/encoder.go L359-362). When
Schema is typed as map[string]any, this sorting reorders the JSON
schema keys sent in the response_format parameter. This key reordering
can affect model output, as models may be sensitive to the structural
presentation of the schema even when the schemas are semantically
equivalent.

By changing Schema from map[string]any to json.RawMessage, the
user-provided JSON schema is sent verbatim to the API without any key
reordering, preserving the intended field ordering and ensuring
consistent model behavior.

Reference:

… key ordering

   The SDK's internal JSON encoder sorts map keys alphabetically for
   deterministic output (internal/apijson/encoder.go L359-362). When
   Schema is typed as map[string]any, this sorting reorders the JSON
   schema keys sent in the response_format parameter. This key reordering
   can affect model output, as models may be sensitive to the structural
   presentation of the schema even when the schemas are semantically
   equivalent.

   By changing Schema from map[string]any to json.RawMessage, the
   user-provided JSON schema is sent verbatim to the API without any key
   reordering, preserving the intended field ordering and ensuring
   consistent model behavior.

   Reference: envoyproxy/ai-gateway#1299
Copy link
Copy Markdown
Collaborator

@dtmeadows dtmeadows left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for this @xiaolin593! This fix looks correct to me. We've changed the type of many of these schema-type fields to this type, like here: https://github.com/anthropics/anthropic-sdk-go/blob/main/message.go#L1457-L1458

@dtmeadows
Copy link
Copy Markdown
Collaborator

Or hrmmm.... maybe not. This is a breaking type change.

@dtmeadows dtmeadows self-requested a review February 18, 2026 20:38
@xiaolin593
Copy link
Copy Markdown
Author

It's indeed a breaking type change which I believe it's needed. I merged latest into branch, @dtmeadows can you help kick off CI?

@xiaolin593
Copy link
Copy Markdown
Author

https://platform.claude.com/docs/en/build-with-claude/structured-outputs#property-ordering

Property ordering
When using structured outputs, properties in objects maintain their defined ordering from your schema, with one important caveat: required properties appear first, followed by optional properties.

I think map[string]any plus current SDK's encoding/json sorting behavior together violates above contract.

@dtmeadows
Copy link
Copy Markdown
Collaborator

Hey @xiaolin593, I definitely agree that this is a positive change! I'd also buy the argument that this is arguably a bug fix where a change like this is merited. I do want to triple check though that a breaking change (albeit small) is acceptable here.

@felixfbecker
Copy link
Copy Markdown

I'm supportive of a breaking change but lets make sure we audit and do it across all fields that need it in one so we don't end up having to make multiple breaking changes or create inconsistency (tool use block's Input, tool definition's InputSchema, output_config Schema, tool runner internals, maybe more). @dtmeadows could you own making sure of that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants