Skip to content

Add User-Agent header to outbound requests#5

Merged
cretz merged 1 commit into
mainfrom
cretz/user-agent-header
May 6, 2026
Merged

Add User-Agent header to outbound requests#5
cretz merged 1 commit into
mainfrom
cretz/user-agent-header

Conversation

@cretz
Copy link
Copy Markdown
Collaborator

@cretz cretz commented May 5, 2026

What changed

Add User-Agent header on HTTP calls to Baseten and other minor adjustments

@cretz cretz requested review from Copilot and marius-baseten May 5, 2026 16:56
if http_client is None:
if http_client_override is None:
request_headers: dict[str, str] = {**(headers or {})}
# Empty api_key is an advanced opt-out from sending Authorization.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the use case for this? Testing/dev only?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To give more full freedom. Technically forcing auth headers on people with 0 workaround can be bad practice for those that have reverse proxies (that only set header on the way upstream). I just didn't want to make API key optional for this rare use case, but it does happen in the wild for API clients like these.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, so this is against the "DUMMY_KEY" value that you'd otherwise need to set.

Though this does stand in tension with fail loud, early and actionable. Setting DUMMY_KEY must be done with clear intent and understanding. Forgetting an API key could be a common mistake. If that happens, the question is how clear would it surface to users that this is the problem and what they need to do to fix it.

Copy link
Copy Markdown
Collaborator Author

@cretz cretz May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this is against the "DUMMY_KEY" value that you'd otherwise need to set.

We were actually force-overriding until this point, there was nothing you could do short of providing your own HTTP client instance

Forgetting an API key could be a common mistake

This is why I don't accept None as a type. But yeah, absent key or bad key have the same server-side auth fail upon invocation. I could accept api_key: str | IDoNotWantAuthHeaderSentinel type of thing, but not even trying to broadcast this via type system (note empty string behavior not in docstring).

api_key: str,
headers: Mapping[str, str] | None = None,
model_id: str | None = None,
chain_id: str | None = None,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why you can specify IDs of two differently typed inference targets for one client.

My reasoning is that a user must know and in advance decide whether they want to invoke a chain or a model, and if that's so, isn't it cleaner to also select the respective inference client type to init?
This hinges now on the assumption that both chains and models always have exact semantics and types for invoking.

Was the goal here more about impl/code sharing or about not bothering the user with two distinct interfaces/types? But would the latter be even good, rather than obfuscating/misleading?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think the "exactly one must be provided"-semantics is both awkward for the code we have to write for checking this at runtime.
But also client side there is no linter/type check that helps enforcing this properly before runtime.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My reasoning is that a user must know and in advance decide whether they want to invoke a chain or a model, and if that's so, isn't it cleaner to also select the respective inference client type to init?

Cleaner to whom, us and our type checker, or the user? Which looks cleaner to you: InferenceClient(api_key=my_api_key, chain_id=my_chain_id) or InferenceClient(api_key=my_api_key, ref=ChainReference(chain_id=my_chain_id)). It is very clearly the former. However, if it is of great concern to have kwarg mutual exclusivity in the type system, we can leverage @overload to prevent both together (though this can get messy as it grows).

Was the goal here more about impl/code sharing or about not bothering the user with two distinct interfaces/types? But would the latter be even good, rather than obfuscating/misleading?

It was more to match the API/spec surface. So we have https://docs.baseten.co/reference/inference-api/, not separate APIs. The only difference is in the construction. It is more misleading to have some places at Baseten share an API surface under a common concept (inference API in this case) and some split.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I understand your reasoning. InferenceClient(api_key=my_api_key, chain_id=my_chain_id) does look clean, but I was thinking about InferenceClient(api_key=my_api_key) or InferenceClient(api_key=my_api_key, chain_id=my_chain_id, model_id=...).
@overload is actually the ideal solution here, I think you should add that.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do that no prob (will do on successive PR)

Comment thread baseten/client/_inference.py
Comment thread baseten/client/_management.py
Comment thread baseten/client/_user_agent.py
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@cretz cretz merged commit ae0b6c3 into main May 6, 2026
5 of 8 checks passed
@cretz cretz deleted the cretz/user-agent-header branch May 6, 2026 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants