Skip to content

fix(anthropic-adapter): strip output_config for non-Anthropic backends - #22727

Closed
cfdude wants to merge 6 commits into
BerriAI:mainfrom
cfdude:fix/strip-output-config-for-non-anthropic-models
Closed

fix(anthropic-adapter): strip output_config for non-Anthropic backends#22727
cfdude wants to merge 6 commits into
BerriAI:mainfrom
cfdude:fix/strip-output-config-for-non-anthropic-models

Conversation

@cfdude

@cfdude cfdude commented Mar 4, 2026

Copy link
Copy Markdown

Summary

  • output_config is an Anthropic Claude-specific parameter with no equivalent in other model providers
  • When routing via the experimental pass-through adapter to non-Anthropic backends (e.g. Amazon Nova Pro on Bedrock, Llama, Mistral), the parameter was forwarded verbatim causing HTTP 400 extraneous key [output_config] is not permitted errors
  • Strip output_config from the request when the target provider is not an Anthropic Claude model (direct Anthropic API or Bedrock-hosted Anthropic Claude)
  • thinking is intentionally not stripped — some non-Anthropic models (e.g. Qwen) support reasoning natively and the adapter already handles translation for those

Test plan

  • Tested locally: Claude Code routing to bedrock/converse/us.amazon.nova-pro-v1:0 via LiteLLM proxy — previously failed with extraneous key [output_config], now succeeds
  • output_config passthrough to native Anthropic Claude models is unaffected
  • Unit tests to be added covering strip/no-strip behavior per provider

…messages adapter

When routing non-Anthropic models (e.g. Amazon Bedrock Nova Pro) through
the Anthropic-compatible /v1/messages endpoint, `_prepare_completion_kwargs`
was forwarding the client-supplied max_tokens directly to the underlying
provider without checking the model's actual output token limit.

This caused hard failures for models like Amazon Nova Pro (10,000 token
limit) when clients such as Claude Code send large max_tokens values that
are valid for other providers (e.g. 64,000 for Anthropic Claude).

Fix: look up max_output_tokens via litellm.get_model_info() before
building the request_data dict and cap accordingly. The lookup uses
custom_llm_provider from extra_kwargs (already resolved by the outer
anthropic_messages_handler via get_llm_provider) with a fallback to
inferring the provider from the model string.

Tested with bedrock/converse/us.amazon.nova-pro-v1:0 routed via LiteLLM
proxy: requests sending max_tokens=16000 are now silently capped to 10000
and succeed instead of returning HTTP 400.
- Simplify two-try-block approach into a single try block: if no explicit
  provider in extra_kwargs, infer it via get_llm_provider() in the same
  path rather than a separate fallback block. This eliminates the
  misleading _capped/_lookup_succeeded flag entirely.
- Use explicit `is not None` check instead of truthy check on
  max_output_tokens, consistent with get_modified_max_tokens pattern
  in token_counter.py and correct for hypothetical zero-limit models.
- Add unit tests covering all capping scenarios:
  - max_tokens capped when it exceeds the model limit
  - max_tokens unchanged when within the limit
  - max_tokens unchanged when equal to the limit
  - provider inferred from model string when absent from extra_kwargs
  - resilient when get_model_info raises
  - no cap when max_output_tokens key is missing from model_info
  - no cap when max_output_tokens is explicitly None
  - explicit provider is used without calling get_llm_provider
Emit a debug log when the adapter silently reduces max_tokens to the
model's output limit, consistent with the get_modified_max_tokens pattern
in token_counter.py. Aids debugging when users observe shorter completions
than expected.
output_config is an Anthropic Claude-specific parameter that has no
equivalent in other model providers. When routing through the
experimental pass-through adapter to non-Anthropic backends (e.g.
Amazon Nova Pro on Bedrock, Llama, Mistral), the parameter is forwarded
verbatim and causes HTTP 400 "extraneous key" errors.

Strip output_config from the request when the target provider is not
an Anthropic Claude model. The thinking parameter is intentionally
excluded from stripping because some non-Anthropic models (e.g. Qwen)
support reasoning/thinking natively and the adapter already handles
translation for those cases.
@vercel

vercel Bot commented Mar 4, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
litellm Error Error Mar 4, 2026 1:38am

Request Review

@greptile-apps

greptile-apps Bot commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds two defensive features to the Anthropic experimental pass-through adapter: (1) capping max_tokens against the target model's known output token limit to prevent HTTP 400 errors from providers with stricter limits, and (2) stripping the Anthropic-specific output_config parameter when routing to non-Anthropic backends. Both changes use litellm.get_model_info() for model lookups, which aligns well with the project's convention of deriving capabilities from the model registry.

  • max_tokens capping (lines 124-154): Gracefully caps max_tokens using model info, with a broad except Exception: pass fallback so unknown models aren't blocked.
  • output_config stripping (lines 198-216): Strips Anthropic-only params for non-Anthropic targets. The _is_anthropic_claude detection covers direct Anthropic API and Bedrock-hosted Claude; Vertex AI coverage gap was flagged in a prior review thread.
  • Test file: Good coverage for both features, but the _call helper has a Python falsy-dict bug that prevents the provider-inference fallback test from actually exercising the intended code path.

Confidence Score: 4/5

  • This PR is safe to merge — it fixes a real HTTP 400 regression for non-Anthropic backends with minimal blast radius
  • The handler changes are well-scoped and defensively coded (graceful fallback on errors). The main concern is a test bug where the provider-inference fallback path isn't actually exercised, but this doesn't affect production behavior.
  • The test file needs the _call helper fix to properly validate the fallback inference path

Important Files Changed

Filename Overview
litellm/llms/anthropic/experimental_pass_through/adapters/handler.py Adds max_tokens capping against model limits and strips output_config for non-Anthropic backends. Logic is sound for covered providers; Vertex AI gap already flagged in prior review.
tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_anthropic_experimental_pass_through_adapters_handler.py New unit tests for max_tokens capping and output_config stripping. The _call helper has a falsy-dict bug that prevents the provider-inference fallback test from exercising the intended code path.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["_prepare_completion_kwargs()"] --> B["Cap max_tokens via get_model_info()"]
    B --> C["Translate request to OpenAI format"]
    C --> D{"Is target Anthropic Claude?"}
    D -->|"provider == 'anthropic'"| E["Keep output_config"]
    D -->|"provider == 'bedrock' && model contains 'anthropic.claude'"| E
    D -->|"Non-Anthropic backend"| F["Strip output_config from excluded_keys"]
    E --> G["Merge extra_kwargs into completion_kwargs"]
    F --> G
    G --> H["Route to litellm.completion()"]
Loading

Last reviewed commit: 3647cac

Tests cover strip/pass-through behavior for output_config based on
target provider: stripped for non-Anthropic backends (Bedrock Nova Pro,
OpenAI, etc.), preserved for Anthropic direct and Bedrock-hosted Claude.
Comment on lines +205 to +212
_anthropic_only_params = {"output_config"}
_target_provider = (extra_kwargs or {}).get("custom_llm_provider", "")
_is_anthropic_claude = _target_provider in (
"anthropic",
) or (
_target_provider == "bedrock"
and "anthropic.claude" in completion_kwargs.get("model", "")
)

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.

Missing Vertex AI Claude detection

The _is_anthropic_claude check only covers the "anthropic" and "bedrock" providers, but Vertex AI also hosts Anthropic Claude models (e.g. vertex_ai/claude-sonnet-4). For those, custom_llm_provider would be "vertex_ai" and the model string would contain "claude" but not "anthropic.claude". This means output_config would be incorrectly stripped for Vertex AI Claude models.

There is already an existing helper LiteLLMAnthropicMessagesAdapter.is_anthropic_claude_model() in the adjacent transformation.py (line 653) that correctly handles all three providers by checking for "anthropic" or "claude" in the model string. Consider reusing that helper, or extending this check to cover Vertex AI:

Suggested change
_anthropic_only_params = {"output_config"}
_target_provider = (extra_kwargs or {}).get("custom_llm_provider", "")
_is_anthropic_claude = _target_provider in (
"anthropic",
) or (
_target_provider == "bedrock"
and "anthropic.claude" in completion_kwargs.get("model", "")
)
_anthropic_only_params = {"output_config"}
_target_provider = (extra_kwargs or {}).get("custom_llm_provider", "")
_is_anthropic_claude = _target_provider in (
"anthropic",
) or (
_target_provider == "bedrock"
and "anthropic.claude" in completion_kwargs.get("model", "")
) or (
_target_provider == "vertex_ai"
and "claude" in completion_kwargs.get("model", "").lower()
)

Comment on lines +1 to +5
"""
Unit tests for LiteLLMMessagesToCompletionTransformationHandler._prepare_completion_kwargs,
specifically the max_tokens capping logic added to prevent HTTP 400 errors from providers
with strict output token limits (e.g. Amazon Nova Pro: 10,000 tokens).
"""

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.

Missing tests for output_config stripping

The PR title and description focus on stripping output_config for non-Anthropic backends, but the test file only covers the max_tokens capping logic. The PR description itself notes "Unit tests to be added covering strip/no-strip behavior per provider" as unchecked. Please add tests verifying:

  1. output_config is stripped when routing to non-Anthropic backends (e.g. Bedrock Nova Pro)
  2. output_config is preserved when routing to Anthropic Claude (direct API)
  3. output_config is preserved when routing to Bedrock-hosted Anthropic Claude
  4. output_config is preserved when routing to Vertex AI Claude

Context Used: Rule from dashboard - What: Ensure that any PR claiming to fix an issue includes evidence that the issue is resolved, such... (source)

max_tokens=max_tokens,
messages=MESSAGES,
model=MODEL,
extra_kwargs=extra_kwargs or {"custom_llm_provider": PROVIDER},

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.

Helper masks empty dict argument

extra_kwargs or {default} treats {} as falsy in Python, so passing extra_kwargs={} silently substitutes the default dict that includes the provider. This means test_fallback_infers_provider_when_not_in_extra_kwargs (line 62) never exercises the fallback inference path — get_llm_provider is never invoked because the provider key is always present. The test passes only because get_model_info is mocked to return the capped value regardless of how the provider was resolved.

Use an explicit None check instead:

Suggested change
extra_kwargs=extra_kwargs or {"custom_llm_provider": PROVIDER},
extra_kwargs=extra_kwargs if extra_kwargs is not None else {"custom_llm_provider": PROVIDER},

mateo-berri pushed a commit that referenced this pull request Apr 25, 2026
…ept it

Resolves the silent strip of Anthropic Structured Outputs across the
Vertex AI Claude transformation paths and the Anthropic-adapter
re-merge. Consolidates and supersedes four stalled community PRs
addressing overlapping aspects of the same root bug:

- #23475 (Vertex AI Claude blanket-strip removal)
- #23396 (Vertex AI Claude conditional passthrough)
- #23706 (Anthropic adapter exclude output_config from non-Anthropic
  backends)
- #22727 (Anthropic adapter strip output_config for non-Anthropic
  backends)

Closes / addresses: #23380 (Vertex AI Claude output_config drop),
related: #26423, #25079, #24549, #25971, #25957, #26163, #24856.

What was broken
---------------
* Vertex AI Claude paths called ``data.pop("output_config")`` and
  ``data.pop("output_format")`` unconditionally even when Vertex
  accepted those fields. Callers asking for Structured Outputs got a
  200 with prose and never knew the schema constraints had been
  silently dropped (often masked for months by permissive fallback
  parsers).
* The ``/v1/messages`` -> ``/chat/completions`` adapter
  (``LiteLLMMessagesToCompletionTransformationHandler``) re-merged the
  raw Anthropic-shaped ``output_config`` into ``completion_kwargs``
  AFTER the translator already mapped its meaningful parts to
  ``response_format`` / ``reasoning_effort``. Non-Anthropic backends
  (Azure OpenAI, Fireworks, Bedrock Nova, etc.) then 400'd with
  "Extra inputs are not permitted".

Approach
--------
Vertex AI Claude (chat-completion + experimental_pass_through paths):
  Replace the unconditional pop with a sanitizer
  ``_sanitize_vertex_anthropic_output_params`` that strips only the
  Vertex-unsupported keys (today: ``effort``) from ``output_config``
  while forwarding ``format`` and the legacy top-level
  ``output_format``. Defensive: non-dict ``output_config`` values are
  dropped to avoid sending malformed payloads downstream.
  Greptile P1 from PR #23396 addressed: when ``output_config`` carries
  both ``format`` and ``effort``, the prior conditional pass-through
  forwarded ``effort`` and reproduced the 400. The new helper filters
  per-key.

Anthropic ``/v1/messages`` adapter:
  Add ``output_config`` to a named module-level constant
  ``ANTHROPIC_ONLY_REQUEST_KEYS`` and wire it into ``excluded_keys`` so
  the post-translation re-merge skips re-adding the raw key. This
  fixes the 400 on non-Anthropic backends and avoids the conflicting
  duplicate (``response_format`` + raw ``output_config``) on
  Anthropic-family backends.
  Greptile P2 from PR #23706 addressed: the constant gives reviewers
  one grep target instead of an inline literal that silently grows.
  Greptile P2 from PR #22727 addressed: ``extra_kwargs or {}`` is
  replaced with explicit ``is None`` checks so empty-dict callers no
  longer skip the fallback path.

Tests
-----
* tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/
  test_vertex_ai_partner_models_anthropic_transformation.py:
  - 5 new/updated cases plus a direct unit test for
    ``_sanitize_vertex_anthropic_output_params``.
  - Updated ``test_vertex_ai_claude_sonnet_4_5_structured_output_fix``
    so its mock-injected ``output_format`` is asserted to FLOW THROUGH
    (the original test asserted the now-buggy strip behavior).
* tests/test_litellm/llms/anthropic/experimental_pass_through/
  adapters/test_handler_output_config_passthrough.py (new):
  - Constant export sanity, output_config strip with ``effort`` only,
    output_config strip with ``format`` only, regression guard that
    unrelated extras still flow, explicit-empty-dict path, and the
    ``extra_kwargs=None`` no-crash path.

Test-quality fixes incorporated from Greptile review on the
superseded PRs:
* No ``inspect.getsource`` source-text assertions (PR #24114 / #23475).
* ``sys.path`` insertion is anchored to ``__file__`` (PR #23706).
* Assertion messages are positional, not tuple (PR #24114-class bug).
* No ``or {}`` masking explicit empty dicts in helper signatures
  (PR #22727).

Verified locally: 26/26 pass with this commit. The new tests
fail (or fail to import) on ``main`` without it.

Out of scope
------------
* The ``max_tokens`` capping logic from PR #22727 — independent
  concern, deserves its own PR with a focused test plan.
* Architectural rework of the ``excluded_keys`` mechanism (Greptile
  P2 on PR #23706 noted point-fix growth). The named constant gives
  maintainers a clear place to extend; a registry-based approach
  would be a follow-up.

Co-Authored-By: netbrah <netbrah>
Co-Authored-By: s-zx <s-zx>
Co-Authored-By: invoicepulse <invoicepulse>
Co-Authored-By: cfdude <cfdude>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
mateo-berri added a commit that referenced this pull request Apr 25, 2026
…h-consolidated

fix(adapters,vertex): pass output_config through to backends that accept it (closes #23380, supersedes #23475/#23396/#23706/#22727)
yugborana pushed a commit to yugborana/litellm that referenced this pull request Jun 2, 2026
…ept it

Resolves the silent strip of Anthropic Structured Outputs across the
Vertex AI Claude transformation paths and the Anthropic-adapter
re-merge. Consolidates and supersedes four stalled community PRs
addressing overlapping aspects of the same root bug:

- BerriAI#23475 (Vertex AI Claude blanket-strip removal)
- BerriAI#23396 (Vertex AI Claude conditional passthrough)
- BerriAI#23706 (Anthropic adapter exclude output_config from non-Anthropic
  backends)
- BerriAI#22727 (Anthropic adapter strip output_config for non-Anthropic
  backends)

Closes / addresses: BerriAI#23380 (Vertex AI Claude output_config drop),
related: BerriAI#26423, BerriAI#25079, BerriAI#24549, BerriAI#25971, BerriAI#25957, BerriAI#26163, BerriAI#24856.

What was broken
---------------
* Vertex AI Claude paths called ``data.pop("output_config")`` and
  ``data.pop("output_format")`` unconditionally even when Vertex
  accepted those fields. Callers asking for Structured Outputs got a
  200 with prose and never knew the schema constraints had been
  silently dropped (often masked for months by permissive fallback
  parsers).
* The ``/v1/messages`` -> ``/chat/completions`` adapter
  (``LiteLLMMessagesToCompletionTransformationHandler``) re-merged the
  raw Anthropic-shaped ``output_config`` into ``completion_kwargs``
  AFTER the translator already mapped its meaningful parts to
  ``response_format`` / ``reasoning_effort``. Non-Anthropic backends
  (Azure OpenAI, Fireworks, Bedrock Nova, etc.) then 400'd with
  "Extra inputs are not permitted".

Approach
--------
Vertex AI Claude (chat-completion + experimental_pass_through paths):
  Replace the unconditional pop with a sanitizer
  ``_sanitize_vertex_anthropic_output_params`` that strips only the
  Vertex-unsupported keys (today: ``effort``) from ``output_config``
  while forwarding ``format`` and the legacy top-level
  ``output_format``. Defensive: non-dict ``output_config`` values are
  dropped to avoid sending malformed payloads downstream.
  Greptile P1 from PR BerriAI#23396 addressed: when ``output_config`` carries
  both ``format`` and ``effort``, the prior conditional pass-through
  forwarded ``effort`` and reproduced the 400. The new helper filters
  per-key.

Anthropic ``/v1/messages`` adapter:
  Add ``output_config`` to a named module-level constant
  ``ANTHROPIC_ONLY_REQUEST_KEYS`` and wire it into ``excluded_keys`` so
  the post-translation re-merge skips re-adding the raw key. This
  fixes the 400 on non-Anthropic backends and avoids the conflicting
  duplicate (``response_format`` + raw ``output_config``) on
  Anthropic-family backends.
  Greptile P2 from PR BerriAI#23706 addressed: the constant gives reviewers
  one grep target instead of an inline literal that silently grows.
  Greptile P2 from PR BerriAI#22727 addressed: ``extra_kwargs or {}`` is
  replaced with explicit ``is None`` checks so empty-dict callers no
  longer skip the fallback path.

Tests
-----
* tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/
  test_vertex_ai_partner_models_anthropic_transformation.py:
  - 5 new/updated cases plus a direct unit test for
    ``_sanitize_vertex_anthropic_output_params``.
  - Updated ``test_vertex_ai_claude_sonnet_4_5_structured_output_fix``
    so its mock-injected ``output_format`` is asserted to FLOW THROUGH
    (the original test asserted the now-buggy strip behavior).
* tests/test_litellm/llms/anthropic/experimental_pass_through/
  adapters/test_handler_output_config_passthrough.py (new):
  - Constant export sanity, output_config strip with ``effort`` only,
    output_config strip with ``format`` only, regression guard that
    unrelated extras still flow, explicit-empty-dict path, and the
    ``extra_kwargs=None`` no-crash path.

Test-quality fixes incorporated from Greptile review on the
superseded PRs:
* No ``inspect.getsource`` source-text assertions (PR BerriAI#24114 / BerriAI#23475).
* ``sys.path`` insertion is anchored to ``__file__`` (PR BerriAI#23706).
* Assertion messages are positional, not tuple (PR BerriAI#24114-class bug).
* No ``or {}`` masking explicit empty dicts in helper signatures
  (PR BerriAI#22727).

Verified locally: 26/26 pass with this commit. The new tests
fail (or fail to import) on ``main`` without it.

Out of scope
------------
* The ``max_tokens`` capping logic from PR BerriAI#22727 — independent
  concern, deserves its own PR with a focused test plan.
* Architectural rework of the ``excluded_keys`` mechanism (Greptile
  P2 on PR BerriAI#23706 noted point-fix growth). The named constant gives
  maintainers a clear place to extend; a registry-based approach
  would be a follow-up.

Co-Authored-By: netbrah <netbrah>
Co-Authored-By: s-zx <s-zx>
Co-Authored-By: invoicepulse <invoicepulse>
Co-Authored-By: cfdude <cfdude>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@github-actions github-actions Bot added the stale label Jun 3, 2026
@github-actions github-actions Bot closed this Jun 11, 2026
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…ept it

Resolves the silent strip of Anthropic Structured Outputs across the
Vertex AI Claude transformation paths and the Anthropic-adapter
re-merge. Consolidates and supersedes four stalled community PRs
addressing overlapping aspects of the same root bug:

- BerriAI#23475 (Vertex AI Claude blanket-strip removal)
- BerriAI#23396 (Vertex AI Claude conditional passthrough)
- BerriAI#23706 (Anthropic adapter exclude output_config from non-Anthropic
  backends)
- BerriAI#22727 (Anthropic adapter strip output_config for non-Anthropic
  backends)

Closes / addresses: BerriAI#23380 (Vertex AI Claude output_config drop),
related: BerriAI#26423, BerriAI#25079, BerriAI#24549, BerriAI#25971, BerriAI#25957, BerriAI#26163, BerriAI#24856.

What was broken
---------------
* Vertex AI Claude paths called ``data.pop("output_config")`` and
  ``data.pop("output_format")`` unconditionally even when Vertex
  accepted those fields. Callers asking for Structured Outputs got a
  200 with prose and never knew the schema constraints had been
  silently dropped (often masked for months by permissive fallback
  parsers).
* The ``/v1/messages`` -> ``/chat/completions`` adapter
  (``LiteLLMMessagesToCompletionTransformationHandler``) re-merged the
  raw Anthropic-shaped ``output_config`` into ``completion_kwargs``
  AFTER the translator already mapped its meaningful parts to
  ``response_format`` / ``reasoning_effort``. Non-Anthropic backends
  (Azure OpenAI, Fireworks, Bedrock Nova, etc.) then 400'd with
  "Extra inputs are not permitted".

Approach
--------
Vertex AI Claude (chat-completion + experimental_pass_through paths):
  Replace the unconditional pop with a sanitizer
  ``_sanitize_vertex_anthropic_output_params`` that strips only the
  Vertex-unsupported keys (today: ``effort``) from ``output_config``
  while forwarding ``format`` and the legacy top-level
  ``output_format``. Defensive: non-dict ``output_config`` values are
  dropped to avoid sending malformed payloads downstream.
  Greptile P1 from PR BerriAI#23396 addressed: when ``output_config`` carries
  both ``format`` and ``effort``, the prior conditional pass-through
  forwarded ``effort`` and reproduced the 400. The new helper filters
  per-key.

Anthropic ``/v1/messages`` adapter:
  Add ``output_config`` to a named module-level constant
  ``ANTHROPIC_ONLY_REQUEST_KEYS`` and wire it into ``excluded_keys`` so
  the post-translation re-merge skips re-adding the raw key. This
  fixes the 400 on non-Anthropic backends and avoids the conflicting
  duplicate (``response_format`` + raw ``output_config``) on
  Anthropic-family backends.
  Greptile P2 from PR BerriAI#23706 addressed: the constant gives reviewers
  one grep target instead of an inline literal that silently grows.
  Greptile P2 from PR BerriAI#22727 addressed: ``extra_kwargs or {}`` is
  replaced with explicit ``is None`` checks so empty-dict callers no
  longer skip the fallback path.

Tests
-----
* tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/
  test_vertex_ai_partner_models_anthropic_transformation.py:
  - 5 new/updated cases plus a direct unit test for
    ``_sanitize_vertex_anthropic_output_params``.
  - Updated ``test_vertex_ai_claude_sonnet_4_5_structured_output_fix``
    so its mock-injected ``output_format`` is asserted to FLOW THROUGH
    (the original test asserted the now-buggy strip behavior).
* tests/test_litellm/llms/anthropic/experimental_pass_through/
  adapters/test_handler_output_config_passthrough.py (new):
  - Constant export sanity, output_config strip with ``effort`` only,
    output_config strip with ``format`` only, regression guard that
    unrelated extras still flow, explicit-empty-dict path, and the
    ``extra_kwargs=None`` no-crash path.

Test-quality fixes incorporated from Greptile review on the
superseded PRs:
* No ``inspect.getsource`` source-text assertions (PR BerriAI#24114 / BerriAI#23475).
* ``sys.path`` insertion is anchored to ``__file__`` (PR BerriAI#23706).
* Assertion messages are positional, not tuple (PR BerriAI#24114-class bug).
* No ``or {}`` masking explicit empty dicts in helper signatures
  (PR BerriAI#22727).

Verified locally: 26/26 pass with this commit. The new tests
fail (or fail to import) on ``main`` without it.

Out of scope
------------
* The ``max_tokens`` capping logic from PR BerriAI#22727 — independent
  concern, deserves its own PR with a focused test plan.
* Architectural rework of the ``excluded_keys`` mechanism (Greptile
  P2 on PR BerriAI#23706 noted point-fix growth). The named constant gives
  maintainers a clear place to extend; a registry-based approach
  would be a follow-up.

Co-Authored-By: netbrah <netbrah>
Co-Authored-By: s-zx <s-zx>
Co-Authored-By: invoicepulse <invoicepulse>
Co-Authored-By: cfdude <cfdude>
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…sthrough-consolidated

fix(adapters,vertex): pass output_config through to backends that accept it (closes BerriAI#23380, supersedes BerriAI#23475/BerriAI#23396/BerriAI#23706/BerriAI#22727)
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.

1 participant