Skip to content

Conversation

johanste
Copy link

  • I understand that this repository is auto-generated and my pull request may not be merged

Changes being requested

Make the api_key parameter accept a typing. Callable[[], str] (or typing.Callable[[], typing.Awaitable[str]] for the async client) to allow for dynamic token refresh.

Additional context & links

This is what the python_ad.py example would look like when using the base OpenAI clients + the bearer token provider.

import asyncio

from openai.lib.azure import OpenAI, AsyncOpenAI, AzureADTokenProvider, AsyncAzureADTokenProvider

scopes = "https://cognitiveservices.azure.com/.default"

# https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource
endpoint = "https://<your-custom-endpoint>.openai.azure.com/openai/v1"

deployment_name = "gpt-4o"  # e.g. gpt-35-instant


def sync_main() -> None:
    from azure.identity import DefaultAzureCredential, get_bearer_token_provider

    token_provider: AzureADTokenProvider = get_bearer_token_provider(DefaultAzureCredential(), scopes)

    client = OpenAI(
        base_url = endpoint,
        api_key = token_provider,
    )

    completion = client.chat.completions.create(
        model=deployment_name,
        messages=[
            {
                "role": "user",
                "content": "How do I output all files in a directory using Python?",
            }
        ],
    )

    print(completion.to_json())


async def async_main() -> None:
    from azure.identity.aio import DefaultAzureCredential, get_bearer_token_provider

    token_provider: AsyncAzureADTokenProvider = get_bearer_token_provider(DefaultAzureCredential(), scopes)

    client = AsyncOpenAI(
        api_key=token_provider,
        base_url=endpoint,
    )

    completion = await client.chat.completions.create(
        model=deployment_name,
        messages=[
            {
                "role": "user",
                "content": "How do I output all files in a directory using Python?",
            }
        ],
    )
    print(completion.to_json())


sync_main()

asyncio.run(async_main())

johanste and others added 6 commits August 26, 2025 12:29
…low bearer tokens to be updated

Allow api_key to be a callable to enable refresh of keys/tokens.
… Propagate bearer_token_provider in the `copy` method.
* add tests, fix copy, add token provider to module client

* fix lint

* ignore for azure copy

* revert change
@johanste johanste requested a review from a team as a code owner August 26, 2025 21:43
johanste and others added 2 commits August 27, 2025 14:54
@RobertCraigie RobertCraigie changed the title Add support for token refresh by accepting a callable api_key parameter value feat(client): support callable api_key Sep 2, 2025
Copy link
Collaborator

@RobertCraigie RobertCraigie left a comment

Choose a reason for hiding this comment

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

Look great!

def api_key(self) -> str | None:
return api_key
def api_key(self) -> str | _t.Callable[[], str] | None:
return api_key() if callable(api_key) else api_key
Copy link
Collaborator

Choose a reason for hiding this comment

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

This feels like it could be brittle and cause some weird behaviour if we access self.api_key in multiple places for the same request.

My gut is that we could just not support callable api keys for the module client?

Copy link
Contributor

Choose a reason for hiding this comment

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

Discussed with @johanste offline and agreed we can remove callable api keys for the module level client.

Copy link
Collaborator

@RobertCraigie RobertCraigie left a comment

Choose a reason for hiding this comment

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

Looks great thank you!

@RobertCraigie RobertCraigie changed the base branch from main to next September 3, 2025 15:51
@RobertCraigie RobertCraigie merged commit e1bad01 into openai:next Sep 3, 2025
4 of 5 checks passed
@stainless-app stainless-app bot mentioned this pull request Sep 3, 2025
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