Spaces:
Running on CPU Upgrade
feat: forward inbound User-Agent to HF router (append convention)
Problem
The proxy's outbound calls to the HF router set no User-Agent (reqwest 0.12 has no default UA โ seanmonstar/reqwest#540). So the router records metadata.userAgent = "Amazon CloudFront" for all proxied Claude Code traffic and cannot attribute it to the originating client. This blocks accurate per-agent/per-client stats in the HF router (e.g. distinguishing Claude Code from other OpenAI-spec router clients).
Root cause
- Claude Code does send a
User-Agent(Anthropic SDK /CLAUDE_AGENT_SDK_CLIENT_APPโclaude-code/<ver>, plusanthropic-version,x-stainless-*). - The single CloudFront distribution (
E1YEKOUYDG655W) frontingrouter.huggingface.coforwards viewer headers to the proxy origin via itsallViewerorigin-request policy (NoCookie,f4a73954-โฆ). So the inbound UA is available to the proxy โ it just wasn't reading or forwarding it. - Verified empirically: a probe with
User-Agent: probe-ua-distinctive-12345reached the router'smetadata.userAgentunchanged. When no UA is sent, CloudFront injectsAmazon CloudFront(its default for absent UA). CloudFront does not rewrite a present UA underallViewerโ theAmazon CloudFrontentries are purely the proxy sending no UA.
Fix
Read the inbound User-Agent and forward it appended to the proxy's own identity, following the standard reverse-proxy convention (e.g. Grafana's forward_user_agent):
User-Agent: claude-code-adapter/<ver> <inbound-client-ua>
Falls back to the proxy identity alone when no inbound UA is present. Implemented as a shared forwarded_user_agent(&headers) helper in src/handlers/mod.rs, applied at all three outbound request sites:
src/handlers/messages.rsโ initial requestsrc/handlers/messages.rsโ 400-retry requestsrc/handlers/responses.rsโ responses API request
The proxy's own identity uses env!("CARGO_PKG_NAME")/env!("CARGO_PKG_VERSION") so it stays in sync with Cargo.toml.
Effect
After this ships, the HF router records metadata.userAgent = "claude-code-adapter/0.1.0 claude-code/2.1.205" for Claude Code traffic instead of "Amazon CloudFront". No CloudFront config change, no router schema change โ reuses the router's existing metadata.userAgent capture path (server/app/inferencePartners.ts, req.header("user-agent")).
For the agent vs. classifier distinction (both carry the same Claude Code UA), the proxy's existing stop-sequence detection (src/adapter/convert_request.rs) remains the signal โ orthogonal, tracked separately.
Verification
cargo testgreen โ 16/16, including 3 new unit tests for the helper (forwards_inbound_user_agent_appended,falls_back_to_proxy_identity_when_no_inbound_ua,falls_back_when_inbound_ua_empty).- CloudFront
allViewerUA forwarding confirmed by direct probe (distinctive UA reached routermetadata.userAgentverbatim).
Note: Generated with Claude Code, acting for @Pierrci .
Investigation trace: anthropic-proxy-classifier-thinking-timeout-5dc27541.jsonl (HF internal bucket, 906KB) โ full session incl. the CloudFront UA-forwarding probes. Also on Traces: https://traces.com/s/jn7ewfqkrv48s1138011mmanps8bv22v