Summary
Expose adk-anthropic's existing per-request header plumbing publicly, so callers can supply the full HeaderMap for a messages request — enabling Authorization: Bearer auth, caller-controlled anthropic-beta composition, and anthropic-version selection without forking the client.
Motivation
The client internally already treats headers as per-request values with replacement semantics: execute_post_request(url, body, headers: Option<HeaderMap>) replaces the defaults entirely when a map is supplied, and both send() and stream() build and mutate a per-request map (the streaming ACCEPT swap, the conditional beta joins). But none of that is reachable publicly — build_default_headers is fixed (x-api-key, anthropic-version: "2023-06-01"), cached_headers has no setter, and no public method accepts headers (as of df9ef83, adk-anthropic/src/client.rs:305-320, 481-505, 533-604, 625-715).
That closes off three real use cases we've hit while building an Anthropic integration:
- Bearer-token auth. Several Anthropic-compatible surfaces authenticate with
Authorization: Bearer <token> instead of x-api-key — OAuth access tokens, and gateways such as GitHub Copilot's Anthropic endpoint. Today there is no way to send Authorization or to omit x-api-key.
- Caller-controlled
anthropic-beta. The client composes betas for its own features (structured outputs, context management, fast mode), but callers cannot request other documented betas — e.g. fine-grained-tool-streaming-2025-05-14 or interleaved-thinking-2025-05-14 — or suppress betas for gateways that reject them.
anthropic-version selection. Pinned to a const today.
Proposed Solution
Expose the existing internal parameter — smallest possible API surface, e.g.:
pub async fn send_with_headers(&self, params: MessageCreateParams, headers: HeaderMap) -> Result<Message>;
pub async fn stream_with_headers(&self, params: &MessageCreateParams, headers: HeaderMap) -> Result<impl Stream<Item = Result<MessageStreamEvent>>>;
with documented replacement semantics (the supplied map replaces the defaults, exactly like the internal parameter today). Replacement rather than merge is load-bearing: it lets a caller send Authorization: Bearer … without x-api-key, so no request ever carries two credentials. A convenience Anthropic::default_headers_for(&self) -> HeaderMap (or making the current private default_headers() public) would let callers start from the standard set and adjust.
Base-URL validation from #457/#458 is unaffected — this proposal changes no URL handling, and the https/loopback rule keeps guarding wherever the headers go.
An alternative shape (builder-level with_extra_headers(HeaderMap) merged into cached_headers) is workable for betas/version but cannot express "omit x-api-key" without additional delete semantics, which is why the per-request replacement form seems cleaner.
Affected Crate(s)
adk-anthropic
Alternatives Considered
- Merge-style extra headers — cannot drop
x-api-key for bearer auth without delete sentinels (see above).
- Forking the client — works, but this is plumbing the crate already has; exposing it keeps downstream users on the shared implementation.
- Env-var control — headers vary per request (per-model beta sets), so process-level configuration doesn't fit.
Additional Context
Following the ask-first convention (per #550): happy to send the PR — the change is exposing the existing Option<HeaderMap> parameter plus docs and tests for the replacement semantics and the bearer-without-x-api-key case. Related follow-up we'd also like to propose separately: a fallbacks field on MessageCreateParams for the server-side fallback beta.
Summary
Expose adk-anthropic's existing per-request header plumbing publicly, so callers can supply the full
HeaderMapfor a messages request — enablingAuthorization: Bearerauth, caller-controlledanthropic-betacomposition, andanthropic-versionselection without forking the client.Motivation
The client internally already treats headers as per-request values with replacement semantics:
execute_post_request(url, body, headers: Option<HeaderMap>)replaces the defaults entirely when a map is supplied, and bothsend()andstream()build and mutate a per-request map (the streaming ACCEPT swap, the conditional beta joins). But none of that is reachable publicly —build_default_headersis fixed (x-api-key,anthropic-version: "2023-06-01"),cached_headershas no setter, and no public method accepts headers (as ofdf9ef83,adk-anthropic/src/client.rs:305-320, 481-505, 533-604, 625-715).That closes off three real use cases we've hit while building an Anthropic integration:
Authorization: Bearer <token>instead ofx-api-key— OAuth access tokens, and gateways such as GitHub Copilot's Anthropic endpoint. Today there is no way to sendAuthorizationor to omitx-api-key.anthropic-beta. The client composes betas for its own features (structured outputs, context management, fast mode), but callers cannot request other documented betas — e.g.fine-grained-tool-streaming-2025-05-14orinterleaved-thinking-2025-05-14— or suppress betas for gateways that reject them.anthropic-versionselection. Pinned to a const today.Proposed Solution
Expose the existing internal parameter — smallest possible API surface, e.g.:
with documented replacement semantics (the supplied map replaces the defaults, exactly like the internal parameter today). Replacement rather than merge is load-bearing: it lets a caller send
Authorization: Bearer …withoutx-api-key, so no request ever carries two credentials. A convenienceAnthropic::default_headers_for(&self) -> HeaderMap(or making the current privatedefault_headers()public) would let callers start from the standard set and adjust.Base-URL validation from #457/#458 is unaffected — this proposal changes no URL handling, and the https/loopback rule keeps guarding wherever the headers go.
An alternative shape (builder-level
with_extra_headers(HeaderMap)merged intocached_headers) is workable for betas/version but cannot express "omitx-api-key" without additional delete semantics, which is why the per-request replacement form seems cleaner.Affected Crate(s)
adk-anthropic
Alternatives Considered
x-api-keyfor bearer auth without delete sentinels (see above).Additional Context
Following the ask-first convention (per #550): happy to send the PR — the change is exposing the existing
Option<HeaderMap>parameter plus docs and tests for the replacement semantics and the bearer-without-x-api-key case. Related follow-up we'd also like to propose separately: afallbacksfield onMessageCreateParamsfor the server-side fallback beta.