feat: auto-load base URL env vars for OpenAI, Anthropic, and Gemini c…#155
feat: auto-load base URL env vars for OpenAI, Anthropic, and Gemini c…#155yauheniya-adesso wants to merge 7 commits into
Conversation
…lients - OpenAI: reads OPENAI_API_BASE as fallback base_url - Anthropic: reads ANTHROPIC_BASE_URL as fallback base_url; api_key now optional (auto-loaded from ANTHROPIC_API_KEY) - Gemini: reads GEMINI_API_BASE as fallback base_url - Add .env.example covering all supported backends
There was a problem hiding this comment.
Pull request overview
Adds automatic environment-variable fallbacks for configuring LLM client base URLs, enabling use behind custom gateways/proxies without requiring base_url to be passed explicitly in code.
Changes:
- OpenAI client: fall back to
OPENAI_API_BASEwhenbase_urlis not provided. - Anthropic client: support
ANTHROPIC_API_KEY+ANTHROPIC_BASE_URLfallbacks and makeapi_keyoptional. - Gemini client: add
base_urlparam and fall back toGEMINI_API_BASE; document supported env vars via new.env.example.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| rlm/clients/openai.py | Adds env fallback for OpenAI base URL (OPENAI_API_BASE). |
| rlm/clients/anthropic.py | Adds dotenv/env defaults for API key + base URL and updates constructor. |
| rlm/clients/gemini.py | Adds base URL configuration support via env + constructor argument. |
| .env.example | Documents environment variables for supported backends. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Fall back to OPENAI_API_BASE env var if base_url is not explicitly provided. | ||
| if base_url is None: | ||
| base_url = DEFAULT_OPENAI_API_BASE |
| if api_key is None: | ||
| api_key = DEFAULT_ANTHROPIC_API_KEY | ||
|
|
||
| if api_key is None: | ||
| raise ValueError( | ||
| "Anthropic API key is required. Set ANTHROPIC_API_KEY env var or pass api_key." | ||
| ) | ||
|
|
||
| # Fall back to ANTHROPIC_BASE_URL env var if base_url is not explicitly provided. | ||
| if base_url is None: | ||
| base_url = DEFAULT_ANTHROPIC_BASE_URL | ||
|
|
||
| client_kwargs = {"api_key": api_key, "timeout": self.timeout} | ||
| if base_url is not None: | ||
| client_kwargs["base_url"] = base_url |
| # Fall back to GEMINI_API_BASE env var if base_url is not explicitly provided. | ||
| if base_url is None: | ||
| base_url = DEFAULT_GEMINI_API_BASE | ||
|
|
||
| # Configure HTTP options with timeout | ||
| http_options = types.HttpOptions(timeout=int(self.timeout * 1000)) # milliseconds | ||
| http_options = types.HttpOptions( | ||
| timeout=int(self.timeout * 1000), # milliseconds | ||
| **({ | ||
| "base_url": base_url | ||
| } if base_url is not None else {}), | ||
| ) |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds automatic environment-variable fallbacks for configuring custom/proxy API base URLs across the OpenAI, Anthropic, and Gemini clients, and documents supported env vars in a new .env.example.
Changes:
- OpenAI client now falls back to
OPENAI_API_BASEwhenbase_urlisn’t provided. - Anthropic client now falls back to
ANTHROPIC_BASE_URLand allowsapi_keyto be omitted (env fallback). - Gemini client now supports
GEMINI_API_BASEand forwards it viahttp_optionswhen present. - Adds
.env.exampleenumerating supported environment variables.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
rlm/clients/openai.py |
Reads OPENAI_API_BASE from env and uses it as default base_url. |
rlm/clients/anthropic.py |
Adds dotenv/env fallbacks for api_key and base_url, and wires base_url into Anthropic SDK constructors. |
rlm/clients/gemini.py |
Reads GEMINI_API_BASE from env and conditionally forwards it through types.HttpOptions. |
.env.example |
Documents expected env vars for multiple backends (OpenAI/Anthropic/Gemini + others). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| base_url: str | None = None, | ||
| max_tokens: int = 32768, |
There was a problem hiding this comment.
Fixed — moved base_url after max_tokens to preserve positional argument order.
| # Fall back to ANTHROPIC_BASE_URL env var if base_url is not explicitly provided. | ||
| if base_url is None: | ||
| base_url = DEFAULT_ANTHROPIC_BASE_URL | ||
|
|
||
| client_kwargs = {"api_key": api_key, "timeout": self.timeout} |
There was a problem hiding this comment.
Unit tests for this exact behavior were added in tests/clients/test_base_url_env_vars.py. Specifically, TestAnthropicClientEnvVars::test_base_url_from_env patches DEFAULT_ANTHROPIC_BASE_URL and asserts the value is forwarded to the anthropic.Anthropic constructor, and test_base_url_not_passed_when_env_not_set covers the case where the env var is unset.
| if base_url is None: | ||
| base_url = DEFAULT_OPENAI_API_BASE |
There was a problem hiding this comment.
Addressed — tests/clients/test_base_url_env_vars.py covers this. Specifically, TestOpenAIClientBaseUrl::test_base_url_from_env patches DEFAULT_OPENAI_API_BASE and asserts the value is forwarded to the openai.OpenAI constructor, test_explicit_base_url_overrides_env verifies an explicit argument takes precedence, and test_base_url_is_none_when_env_not_set covers the unset case.
| # Fall back to GEMINI_API_BASE env var if base_url is not explicitly provided. | ||
| if base_url is None: | ||
| base_url = DEFAULT_GEMINI_API_BASE | ||
|
|
||
| # Configure HTTP options with timeout |
There was a problem hiding this comment.
Addressed — tests/clients/test_base_url_env_vars.py covers this. Specifically, TestGeminiClientBaseUrl::test_base_url_from_env patches DEFAULT_GEMINI_API_BASE and types.HttpOptions and asserts the expected base_url is passed to HttpOptions, test_explicit_base_url_overrides_env verifies an explicit argument takes precedence over the env var, and test_base_url_absent_when_env_not_set covers the unset case.
…pic, and Gemini clients
…ckward compatibility
There was a problem hiding this comment.
Pull request overview
Adds automatic environment-variable fallbacks for configuring client base URLs (and for Anthropic, API key), enabling organizations to route OpenAI/Anthropic/Gemini traffic through gateways/proxies without requiring explicit base_url arguments in code.
Changes:
- Add
OPENAI_API_BASE,ANTHROPIC_BASE_URL, andGEMINI_API_BASEenv-var fallbacks in the respective clients. - Add
ANTHROPIC_API_KEYenv-var fallback and validation inAnthropicClient. - Add a consolidated
.env.exampleplus new unit tests covering the fallback behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
rlm/clients/openai.py |
Loads OPENAI_API_BASE and uses it when base_url isn’t provided. |
rlm/clients/anthropic.py |
Loads ANTHROPIC_API_KEY / ANTHROPIC_BASE_URL, adds fallbacks + error on missing key. |
rlm/clients/gemini.py |
Loads GEMINI_API_BASE and passes it into HttpOptions when provided. |
tests/clients/test_base_url_env_vars.py |
New unit tests validating env-var fallback and precedence behavior. |
.env.example |
Documents supported environment variables across backends. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| """ | ||
|
|
||
| import os | ||
| from unittest.mock import MagicMock, patch |
| with patch("rlm.clients.openai.DEFAULT_OPENAI_API_BASE", "https://my-org.example.com/v1"): | ||
| client = OpenAIClient(api_key="test-key") | ||
|
|
|
|
||
| client = OpenAIClient(api_key="test-key", base_url="https://explicit.example.com/v1") | ||
|
|
|
|
||
| client = OpenAIClient(api_key="test-key") | ||
|
|
| from rlm.clients.anthropic import AnthropicClient | ||
|
|
||
| client = AnthropicClient() | ||
|
|
| from rlm.clients.gemini import GeminiClient | ||
|
|
||
| client = GeminiClient(api_key="test-key", base_url="https://explicit.example.com") | ||
|
|
| ): | ||
| from rlm.clients.gemini import GeminiClient | ||
|
|
||
| client = GeminiClient(api_key="test-key") |
| from rlm.clients.anthropic import AnthropicClient | ||
|
|
||
| client = AnthropicClient() | ||
|
|
| from rlm.clients.anthropic import AnthropicClient | ||
|
|
||
| client = AnthropicClient() | ||
|
|
| from rlm.clients.gemini import GeminiClient | ||
|
|
||
| client = GeminiClient(api_key="test-key") | ||
|
|
There was a problem hiding this comment.
Fixed — renamed unused client assignments to _ across all three test classes.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
rlm/clients/openai.py:47
- When
OPENAI_API_BASEis set to a custom gateway/proxy URL andapi_keyis omitted,api_keyremainsNonebecause the env-key fallback only triggers for the default OpenAI base URL (or a few hard-coded provider URLs). This undermines the intended “API key env var fallback” behavior and can lead to an unauthenticated client (depending on SDK behavior). Consider defaulting toDEFAULT_OPENAI_API_KEYfor any unrecognizedbase_url(only overriding it for known providers like OpenRouter/Vercel/Prime), and add a unit test coveringOPENAI_API_BASE+ omittedapi_keyto ensure the OpenAI key is still forwarded.
# Fall back to OPENAI_API_BASE env var if base_url is not explicitly provided.
if base_url is None:
base_url = DEFAULT_OPENAI_API_BASE
if api_key is None:
if base_url == "https://api.openai.com/v1" or base_url is None:
api_key = DEFAULT_OPENAI_API_KEY
elif base_url == "https://openrouter.ai/api/v1":
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Addressed the suppressed concern from the "Pull request overview" regarding OPENAI_API_BASE + omitted api_key. Added an else branch in OpenAIClient.init that falls back to DEFAULT_OPENAI_API_KEY for any unrecognized base URL, ensuring custom gateways set via OPENAI_API_BASE are not left unauthenticated. Covered by the new test_openai_api_key_used_for_custom_base_url test. |
Many organisations route API calls through a custom gateway or proxy
(e.g. using OPENAI_API_BASE). Currently these env vars are silently
ignored unless base_url is passed explicitly in code.
This PR adds automatic fallback support in all three main clients:
OPENAI_API_BASE→ OpenAI clientANTHROPIC_BASE_URL→ Anthropic clientGEMINI_API_BASE→ Gemini clientAlso adds
.env.exampledocumenting all supported environment variablesacross every backend.
No breaking changes — existing behaviour is preserved when env vars are unset.