Skip to content

fix(anthropic): migrate output_format to output_config.format (GA API) - #21635

Open
ropoctl wants to merge 1 commit into
BerriAI:litellm_oss_stagingfrom
ropoctl:main
Open

fix(anthropic): migrate output_format to output_config.format (GA API)#21635
ropoctl wants to merge 1 commit into
BerriAI:litellm_oss_stagingfrom
ropoctl:main

Conversation

@ropoctl

@ropoctl ropoctl commented Feb 20, 2026

Copy link
Copy Markdown

Anthropic's structured output API has graduated from beta:

  • output_format parameter moved to output_config.format
  • Beta headers (structured-outputs-2025-11-13) no longer required
  • Old beta header + output_format still work during transition period

Changes:

  • map_openai_params: store into output_config.format instead of output_format
  • update_headers: only add beta header for legacy output_format passthrough
  • Cosmetic: auto-formatted some long lines

Ref: https://platform.claude.com/docs/en/build-with-claude/structured-outputs

Relevant issues

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have Added testing in the tests/litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.
  • Branch creation CI run
    Link:

  • CI run for the last commit
    Link:

  • Merge / cherry-pick CI run
    Links:

Type

🆕 New Feature
🐛 Bug Fix
🧹 Refactoring
📖 Documentation
🚄 Infrastructure
✅ Test

Changes

@CLAassistant

CLAassistant commented Feb 20, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@vercel

vercel Bot commented Feb 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Feb 20, 2026 7:44am

Request Review

@greptile-apps

greptile-apps Bot commented Feb 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Migrates Anthropic structured output from the beta API (output_format + structured-outputs-2025-11-13 header) to the GA API (output_config.format, no beta header required), while preserving backward-compatible passthrough of a user-supplied output_format key.

  • map_openai_params: uses setdefault(\"output_config\", {})[\"format\"] so a pre-existing effort key in output_config is preserved, and no output_format key is set.
  • update_headers: beta header is added only when output_format is still present (legacy direct passthrough); GA output_config.format requests go without it.
  • Tests are updated to verify the GA shape and two new tests cover the format+effort coexistence and an end-to-end transform_request check.

Confidence Score: 5/5

Safe to merge — the two-line production change is a straightforward field rename with no side effects, and the updated tests directly verify the new GA shape.

The production diff is minimal: one assignment changes which key is written in optional_params, and one condition narrows when the beta header is injected. Both directions are covered by existing plus new unit tests. The legacy output_format passthrough path is explicitly preserved, so direct callers who bypass map_openai_params are unaffected.

No files require special attention.

Important Files Changed

Filename Overview
litellm/llms/anthropic/chat/transformation.py Two-line change: map_openai_params now writes into output_config.format via setdefault (correctly preserving a pre-existing effort key), and update_headers drops the beta header for GA models while retaining it only for legacy output_format passthrough.
tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py Existing tests updated to assert GA API shape (output_config.format, no beta header); two new tests added covering output_config.format + effort coexistence and end-to-end transform_request output.

Reviews (7): Last reviewed commit: "fix(anthropic): migrate output_format to..." | Re-trigger Greptile

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 file reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread litellm/llms/anthropic/chat/transformation.py Outdated
@greptile-apps

greptile-apps Bot commented Feb 20, 2026

Copy link
Copy Markdown
Contributor
Additional Comments (1)

litellm/llms/anthropic/chat/transformation.py
the test at line 897 in test_anthropic_chat_transformation.py still expects output_format key, but now the code sets output_config.format instead

    # Should use output_config.format (native structured outputs)
    assert "output_config" in optional_params
    assert optional_params["output_config"]["format"]["type"] == "json_schema"

@ropoctl

ropoctl commented Feb 20, 2026

Copy link
Copy Markdown
Author

My apologies, the agent that wrote this ran black on the modified files, so there are unrelated whitespace/formatting changes. I will remove those if needed.

I verified the change with this script

#!/usr/bin/env -S uv run
# /// script
# requires-python = ">=3.11"
# dependencies = [
#   "litellm @ <REDACTED0>",
#   "pydantic",
# ]
# ///
"""Test Anthropic structured output with output_config.format (GA API)."""
import os
import litellm
from pydantic import BaseModel

os.environ["ANTHROPIC_API_KEY"] = "<REDACTED1>"


class ExtractedInfo(BaseModel):
    name: str
    email: str
    plan_interest: str
    demo_requested: bool


response = litellm.completion(
    model="anthropic/claude-sonnet-4-20250514",
    api_base="<REDACTED2>",
    messages=[
        {
            "role": "user",
            "content": "Extract info: John Smith (john@example.com) wants Enterprise plan, demo next Tuesday 2pm.",
        }
    ],
    response_format=ExtractedInfo,
    max_tokens=1024,
)

print("=== Response ===")
print(response.choices[0].message.content)
print(f"\n=== Stop reason: {response.choices[0].finish_reason} ===")

# Validate it parses
parsed = ExtractedInfo.model_validate_json(response.choices[0].message.content)
print(f"\n=== Parsed ===")
print(f"Name: {parsed.name}")
print(f"Email: {parsed.email}")
print(f"Plan: {parsed.plan_interest}")
print(f"Demo: {parsed.demo_requested}")
print("\n✅ Anthropic structured output works!")

@ropoctl

ropoctl commented Feb 20, 2026

Copy link
Copy Markdown
Author

ptal @greptileai

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 files reviewed, 5 comments

Edit Code Review Agent Settings | Greptile

Comment thread litellm/llms/anthropic/chat/transformation.py Outdated
Comment thread litellm/llms/anthropic/chat/transformation.py Outdated
@greptile-apps

greptile-apps Bot commented Feb 20, 2026

Copy link
Copy Markdown
Contributor
Additional Comments (3)

litellm/llms/anthropic/chat/transformation.py
method renamed to _is_claude_opus_4_6 but still called with old name _is_claude_4_6_model

            or AnthropicConfig._is_claude_opus_4_6(model)

litellm/llms/anthropic/chat/transformation.py
method renamed to _is_claude_opus_4_6 but still called with old name _is_claude_4_6_model

        if AnthropicConfig._is_claude_opus_4_6(model):

litellm/llms/anthropic/chat/transformation.py
method renamed to _is_claude_opus_4_6 but still called with old name _is_claude_4_6_model

                if effort == "max" and not self._is_claude_opus_4_6(model):

@ropoctl

ropoctl commented Feb 20, 2026

Copy link
Copy Markdown
Author

ptal @greptileai

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@greptile-apps

greptile-apps Bot commented Feb 20, 2026

Copy link
Copy Markdown
Contributor
Additional Comments (1)

litellm/llms/anthropic/chat/transformation.py
missing opus_4.6 and opus_4_6 (underscore variants with dots). Other parts of the codebase check for these variants (e.g., bedrock/common_utils.py:486, bedrock/chat/converse_transformation.py:1280)

                        "opus-4.6",
                        "opus_4.6",
                        "opus-4-6",
                        "opus_4_6",
                        "sonnet-4.6",

@ropoctl

ropoctl commented Feb 20, 2026

Copy link
Copy Markdown
Author

Additional Comments (1)
litellm/llms/anthropic/chat/transformation.py missing opus_4.6 and opus_4_6 (underscore variants with dots). Other parts of the codebase check for these variants (e.g., bedrock/common_utils.py:486, bedrock/chat/converse_transformation.py:1280)

                        "opus-4.6",
                        "opus_4.6",
                        "opus-4-6",
                        "opus_4_6",
                        "sonnet-4.6",

pr no longer touches this, ptal @greptileai

@ropoctl

ropoctl commented Feb 25, 2026

Copy link
Copy Markdown
Author

@greptileai ptal

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@ropoctl

ropoctl commented Feb 27, 2026

Copy link
Copy Markdown
Author

@ishaan-jaff would you be able to review this, please?

@Arithmomaniac

Copy link
Copy Markdown

@ropoctl know why your checks are failing?

@ropoctl

ropoctl commented Apr 19, 2026

Copy link
Copy Markdown
Author

@ropoctl know why your checks are failing?

it's flakes coming from files I didn't touch at all

@ropoctl

ropoctl commented Jul 10, 2026

Copy link
Copy Markdown
Author

@greptileai ptal

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ropoctl
ropoctl changed the base branch from main to litellm_oss_staging July 10, 2026 21:35
@ropoctl

ropoctl commented Jul 10, 2026

Copy link
Copy Markdown
Author

@greptileai ptal — rebased onto the required litellm_oss_staging base.

@codspeed-hq

codspeed-hq Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing ropoctl:main (53838bd) with main (3d63eda)1

Open in CodSpeed

Footnotes

  1. No successful run was found on litellm_oss_staging (6d796d0) during the generation of this report, so main (3d63eda) was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Anthropic structured outputs are now GA. The beta `output_format` parameter
has moved to `output_config.format`, and beta headers are no longer required.

- Updated map_openai_params to set output_config.format instead of output_format
- Legacy output_format passthrough still triggers the beta header
- Updated and added tests verifying GA API structure and no beta header

Ref: https://platform.claude.com/docs/en/build-with-claude/structured-outputs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ropoctl

ropoctl commented Jul 10, 2026

Copy link
Copy Markdown
Author

@greptileai ptal — updated the newer output_config.format regression test for GA no-beta-header behavior; full Anthropic transformation file passes (305 tests).

@ropoctl

ropoctl commented Jul 12, 2026

Copy link
Copy Markdown
Author

The CI red is because the targeted branch does not have #32643 yet

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