Skip to content

[Bug]: OAuth Pro/Max/Team requests rejected with HTTP 400 "third-party / extra usage" (missing x-anthropic-billing-header system block) #48176

Description

@yechan-9208

Bug Description

With a Claude Pro/Max/Team OAuth credential (sk-ant-oat01-*) on the anthropic provider, requests are currently rejected with:

HTTP 400 invalid_request_error:
"Third-party apps now draw from extra usage, not plan limits.
 Ask your workspace admin to add more and keep going."

This makes Pro/Max/Team OAuth effectively unusable on-plan.

This previously worked. Per Anthropic's help article "Use the Claude Agent SDK with your Claude plan", a ~June 15 2026 change that would meter programmatic usage was paused ("…still draw from your subscription's usage limits"). Empirically the pause only restores on-plan billing for traffic that presents as the genuine Agent-SDK/CLI surface — i.e. requests that carry the x-anthropic-billing-header … cc_entrypoint=sdk-cli system block. Hermes omits that block, so it is, for now, treated as third-party traffic.

Steps to Reproduce

  1. Add a Claude Pro/Max/Team OAuth credential: hermes auth add anthropic (or paste an sk-ant-oat01-* token).
  2. Run a request:
    hermes -z "say hi" -m claude-opus-4-8 --provider anthropic --cli
    
  3. The request returns HTTP 400 "...extra usage, not plan limits".

Expected Behavior

The OAuth request should return HTTP 200 with usage.service_tier: "standard", drawn from the subscription plan — the same as the genuine claude CLI on the same account (apiProvider: firstParty).

Actual Behavior

HTTP 400 invalid_request_error
"Third-party apps now draw from extra usage, not plan limits.
 Ask your workspace admin to add more and keep going."

A/B on a live Team plan:

system[0] billing block result
absent (current) HTTP 400
cc_entrypoint=sdk-cli present HTTP 200 (plan)

Affected Component

Agent Core (conversation loop, context compression, memory) — specifically the Anthropic OAuth request path in agent/anthropic_adapter.py.

Messaging Platform (if gateway-related)

N/A (CLI only)

Debug Report

--- hermes dump ---
version:   0.16.0 (2026.6.5)
os:        Darwin 25.5.0 arm64
python:    3.11.15
model:     claude-opus-4-8
provider:  anthropic

--- agent.log (relevant lines, secrets redacted) ---
agent.chat_completion_helpers: Streaming failed before delivery: Error code: 400 -
  {'type':'error','error':{'type':'invalid_request_error','message':'Third-party apps now
  draw from extra usage, not plan limits. Ask your workspace admin to add more and keep
  going.'}, 'request_id':'req_011Cc9nVo4Ca6j3FzBuFpJTK'}
agent.conversation_loop: API call failed (attempt 1/3) error_type=BadRequestError
  provider=anthropic base_url=https://api.anthropic.com model=claude-opus-4-8
  summary=HTTP 400: Third-party apps now draw from extra usage, not plan limits.
agent.conversation_loop: Non-retryable client error (HTTP 400).

Operating System

macOS 26.5.1 (build 25F80)

Python Version

3.11.15

Hermes Version

v0.16.0 (2026.6.5); also reproduced against current main (fcf6cb3)

Additional Logs / Traceback (optional)

Captured from a genuine claude -p request to api.anthropic.com (HTTP 200) via a local logging proxy (ANTHROPIC_BASE_URL). The first system block is a machine-parsed billing-attribution token, distinct from the natural-language identity line:

system[0]  x-anthropic-billing-header: cc_version=2.1.181.d08; cc_entrypoint=sdk-cli;
system[1]  You are a Claude agent, built on Anthropic's Claude Agent SDK.
User-Agent claude-cli/2.1.181 (external, sdk-cli)
x-app      cli
URL        /v1/messages?beta=true

Root Cause Analysis (optional)

The detection is server-side billing/attribution analysis. The genuine Claude Code / Agent-SDK CLI puts the x-anthropic-billing-header token as system[0]:

x-anthropic-billing-header: cc_version=<version>; cc_entrypoint=<entrypoint>;

The OAuth (is_oauth) path in agent/anthropic_adapter.py already declares the Claude Code identity in natural language via cc_block ("You are Claude Code…") but omits system[0] (the billing token), so requests are attributed as a generic third-party app → extra-usage lane → 400.

What the block contains: cc_version (genuine, from the installed claude version) and a hardcoded cc_entrypoint=sdk-cli label. The captured request carried only these two fields; the gate routes on the cc_entrypoint label for this surface.

Proposed Fix (optional)

Prepend the x-anthropic-billing-header block as system[0] on the OAuth path in agent/anthropic_adapter.py, ahead of the identity prefix — establishing at the billing-attribution layer the same Claude Code identity cc_block only asserts in prose. PR attached.

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High — major feature broken, no workaroundarea/authAuthentication, OAuth, credential poolscomp/agentCore agent runtime: loop, agent_init, prompt builder, context-compression, responses endpointprovider/anthropicAnthropic native Messages APItype/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions