microsoft/semantic-kernel · error · ServiceInitializationError
No API key or Azure AD token available for ephemeral token r
Error message
No API key or Azure AD token available for ephemeral token request.
What it means
Raised by AzureRealtimeWebRTC._get_ephemeral_token_headers_and_url(). This method builds the auth headers for the ephemeral token request to the Azure Realtime client_secrets endpoint. It checks self.client.api_key (must be set and not the '<missing API key>' sentinel) and self.client._azure_ad_token (must be non-None). If neither is available, there is no credential to attach to the request. Notably, this method does NOT check for ad_token_provider — only static api_key and static ad_token are supported for ephemeral token retrieval.
Source
Thrown at python/semantic_kernel/connectors/ai/open_ai/services/azure_realtime.py:340
url = f"{endpoint}/openai/v1/realtime/client_secrets"
if self.client.api_key and self.client.api_key != "<missing API key>":
return (
{
"api-key": self.client.api_key,
"Content-Type": "application/json",
},
url,
)
if self.client._azure_ad_token is not None: # type: ignore[attr-defined]
return (
{
"Authorization": f"Bearer {self.client._azure_ad_token}", # type: ignore[attr-defined]
"Content-Type": "application/json",
},
url,
)
raise ServiceInitializationError("No API key or Azure AD token available for ephemeral token request.")
@override
async def _get_ephemeral_token(self) -> str:
"""Get an ephemeral token from Azure OpenAI.
Azure GA requires a nested session object:
{"session": {"type": "realtime", "model": "<deployment>"}}
And returns the token directly as {"value": "..."} rather than
OpenAI's {"client_secret": {"value": "..."}}.
See: https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/realtime-audio-webrtc
"""
data = {
"session": {
"type": "realtime",
"model": self.ai_model_id,
}
}
headers, url = self._get_ephemeral_token_headers_and_url()View on GitHub (pinned to c028a0c7dc)
Solutions
- Provide an api_key when constructing AzureRealtimeWebRTC — the ephemeral token endpoint accepts key-based auth.
- Provide a static ad_token (pre-fetched Azure AD token string) instead of only an ad_token_provider.
- If you must use a token provider, pre-resolve the token yourself and pass it as ad_token=<resolved_token>.
- If using a pre-built client, ensure it was constructed with api_key= or azure_ad_token= (not just azure_ad_token_provider=).
Example fix
# before (token provider only — ephemeral token path cannot use it)
service = AzureRealtimeWebRTC(
audio_track=my_track,
endpoint='https://myresource.openai.azure.com',
deployment_name='gpt-4o-realtime',
ad_token_provider=my_provider_func, # no static key or token
)
# after (pass api_key for ephemeral token auth)
service = AzureRealtimeWebRTC(
audio_track=my_track,
endpoint='https://myresource.openai.azure.com',
deployment_name='gpt-4o-realtime',
api_key=os.environ['AZURE_OPENAI_API_KEY'],
) Defensive patterns
Strategy: validation
Validate before calling
def validate_webrtc_auth(api_key, ad_token, ad_token_provider, async_client):
"""The AzureRealtimeWebRTC ephemeral token path only supports static api_key or static ad_token.
An ad_token_provider alone is not sufficient for the ephemeral token request."""
if async_client is not None:
# Client handles its own auth — but verify it has a key or static token
return
if not api_key and not ad_token:
if ad_token_provider:
raise ValueError(
'AzureRealtimeWebRTC ephemeral token endpoint requires api_key or static ad_token. '
'An ad_token_provider alone is not supported. Pre-resolve the token and pass as ad_token.'
)
raise ValueError('api_key or ad_token is required for AzureRealtimeWebRTC')
validate_webrtc_auth(api_key, ad_token, ad_token_provider, async_client) Try / catch
from semantic_kernel.exceptions.service_exceptions import ServiceInitializationError
try:
token = await service._get_ephemeral_token()
except ServiceInitializationError as e:
if 'No API key or Azure AD token' in str(e):
# Reconstruct the service with api_key or a pre-resolved ad_token
print('WebRTC ephemeral token requires static api_key or ad_token, not a provider.')
raise Prevention
- Pass api_key when using AzureRealtimeWebRTC — the ephemeral token path checks static credentials only.
- If using Entra ID, pre-resolve the token with get_entra_auth_token() and pass it as ad_token=.
- Avoid relying solely on ad_token_provider for WebRTC realtime.
- If passing a pre-built client, ensure it has api_key= or azure_ad_token= set (not just azure_ad_token_provider=).
When it happens
Trigger: Constructing AzureRealtimeWebRTC with only an ad_token_provider (no static api_key, no static ad_token). The AsyncAzureOpenAI client is configured with a callable token provider, so client.api_key is unset and client._azure_ad_token is None at the time this method runs. Also possible if a pre-built async_client was passed that has neither a key nor a static token.
Common situations: Using Azure managed identity (DefaultAzureCredential with a token provider callback) for WebRTC realtime; passing a bare AsyncAzureOpenAI client built elsewhere that relies on a provider; migrating from key-based auth to Entra ID auth and forgetting that the WebRTC ephemeral-token path only checks static credentials.
Related errors
- Failed to get ephemeral token: {error_text}
- OpenAI/Azure OpenAI configuration was not found.
- Failed to receive audio frame
- Please provide either an api_key, ad_token, ad_token_provide
- Session is required for SessionUpdateEvent
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/1a777155f61005fd.
Report an issue: GitHub.