Skip to content

Python (anthropic): Migrate structured outputs to GA output_config.format#5884

Open
t-anjan wants to merge 1 commit into
microsoft:mainfrom
t-anjan:fix/anthropic-output-config-ga
Open

Python (anthropic): Migrate structured outputs to GA output_config.format#5884
t-anjan wants to merge 1 commit into
microsoft:mainfrom
t-anjan:fix/anthropic-output-config-ga

Conversation

@t-anjan
Copy link
Copy Markdown
Contributor

@t-anjan t-anjan commented May 15, 2026

Summary

RawAnthropicClient._prepare_options forwards response_format as the deprecated beta parameter output_format={"type": "json_schema", "schema": {...}} plus the beta flag structured-outputs-2025-11-13. When the same request also includes tools, Claude emits concatenated / malformed JSON — e.g. three copies of the schema's empty default like {"matches":[]}{"matches":[]}{"matches":[]} — instead of populating the schema. Anthropic's GA shape — output_config={"format": {"type":"json_schema","schema":{...}}} — works correctly with tools.

This PR migrates the provider to the GA shape.

Verified empirically

Observed on a structured-output workload that combined response_format (a Pydantic model) with a tool (run_shell) against claude-sonnet-4-6: the deprecated path produced the malformed concatenated output above, the GA path did not.

Why no beta flag is needed on the GA path

AsyncMessages.create() on beta.messages (which is what MAF dispatches through — _chat_client.py:541, 550) accepts output_config as a top-level parameter and does not require structured-outputs-2025-11-13. Only beta.messages.parse(...) auto-injects a structured-outputs beta flag (and even then it injects structured-outputs-2025-12-15, not the 2025-11-13 flag MAF was sending). So create() with output_config is genuinely flag-free.

Verified against installed anthropic==0.80.0 — both BetaOutputConfigParam and OutputConfigParam expose exactly {format: JSONOutputFormatParam, effort: Optional[Literal["low","medium","high","max"]]}.

Changes

  • python/packages/anthropic/agent_framework_anthropic/_chat_client.py:
    • Move response_format into run_options["output_config"]["format"] (GA shape) and stop adding the structured-outputs-2025-11-13 beta flag.
    • Merge the format into any caller-supplied output_config so e.g. output_config["effort"] (adaptive-thinking effort level) survives the transformation.
    • Drop the now-unused STRUCTURED_OUTPUTS_BETA_FLAG constant (private to this module — no external callers).
    • _prepare_response_format keeps the same {"type": "json_schema", "schema": ...} return shape; the docstring is updated to point at the GA target.

Test plan

uv run pytest packages/anthropic/tests → 130 passed.

New tests:

  • test_prepare_options_uses_output_config_for_response_format — the GA output_config.format shape is emitted, the deprecated output_format key is not, and structured-outputs-2025-11-13 is not added to betas.
  • test_prepare_options_preserves_caller_supplied_output_config_effort — a caller-supplied output_config["effort"] survives the merge.
  • test_prepare_options_no_response_format_omits_output_config — no output_config is added implicitly when response_format is absent.

…ormat`

Bug
---
`RawAnthropicClient._prepare_options` forwards `response_format` as the
**deprecated** beta parameter `output_format={"type": "json_schema", "schema":
{...}}` plus the beta flag `structured-outputs-2025-11-13`. When the same
request also includes `tools`, Claude emits concatenated / malformed JSON —
e.g. three copies of the schema's empty default like
`{"matches":[]}{"matches":[]}{"matches":[]}` — instead of populating the
schema. Anthropic's GA shape — `output_config={"format": {"type":
"json_schema", "schema": {...}}}` — works correctly with tools.

Verified empirically on `agent-framework-anthropic` against
`claude-sonnet-4-6` for a structured-output workload that combined
`response_format` with a tool (`run_shell`); the deprecated path produced
the malformed concatenated output, the GA path did not.

Changes
-------
- Move `response_format` into `run_options["output_config"]["format"]` and
  stop adding the `structured-outputs-2025-11-13` beta flag (the GA path
  doesn't need it).
- Merge the format into any caller-supplied `output_config` so e.g.
  `output_config["effort"]` (adaptive-thinking effort level) survives the
  transformation.
- Drop the now-unused `STRUCTURED_OUTPUTS_BETA_FLAG` constant (private to
  this module — no external callers).
- `_prepare_response_format` keeps the same `{"type": "json_schema",
  "schema": ...}` return shape; the docstring is updated to point at the
  GA target.

Test plan
---------
- `uv run pytest packages/anthropic/tests` → 130 passed.
- New tests:
  - `test_prepare_options_uses_output_config_for_response_format` — the
    GA `output_config.format` shape is emitted, the deprecated
    `output_format` key is not, and the `structured-outputs-2025-11-13`
    beta flag is not added.
  - `test_prepare_options_preserves_caller_supplied_output_config_effort`
    — a caller-supplied `output_config["effort"]` survives the merge.
  - `test_prepare_options_no_response_format_omits_output_config` — no
    `output_config` is added implicitly when `response_format` is absent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 15, 2026 03:49
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Migrates the Python Anthropic provider’s structured-output forwarding from the deprecated beta output_format + structured-outputs-2025-11-13 flag to Anthropic’s GA output_config.format shape, addressing malformed/concatenated JSON responses when structured outputs are combined with tools.

Changes:

  • Update _prepare_options to place response_format under output_config["format"] and stop injecting the deprecated structured-outputs beta flag.
  • Merge GA format into any caller-supplied output_config so other settings (e.g., effort) are preserved.
  • Add unit tests validating the new GA shape, the absence of deprecated parameters/flags, and correct merge behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
python/packages/anthropic/agent_framework_anthropic/_chat_client.py Switch structured outputs to GA output_config.format, remove deprecated beta-flag path, and preserve caller output_config fields via merge.
python/packages/anthropic/tests/test_anthropic_client.py Add tests ensuring GA output_config.format is emitted, deprecated output_format/beta flag are not used, and caller output_config.effort is preserved.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants