Skip to content

fix(custom-provider): preserve base URL for anthropic_messages api_mode - #30232

Closed
terlanks wants to merge 1 commit into
NousResearch:mainfrom
terlanks:fix/custom-provider-anthropic-messages-url
Closed

fix(custom-provider): preserve base URL for anthropic_messages api_mode#30232
terlanks wants to merge 1 commit into
NousResearch:mainfrom
terlanks:fix/custom-provider-anthropic-messages-url

Conversation

@terlanks

Copy link
Copy Markdown

Problem

When a custom provider is configured with api_mode: anthropic_messages, the code in resolve_provider_client() unconditionally rewrites the base URL via _to_openai_base_url(), converting e.g. http://host/anthropichttp://host/v1.

The Anthropic SDK then appends /v1/messages to the base URL, resulting in a request to /v1/v1/messages404.

Root Cause

The generic custom provider branch (~line 3271) lacks the api_mode guard that the named custom-provider branch (~line 3380) already has:

# named-custom branch (correct)
if entry_api_mode == "anthropic_messages":
    # keeps custom_base as-is
else:
    openai_base = _to_openai_base_url(custom_base)

The generic branch was missing this check entirely.

Fix

Apply the same guard to the generic custom branch: when api_mode == "anthropic_messages", keep the original base URL (only strip trailing slash). For all other api_modes, the existing _to_openai_base_url() rewrite is preserved.

Testing

Reproduced and verified with a local Anthropic-compatible proxy (base_url: http://localhost:6655/anthropic, api_mode: anthropic_messages). Before the fix: 404 on every call. After: requests route correctly to /anthropic/v1/messages.

When a custom provider is configured with api_mode=anthropic_messages,
the existing code unconditionally rewrote the base URL via
_to_openai_base_url(), converting e.g. http://host/anthropic to
http://host/v1.  The Anthropic SDK then appended /v1/messages, resulting
in a request to /v1/v1/messages which returns 404.

The named-custom-provider branch (around line 3380) already handled this
correctly by skipping the URL rewrite for anthropic_messages.  Apply the
same guard to the generic custom-provider branch.

Fix: when api_mode == 'anthropic_messages', keep the original base URL
as-is and only strip a trailing slash.  For all other api_modes the
existing _to_openai_base_url() rewrite is preserved.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint area/config Config system, migrations, profiles duplicate This issue or pull request already exists labels May 22, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #29624 — same fix location in auxiliary_client.py generic custom provider branch: skip _to_openai_base_url() when api_mode == "anthropic_messages". PR #29624 is a broader fix (builds full Anthropic client); this PR is a minimal guard. Same bug class as #17084 (closed), #17467 (merged).

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for isolating the generic custom-provider path. The premise still holds on current main: agent/auxiliary_client.py:4636 rewrites an explicit custom URL before agent/auxiliary_client.py:4693 passes that rewritten value into the Anthropic wrapper. The named-provider and fallback-custom paths already preserve the Anthropic route (agent/auxiliary_client.py:2403-2419, agent/auxiliary_client.py:4756-4804).

Problems

  • The diff has no regression test. Existing tests cover _try_custom_endpoint() (tests/agent/test_auxiliary_client_anthropic_custom.py:35) and named custom providers (tests/agent/test_auxiliary_named_custom_providers.py:341), not resolve_provider_client("custom", explicit_base_url=..., api_mode="anthropic_messages").

Suggested changes

  • Add a focused test for that explicit-base generic branch, asserting it returns an AnthropicAuxiliaryClient whose base URL remains the supplied /anthropic URL, plus a non-Anthropic control assertion that preserves the existing OpenAI rewrite.

The target has moved to agent/auxiliary_client.py:4636, so salvage requires a small manual transplant rather than a clean cherry-pick. This is an automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
@teknium1

Copy link
Copy Markdown
Contributor

This bug is now fixed on main via #85466 (salvage of #64891). Credit correction: your PR was submitted May 22 — the second-earliest fix for this branch (after #29624 on May 21), months before the version that merged, and your diff is nearly line-identical to what landed for the wrapper path. The pre-merge duplicate sweep missed it, which is our miss.

The merged variant additionally kept the /v1 rewrite for the plain-OpenAI fallback client and carried a regression test file, so it was taken as the base. Closing as resolved-on-main with early-submitter credit to you. Thanks, and sorry for the wait.

@teknium1 teknium1 closed this Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants