feat(proxy): Anthropic Claude OAuth upstream adapter - #58647
Open
demi-hl wants to merge 1 commit into
Open
Conversation
Adds `--provider anthropic` to `hermes proxy`, forwarding Anthropic
Messages API requests using Hermes-managed Anthropic OAuth credentials
(Claude Pro/Max), so local apps can hit Claude through the proxy with any
bearer token — same pattern as the existing nous/xai upstreams.
Anthropic's OAuth endpoint needs more than a bearer swap, so this adds two
small, opt-in adapter hooks to the proxy server (both default to no-op, so
nous/xai are unaffected):
- extra_headers(cred): inject the OAuth beta/version/user-agent headers.
- transform_body(path, body): prepend the Claude Code system identity
block, which the OAuth endpoint expects on subscription tokens.
Also strips inbound `x-api-key` alongside `authorization` in the forward
path — the proxy always supplies its own credential, and a stale client
x-api-key otherwise takes precedence at Anthropic and 401s the OAuth call.
Adapter reuses the existing agent.credential_pool (load/select/refresh/
rotate on 401|429), mirroring the xai adapter. Only /messages is forwarded.
teknium1
reviewed
Jul 15, 2026
teknium1
left a comment
Contributor
There was a problem hiding this comment.
Thanks for extending the subscription proxy to a concrete Anthropic OAuth use case.
Problems
tests/hermes_cli/test_proxy.py:51-53currently requiresget_adapter("anthropic")to raise. This PR registersanthropicbut changes no tests, so the existing suite will fail.- The adapter selects from the shared
anthropicpool without filtering to OAuth.agent/credential_pool.py:92-93supports both OAuth and API-key entries, andCredentialPool.select()(agent/credential_pool.py:1419-1421) has no auth-type filter. An API-key entry could be sent as Bearer through the OAuth masquerade path. - Native OAuth requests include
x-app: clialongside the beta and user-agent headers (agent/anthropic_adapter.py:818-823); the new hook omits it. - The feature changes the proxy's documented pass-through contract, but
website/docs/user-guide/features/subscription-proxy.md:185-203and the static provider help inhermes_cli/subcommands/gateway.py:321-325are not updated.
Suggested changes
- Add hermetic proxy tests, filter selection/rotation to OAuth entries, align the full OAuth header set with
agent/anthropic_adapter.py, and update the proxy docs/help for native Messages API usage.
Automated hermes-sweeper review.
| @@ -16,6 +17,7 @@ | |||
| ADAPTERS: Dict[str, Type[UpstreamAdapter]] = { | |||
| "nous": NousPortalAdapter, | |||
| "xai": XAIGrokAdapter, | |||
Contributor
There was a problem hiding this comment.
This registration invalidates the current expectation in tests/hermes_cli/test_proxy.py:51-53 that get_adapter("anthropic") raises. Please update that test and add coverage for the new adapter; this PR currently changes no test files.
19 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
--provider anthropictohermes proxy, forwarding Anthropic Messages API requests using Hermes-managed Anthropic OAuth credentials (Claude Pro/Max). Local apps can then hit Claude through the proxy with any bearer token — the same "attach real credentials to a dummy-auth request" pattern the existingnousandxaiupstreams already provide.Why it needs more than a bearer swap
Unlike the OpenAI-compatible providers, Anthropic's OAuth endpoint rejects/misroutes subscription tokens unless the request also carries:
To support that without touching the other adapters, this adds two small opt-in hooks to the proxy server, both defaulting to no-op via
getattr(nous/xai are byte-for-byte unaffected):extra_headers(cred) -> dict— merged into the forwarded headers.transform_body(rel_path, body) -> bytes— rewrite the request body (here: prepend the Claude Code system block, idempotently — already-prefixed requests are not double-prefixed).x-api-keystripThe forward path already strips/replaces inbound
authorization. This also strips inboundx-api-key, because the proxy always supplies its own credential — and a stale clientx-api-keyotherwise takes precedence at Anthropic and 401s the OAuth call. No-op for nous/xai (they never receive one).Adapter
AnthropicOAuthAdapterreuses the existingagent.credential_pool(load_pool/select/try_refresh_current/mark_exhausted_and_rotateon 401|429), mirroring the xai adapter's shape. Only/messagesis inallowed_paths(Anthropic OAuth does not serve the/chat/completionssurface).Files
hermes_cli/proxy/adapters/anthropic.py(new)hermes_cli/proxy/server.py— two opt-in hooks +x-api-keystriphermes_cli/proxy/adapters/__init__.py— register inADAPTERSTesting
py_compileclean on all three files.ADAPTERSresolves['anthropic', 'nous', 'xai'].claude-haiku-4-5/claude-sonnet-4-5200s (service_tier: standard), headers injected and system block prepended by the hooks.