microsoft/semantic-kernel · critical · ServiceInitializationError

Please provide either api_key, ad_token, ad_token_provider,

Error message

Please provide either api_key, ad_token, ad_token_provider, credential or a client.

What it means

The base Azure config builder requires at least one authentication mechanism to construct the underlying AsyncAzureOpenAI client. It checks for api_key, ad_token, ad_token_provider, or credential (or a pre-built client). If none are provided AND no client is passed, it raises ServiceInitializationError. This is the first guard in the config chain — it fires before endpoint/base_url validation.

Source

Thrown at python/semantic_kernel/connectors/ai/open_ai/services/azure_config_base.py:85

            credential: The credential to use for authentication. (Optional)
            kwargs: Additional keyword arguments.

        """
        # Merge APP_INFO into the headers if it exists
        merged_headers = dict(copy(default_headers)) if default_headers else {}
        if APP_INFO:
            merged_headers.update(APP_INFO)
            merged_headers = prepend_semantic_kernel_to_user_agent(merged_headers)

        if not client:
            # If the client is None, the api_key is none, the ad_token is none, and the ad_token_provider is none,
            # then we will attempt to get the ad_token using the default endpoint specified in the Azure OpenAI
            # settings.
            if not api_key and not ad_token_provider and not ad_token and token_endpoint and credential:
                ad_token = get_entra_auth_token(credential, token_endpoint)

            if not api_key and not ad_token and not ad_token_provider and not credential:
                raise ServiceInitializationError(
                    "Please provide either api_key, ad_token, ad_token_provider, credential or a client."
                )

            if not endpoint and not base_url:
                raise ServiceInitializationError("Please provide an endpoint or a base_url")

            args: dict[str, Any] = {
                "default_headers": merged_headers,
            }
            if api_version:
                args["api_version"] = api_version
            if ad_token:
                args["azure_ad_token"] = ad_token
            if ad_token_provider:
                args["azure_ad_token_provider"] = ad_token_provider
            if api_key:
                args["api_key"] = api_key
            if base_url:

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Set AZURE_OPENAI_API_KEY environment variable, or pass api_key='...' to the constructor.
  2. For managed identity: pass credential=DefaultAzureCredential() (and set token_endpoint if needed).
  3. For token-based auth: pass ad_token or ad_token_provider (a callable returning the token).
  4. Pass a pre-built AsyncAzureOpenAI client if you manage auth externally.

Example fix

// before
service = AzureChatCompletionService(
    deployment_name='gpt-4o',
    endpoint='https://my-resource.openai.azure.com/'
)  # no auth
// after
# Option 1: API key
service = AzureChatCompletionService(
    deployment_name='gpt-4o',
    endpoint='https://my-resource.openai.azure.com/',
    api_key=os.environ['AZURE_OPENAI_API_KEY']
)
# Option 2: Managed identity
from azure.identity import DefaultAzureCredential
service = AzureChatCompletionService(
    deployment_name='gpt-4o',
    endpoint='https://my-resource.openai.azure.com/',
    credential=DefaultAzureCredential()
)
Defensive patterns

Strategy: validation

Validate before calling

import os

def validate_azure_auth(api_key, ad_token, ad_token_provider, credential, client) -> None:
    if client:
        return  # pre-built client bypasses auth check
    if not any([api_key, ad_token, ad_token_provider, credential]):
        if not os.environ.get('AZURE_OPENAI_API_KEY'):
            raise ValueError(
                'No authentication provided. Pass api_key, ad_token, ad_token_provider, '
                'credential, or client — or set AZURE_OPENAI_API_KEY.'
            )

Type guard

def has_azure_auth(api_key, ad_token, ad_token_provider, credential, client) -> bool:
    import os
    return any([
        client, api_key, ad_token, ad_token_provider, credential,
        os.environ.get('AZURE_OPENAI_API_KEY')
    ])

Try / catch

from semantic_kernel.exceptions import ServiceInitializationError

try:
    service = AzureChatCompletionService(deployment_name=dep, endpoint=ep)
except ServiceInitializationError as e:
    if 'Please provide either' in str(e):
        service = AzureChatCompletionService(
            deployment_name=dep, endpoint=ep, api_key=os.environ['AZURE_OPENAI_API_KEY']
        )

Prevention

When it happens

Trigger: Constructing any Azure OpenAI service (chat, text, embedding, audio, realtime) without providing api_key, ad_token, ad_token_provider, credential, or client — and without corresponding AZURE_OPENAI_API_KEY env var. Also fires if token_endpoint is set but no credential is provided to obtain a token.

Common situations: Fresh setup where AZURE_OPENAI_API_KEY env var hasn't been set; using managed identity (credential) but forgetting to pass the credential object; .env file not loaded; typo in the env var name; switching from api_key auth to managed identity but removing the key without adding credential.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/4901d95545f8a9c6. Report an issue: GitHub.