Repository navigation
fix(anthropic): forward safeguards and anthropic-beta unchanged on native /v1/messages - #42152
Conversation
…tive /v1/messages Native Anthropic Messages requests derived their allowlist from AnthropicMessagesRequestOptionalParams, which lacked safeguards, and the shared beta-header filter dropped betas unknown to the provider mapping even when the upstream is api.anthropic.com itself. Claude Code auto mode then saw no safeguard_results and fell back to billed classifier calls Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
|
|
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…treaming chunks Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
@greptileai please re-review b59028d: safeguards now stripped on the adapter path, streaming chunk types carry safeguard_results, test docstrings removed |
…nthropic sends
Driving a real Claude Code 2.1.278 through the proxy, and a direct call to
api.anthropic.com, both show these two fields are JSON arrays on the wire rather
than objects. The request carries safeguards as
[{"type": "dangerous_tool_use", "classifier_context": {...}}] under beta
dangerous-tool-use-2026-09-03, and the 200 comes back with safeguard_results as
[{"type": "dangerous_tool_use", "status": {"type": "available", "tool_uses": {...}}}].
No runtime change: the request filter matches on TypedDict keys and never inspects
the value. The test fixtures move to the captured shapes so the regression tests
pin what the client and the provider actually exchange.
|
@greptileai please review the current head 1ac4d7a, which retypes safeguards and safeguard_results as arrays and updates the test fixtures |
… beta to Bedrock Invoke and Vertex on /v1/messages Claude Code's server-side auto-mode classifier sends a `safeguards` body field together with the `dangerous-tool-use-2026-09-03` beta. PR BerriAI#42152 made the first-party anthropic route pass them through, but the beta header mapping left the other two Claude platforms at null, so Bedrock Invoke dropped both (classifier silently disabled) and Vertex forwarded the body field without the beta, which the platform rejects with "safeguards: Extra inputs are not permitted" (a 400 Claude Code hides by retrying without them). Map the beta for bedrock and vertex_ai in the beta headers config and add `safeguards` to the Bedrock Invoke request allowlist so the pair reaches both platforms unchanged. Nothing is injected: a client that sends `safeguards` without the beta still gets the platform's 400, exactly as api.anthropic.com answers it.
…tive /v1/messages Backport of BerriAI#42152 to stable/1.102.x. Cherry-picked from merge commit e912ebe (litellm_claude_code_safeguards_passthrough).
…02.1) (#736) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/berriai/litellm](https://images.chainguard.dev/directory/image/wolfi-base/overview) ([source](https://github.com/BerriAI/litellm)) | patch | `v1.102.0` → `v1.102.1` | --- ### Release Notes <details> <summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary> ### [`v1.102.1`](https://github.com/BerriAI/litellm/releases/tag/v1.102.1) [Compare Source](BerriAI/litellm@v1.102.0...v1.102.1) ##### Verify Docker Image Signature All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53). **Verify using the pinned commit hash (recommended):** A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` **Verify using the release tag (convenience):** Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/v1.102.1/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` Expected output: ``` The following checks were performed on each of these signatures: - The cosign claims were validated - The signatures were verified against the specified public key ``` *** ##### What's Changed - fix(anthropic): backport [#​42152](BerriAI/litellm#42152) and [#​42288](BerriAI/litellm#42288) to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42538](BerriAI/litellm#42538) - feat(typesafe): backport the jev change set to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42595](BerriAI/litellm#42595) - chore(release): backport [#​42388](BerriAI/litellm#42388) and [#​41462](BerriAI/litellm#41462) to stable/1.102.x by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42618](BerriAI/litellm#42618) **Full Changelog**: <BerriAI/litellm@v1.102.0...v1.102.1> </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/London) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDguMiIsInVwZGF0ZWRJblZlciI6IjQ0LjEwOC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.hayden.moe/hayden/phoebe/pulls/736
…02.1) (#2200) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/berriai/litellm](https://images.chainguard.dev/directory/image/wolfi-base/overview) ([source](https://github.com/BerriAI/litellm)) | patch | `v1.102.0` → `v1.102.1` | --- >⚠️ **Warning** > > Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/6) for more information. --- ### Release Notes <details> <summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary> ### [`v1.102.1`](https://github.com/BerriAI/litellm/releases/tag/v1.102.1) [Compare Source](BerriAI/litellm@v1.102.0...v1.102.1) #### Verify Docker Image Signature All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53). **Verify using the pinned commit hash (recommended):** A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` **Verify using the release tag (convenience):** Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/v1.102.1/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` Expected output: ``` The following checks were performed on each of these signatures: - The cosign claims were validated - The signatures were verified against the specified public key ``` *** #### What's Changed - fix(anthropic): backport [#​42152](BerriAI/litellm#42152) and [#​42288](BerriAI/litellm#42288) to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42538](BerriAI/litellm#42538) - feat(typesafe): backport the jev change set to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42595](BerriAI/litellm#42595) - chore(release): backport [#​42388](BerriAI/litellm#42388) and [#​41462](BerriAI/litellm#41462) to stable/1.102.x by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42618](BerriAI/litellm#42618) **Full Changelog**: <BerriAI/litellm@v1.102.0...v1.102.1> </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/Rome) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDQuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjEwNC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.aresu.eu/GiorgioAresu/home-ops/pulls/2200
…02.1) (#267) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/berriai/litellm](https://images.chainguard.dev/directory/image/wolfi-base/overview) ([source](https://github.com/BerriAI/litellm)) | patch | `v1.102.0` → `v1.102.1` | --- ### Release Notes <details> <summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary> ### [`v1.102.1`](https://github.com/BerriAI/litellm/releases/tag/v1.102.1) [Compare Source](BerriAI/litellm@v1.102.0...v1.102.1) #### Verify Docker Image Signature All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53). **Verify using the pinned commit hash (recommended):** A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` **Verify using the release tag (convenience):** Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/v1.102.1/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` Expected output: ``` The following checks were performed on each of these signatures: - The cosign claims were validated - The signatures were verified against the specified public key ``` *** #### What's Changed - fix(anthropic): backport [#​42152](BerriAI/litellm#42152) and [#​42288](BerriAI/litellm#42288) to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42538](BerriAI/litellm#42538) - feat(typesafe): backport the jev change set to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42595](BerriAI/litellm#42595) - chore(release): backport [#​42388](BerriAI/litellm#42388) and [#​41462](BerriAI/litellm#41462) to stable/1.102.x by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42618](BerriAI/litellm#42618) **Full Changelog**: <BerriAI/litellm@v1.102.0...v1.102.1> </details> --- ### Configuration 📅 **Schedule**: (in timezone America/New_York) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDUuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjEwNS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.greyrock.io/todd/home-ops/pulls/267
…tive /v1/messages Backport of BerriAI#42152 to stable/1.99.x. Cherry-picked from merge commit e912ebe (litellm_claude_code_safeguards_passthrough).
…tive /v1/messages (BerriAI#42152) Backport of BerriAI#42152 to stable/1.103.x. Cherry-picked from e912ebe (main, first parent).
…03.2) (#328) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/berriai/litellm](https://images.chainguard.dev/directory/image/wolfi-base/overview) ([source](https://github.com/BerriAI/litellm)) | patch | `v1.103.1` → `v1.103.2` | --- ### Release Notes <details> <summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary> ### [`v1.103.2`](https://github.com/BerriAI/litellm/releases/tag/v1.103.2) [Compare Source](BerriAI/litellm@v1.103.1...v1.103.2) #### Verify Docker Image Signature All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53). **Verify using the pinned commit hash (recommended):** A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \ ghcr.io/berriai/litellm:v1.103.2 ``` **Verify using the release tag (convenience):** Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/v1.103.2/cosign.pub \ ghcr.io/berriai/litellm:v1.103.2 ``` Expected output: ``` The following checks were performed on each of these signatures: - The cosign claims were validated - The signatures were verified against the specified public key ``` *** #### What's Changed - chore(release): sync stable/1.103.x to v1.103.1 by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​43824](BerriAI/litellm#43824) - fix(proxy): backport [#​40541](BerriAI/litellm#40541), [#​43642](BerriAI/litellm#43642), and [#​43656](BerriAI/litellm#43656) to stable/1.103.x for v1.103.2 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​43897](BerriAI/litellm#43897) - fix(anthropic): backport [#​42152](BerriAI/litellm#42152) and [#​42288](BerriAI/litellm#42288) to stable/1.103.x by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​43662](BerriAI/litellm#43662) - fix(proxy): backport [#​43962](BerriAI/litellm#43962) to stable/1.103.x by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​43984](BerriAI/litellm#43984) **Full Changelog**: <BerriAI/litellm@v1.103.1...v1.103.2> </details> --- ### Configuration 📅 **Schedule**: (in timezone America/New_York) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMTUuMTMiLCJ1cGRhdGVkSW5WZXIiOiI0NC4xMTUuMTMiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbInJlbm92YXRlL2NvbnRhaW5lciIsInR5cGUvcGF0Y2giXX0=--> Reviewed-on: https://git.greyrock.io/todd/home-ops/pulls/328
TLDR
Problem this solves:
/v1/messagesdropped thesafeguardsrequest fieldanthropic-betaHow it solves it:
safeguardsadded toAnthropicMessagesRequestOptionalParamsand the native supported listanthropicroute no longer filtersanthropic-beta, other providers still dosafeguardsandsafeguard_resultstyped as the arrays Claude Code 2.1.278 and api.anthropic.com actually exchange ([{"type": "dangerous_tool_use", ...}]), declared on the request, response and streaming chunk types (runtime already kept them)safeguardsinstead of leaking itUser Flow
Before: a Claude Code user on auto mode pays for classifier requests because the gateway strips the safeguards contract
"safeguards": {"auto_mode": {...}}andanthropic-beta: interleaved-thinking-2025-05-14,safeguards-2026-09-01safeguardskey and ananthropic-betaheader holding onlyinterleaved-thinking-2025-05-14safeguard_results, so Claude Code decides server review is unavailable and starts sending its own billed classifier requestsAfter: the same request reaches Anthropic unchanged and the response carries the server verdict
safeguardsin the body and the fullanthropic-betavalue,anthropic-versionuntouchedmessage_start/message_deltawhen streaming) carriessafeguard_results, so the session qualifies for no-charge classifier requestssafeguardsfield and the full beta header, priced normallyRelevant issues
Affected release
Linear ticket
Resolves LIT-8232
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@greptileaito re-request a review after pushing changes)Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
Root cause in one sentence: the native Anthropic Messages path builds its request allowlist from
AnthropicMessagesRequestOptionalParams(nosafeguards) and runs the cross-provideranthropic-betafilter even when the upstream is api.anthropic.com, so both the field and the unknown beta were dropped before the request left the proxySetup shared by both arms. Postgres plus the proxy on
localhost:4000started withPYTHONPATH=$PWD uv run --no-sync litellm --config proxy_config.yaml --port 4000. Thefake-claudedeployment isanthropic/claude-sonnet-4-5withapi_base: http://127.0.0.1:4123, a tiny HTTP server that records the exact headers and body it receives and answers a real Anthropic-shaped message (withsafeguard_results) as JSON or SSE.real-claudeisanthropic/claude-haiku-4-5against api.anthropic.com with a real key. Payloads are byte-identical across armsreq.json:{"model":"fake-claude","max_tokens":64,"safeguards":{"auto_mode":{"enabled":true,"version":"2026-09-01"}},"system":[{"type":"text","text":"You are Claude Code."},{"type":"text","text":"attribution block","cache_control":{"type":"ephemeral"}}],"messages":[{"role":"user","content":"hi"}]}req_stream.jsonis the same with"stream":true. Headers on every call:anthropic-version: 2023-06-01andanthropic-beta: interleaved-thinking-2025-05-14,safeguards-2026-09-01Before (0f7d4dc)
Native /v1/messages, non-streaming
curl -s localhost:4000/v1/messages -H "Authorization: Bearer $KEY" -H "content-type: application/json" -H "anthropic-version: 2023-06-01" -H "anthropic-beta: interleaved-thinking-2025-05-14,safeguards-2026-09-01" -d @req.json"safeguard_results":{"verdict":"allow","checks":["shell_command"]}because the fake upstream always sends it{"anthropic-beta": "interleaved-thinking-2025-05-14", "anthropic-version": "2023-06-01", "has_safeguards": false, "safeguards": null, "body_keys": ["max_tokens", "messages", "model", "system"]}. Thesafeguardsfield is gone andsafeguards-2026-09-01was stripped from the beta headerNative /v1/messages, streaming
-Nand-d @req_stream.jsonmessage_startandmessage_deltareach the client withsafeguard_results(the SSE bytes are forwarded raw)has_safeguards: false, beta header reduced tointerleaved-thinking-2025-05-14After (b59028d; 1ac4d7a only retypes the fields as arrays and changes no runtime code, the filter matches on keys, not values)
Native /v1/messages, non-streaming
req.json{'anthropic-beta': 'interleaved-thinking-2025-05-14,safeguards-2026-09-01', 'anthropic-version': '2023-06-01', 'has_safeguards': True, 'safeguards': {'auto_mode': {'enabled': True, 'version': '2026-09-01'}}}and the body keys now includesafeguards, with thesystemarray and its attribution block in the original orderNative /v1/messages, streaming
-N -d @req_stream.jsonhas_safeguards: True, full beta headerReal api.anthropic.com (costs real money)
curl -s localhost:4000/v1/messages ... -d '{"model":"real-claude","max_tokens":16,"messages":[{"role":"user","content":"Say ok"}]}'returns 200 with"content":[{"type":"text","text":"ok"}]-H "anthropic-beta: safeguards-2026-09-01"and"safeguards":{"auto_mode":{...}}in the body returns 400 from Anthropic:Unexpected value(s) safeguards-2026-09-01 for the anthropic-beta header. Without the header Anthropic answerssafeguards: Extra inputs are not permitted. Both errors come from Anthropic, which proves the proxy now forwards the field and the beta verbatim. The account used here is not enrolled in the safeguards beta, so the positive verdict is shown with the recording upstream aboveAdmin UI, http://localhost:4000/ui/logs
fake-clauderows at 17:08 are the fixed non-streaming and streaming calls, logged as Success with cost$0.000105, so logging and cost tracking tolerate the new fieldsafeguards.auto_modeand the forwardedanthropic-beta: interleaved-thinking-2025-05-14,safeguards-2026-09-01plusanthropic-version: 2023-06-01real-claudefailure row shows Anthropic's ownsafeguards: Extra inputs are not permittedmessage, i.e. the field left the proxyHandler branches exercised
Both arms go through
anthropic_messages->BaseLLMHTTPHandler.anthropic_messages_handlerwithcustom_llm_provider="anthropic", i.e.AnthropicMessagesConfig. The non-streaming leg takes the JSON response branch, the streaming leg takes theAnthropicMessagesStreamingResponseraw SSE forward. The raw pass-through routePOST /anthropic/v1/messageswas also exercised: it forwards the body and headers verbatim already (upstream capture showedhas_safeguards: Trueand the full beta before the fix), so no change was needed there. Cross-provider configs (bedrock, vertex_ai) keep filtering betas becauseshould_filter_anthropic_beta_headersonly returns False when the resolved provider isanthropicMutation checks
Removing
safeguardsfromAnthropicMessagesRequestOptionalParamsfails both new tests (2 failed), restoring the line passes them (2 passed), restore verified withcmp -s. Removing theshould_filter_anthropic_beta_headersoverride fails the non-streaming test on the beta assertion. RemovingsafeguardsfromANTHROPIC_ONLY_REQUEST_KEYSfails the new adapter test (1 failed). Removingsafeguardsfromget_supported_anthropic_messages_paramsalone survives: that list does not gate request fields on this path, it is kept so the native supported surface stays truthfulTaxonomy audit
F3/O4 (sibling surfaces): streaming and non-streaming both covered by tests and live runs,
/anthropic/*pass-through audited and untouched, the adapter path (/v1/messagesto an OpenAI-format model) now stripssafeguardslikeoutput_configso those backends do not get a 400. W1 (caller dict mutation): no new mutation, the fix only adds a key to an allowlist and an override returning a bool. X1 (falsy handling):safeguardsis only dropped whenNone, an empty dict is forwarded. V1: no key routing change. C1-C7: beta filtering on the first-partyanthropicprovider changes from allowlist to pass-through, called out in Caveats. H: no new comments in source,X | Noneused,ReadOnlyon both TypedDict fields, no budget files touched. T1-T5: both tests fail on the unfixed treeType
🐛 Bug Fix
Caveats (if any)
Low
anthropicroute now forwards everyanthropic-betavalue, so a typo reaches Anthropic and returns their 400 instead of being silently droppedsafeguard_resultsproof uses a recording upstream; the real account is not enrolled in the betaFinal Attestation
Link to Devin session: https://app.devin.ai/sessions/b5a306df827d4047a1cf9d8d41c0aba8
Open in Devin Desktop: https://app.devin.ai/desktop/session/b5a306df827d4047a1cf9d8d41c0aba8?variant=devin
Requested by: @yassin-berriai