Skip to content

fix(agent): strip x-stainless headers from OAuth Anthropic requests to prevent 429 - #70054

Closed
x7peeps wants to merge 1 commit into
NousResearch:mainfrom
x7peeps:fix/issue-70039-anthropic-oauth-429
Closed

fix(agent): strip x-stainless headers from OAuth Anthropic requests to prevent 429#70054
x7peeps wants to merge 1 commit into
NousResearch:mainfrom
x7peeps:fix/issue-70039-anthropic-oauth-429

Conversation

@x7peeps

@x7peeps x7peeps commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Background

Fixes #70039: Anthropic subscription OAuth token gets generic 429 through Hermes, while the genuine Claude Code binary works with the same token.

Root Cause Analysis

The Anthropic Python SDK automatically injects x-stainless-* headers into every request (x-stainless-lang, x-stainless-runtime, x-stainless-package-version, x-stainless-arch, x-stainless-os).

Claude Code CLI uses axios (Node.js) to send requests without these headers. Anthropic infrastructure uses these SDK headers as a fingerprint to distinguish Claude Code official client from third-party SDK requests, and applies stricter rate-limit tiers for subscription OAuth tokens.

Even when the User-Agent, x-app, and anthropic-beta headers match Claude Code fingerprint exactly, the presence of x-stainless-* headers causes Anthropic to classify the request as third-party SDK traffic, persistently returning HTTP 429 for subscription tokens.

Fix

In the build_anthropic_client OAuth token branch, route requests through a custom httpx.Client with a request event hook that strips all x-stainless-* headers before they go on the wire.

This makes the HTTP request indistinguishable from the genuine Claude Code CLI traffic, allowing subscription tokens to work through the native adapter.

The pattern mirrors the existing Azure Entra ID bearer hook (_build_anthropic_client_with_bearer_hook) already in the codebase.

Changes:

  • agent/anthropic_adapter.py: New _build_oauth_http_client() helper + custom http_client in OAuth branch
  • tests/agent/test_anthropic_oauth_ua_prefix.py: New TestOAuthStainlessHeaders test class (2 test cases)

Verification

  • Code changes verified locally (pytest 6 passed)
  • Follows project AGENTS.md contribution guidelines
  • No breaking changes (only affects OAuth token path, API key path unchanged)

Closes #70039

… to prevent 429

Fix NousResearch#70039

Anthropic's Python SDK automatically injects x-stainless-* headers
(language, runtime, OS, package version) into every request. Anthropic's
infrastructure uses these headers as a fingerprint to differentiate
"Claude Code CLI" (which uses axios) from "third-party SDK" requests.

When a subscription OAuth token is used through Hermes, the presence of
these SDK headers causes Anthropic to apply stricter rate-limit tiers,
resulting in persistent HTTP 429 errors — even when the User-Agent,
x-app, and anthropic-beta headers match Claude Code's fingerprint exactly.

Fix: For OAuth token auth, route requests through a custom httpx.Client
with a request event hook that strips all x-stainless-* headers before
they go on the wire. This makes the HTTP request indistinguishable from
the genuine Claude Code CLI's traffic, allowing subscription tokens to
work through the native adapter.

The pattern mirrors the existing Azure Entra ID bearer hook
(_build_anthropic_client_with_bearer_hook) already in the codebase.
@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 provider/anthropic Anthropic native Messages API area/auth Authentication, OAuth, credential pools sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades needs-repro Bug needs reproduction steps needs-decision Awaiting maintainer decision before any implementation labels Jul 23, 2026
@x7peeps x7peeps closed this Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint needs-decision Awaiting maintainer decision before any implementation needs-repro Bug needs reproduction steps P2 Medium — degraded but workaround exists provider/anthropic Anthropic native Messages API 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.

Anthropic subscription OAuth token gets generic 429 through Hermes, while the genuine Claude Code binary works with the same token

2 participants