Azure AI Voicelive Py
MicrosoftOfficialCreated by Microsoft
- Skill
- Tool integration
- Software development
- MIT
- Low risk
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The azure-ai-voicelive-py skill provides a Python SDK to facilitate bidirectional WebSocket communication with Azure AI models. It enables developers to integrate voice capabilities into applications, supporting features such as voice assistants, chatbots, speech-to-speech translation, and voice-driven avatars. The SDK includes tools for managing audio buffers, configuring session parameters, handling function calls, and processing real-time events.
What it does
- Establishes bidirectional WebSocket connections for audio streaming.
- Supports Server VAD and manual turn-based conversation control.
- Enables function calling and integration with MCP tools.
- Provides mechanisms for real-time transcription and audio output.
- Offers configuration for various voice models and audio formats.
- Facilitates integration with voice-driven avatars.
When to use it
- When building Python applications that require real-time voice interaction.
- When implementing voice-enabled chatbots or virtual assistants.
- When developing systems requiring speech-to-speech translation.
- When integrating voice-driven avatars into software projects.
Advantages
- Native support for asynchronous Python patterns.
- Flexible authentication options including Entra ID integration.
- Comprehensive event handling for session and audio management.
- Granular control over audio input and output buffers.
Usage examples
- “How do I initialize a connection to the Azure AI Voice Live service?”
- The user receives a code snippet demonstrating the use of the connect() function within an async context manager, including the required endpoint and credential configuration.
- “Show me how to configure a voice assistant with a custom function tool.”
- The user receives an example of using the session.update() method to define a FunctionTool, including its name, description, and parameter schema.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/microsoft/azure-ai-voicelive-py/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip azure-ai-voicelive-py.zip -d .agents/skills
Documentation by Microsoft
Azure AI Voice Live SDK
Build real-time voice AI applications with bidirectional WebSocket communication.
Installation
pip install azure-ai-voicelive aiohttp azure-identityEnvironment Variables
AZURE_COGNITIVE_SERVICES_ENDPOINT=https://<region>.api.cognitive.microsoft.com # Required for all auth methods
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
AZURE_COGNITIVE_SERVICES_KEY=<api-key> # Only required for the legacy API-key auth path belowAuthentication & Lifecycle
🔑 Two rules apply to every code sample below:
Prefer
DefaultAzureCredential. It works locally (Azure CLI / VS Code / Developer CLI) and in Azure (managed identity, workload identity) with no code change. Avoid connection strings, account/API keys — they bypass Entra audit and rotation.
Local dev:
DefaultAzureCredentialworks as-is.Production: set
AZURE_TOKEN_CREDENTIALS=prod(orAZURE_TOKEN_CREDENTIALS=<specific_credential>) to constrain the credential chain to production-safe credentials.Wrap every client in a context manager so HTTP transports, sockets, and token caches are released deterministically:
Sync:
with <Client>(...) as client:Async:
async with <Client>(...) as client:andasync with DefaultAzureCredential() as credential:(fromazure.identity.aio)Snippets may abbreviate this setup, but production code should always follow both rules.
import os
from azure.ai.voicelive.aio import connect
from azure.identity.aio import DefaultAzureCredential, ManagedIdentityCredential
# Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
# Or use a specific credential directly in production:
# See https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python#credential-classes
# credential = ManagedIdentityCredential()
async with DefaultAzureCredential(require_envvar=True) as credential:
async with connect(
endpoint=os.environ["AZURE_COGNITIVE_SERVICES_ENDPOINT"],
credential=credential,
model="gpt-4o-realtime-preview",
credential_scopes=["https://cognitiveservices.azure.com/.default"]
) as conn:
...Legacy: API Key (existing keyed deployments)
New code should use DefaultAzureCredential above. Use AzureKeyCredential only if you have an existing keyed deployment that hasn't been migrated to Entra ID yet — for example, regulated environments still completing their Entra rollout.
import os
from azure.core.credentials import AzureKeyCredential
from azure.ai.voicelive.aio import connect
async with connect(
endpoint=os.environ["AZURE_COGNITIVE_SERVICES_ENDPOINT"],
credential=AzureKeyCredential(os.environ["AZURE_COGNITIVE_SERVICES_KEY"]),
model="gpt-4o-realtime-preview",
) as conn:
...Quick Start
import asyncio
import os
from azure.ai.voicelive.aio import connect
from azure.identity.aio import DefaultAzureCredential
async def main():
async with connect(
endpoint=os.environ["AZURE_COGNITIVE_SERVICES_ENDPOINT"],
credential=DefaultAzureCredential(),
model="gpt-4o-realtime-preview",
credential_scopes=["https://cognitiveservices.azure.com/.default"]
) as conn:
# Update session with instructions
await conn.session.update(session={
"instructions": "You are a helpful assistant.",
"modalities": ["text", "audio"],
"voice": "alloy"
})
# Listen for events
async for event in conn:
print(f"Event: {event.type}")
if event.type == "response.audio_transcript.done":
print(f"Transcript: {event.transcript}")
elif event.type == "response.done":
break
asyncio.run(main())Core Architecture
Connection Resources
The VoiceLiveConnection exposes these resources:
| Resource | Purpose | Key Methods |
|---|---|---|
conn.session | Session configuration | update(session=...) |
conn.response | Model responses | create(), cancel() |
conn.input_audio_buffer | Audio input | append(), commit(), clear() |
conn.output_audio_buffer | Audio output | clear() |
conn.conversation | Conversation state | item.create(), item.delete(), item.truncate() |
conn.transcription_session | Transcription config | update(session=...) |
Session Configuration
from azure.ai.voicelive.models import RequestSession, FunctionTool
await conn.session.update(session=RequestSession(
instructions="You are a helpful voice assistant.",
modalities=["text", "audio"],
voice="alloy", # or "echo", "shimmer", "sage", etc.
input_audio_format="pcm16",
output_audio_format="pcm16",
turn_detection={
"type": "server_vad",
"threshold": 0.5,
"prefix_padding_ms": 300,
"silence_duration_ms": 500
},
tools=[
FunctionTool(
type="function",
name="get_weather",
description="Get current weather",
parameters={
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
)
]
))Audio Streaming
Send Audio (Base64 PCM16)
import base64
# Read audio chunk (16-bit PCM, 24kHz mono)
audio_chunk = await read_audio_from_microphone()
b64_audio = base64.b64encode(audio_chunk).decode()
await conn.input_audio_buffer.append(audio=b64_audio)Receive Audio
async for event in conn:
if event.type == "response.audio.delta":
audio_bytes = base64.b64decode(event.delta)
await play_audio(audio_bytes)
elif event.type == "response.audio.done":
print("Audio complete")Event Handling
async for event in conn:
match event.type:
# Session events
case "session.created":
print(f"Session: {event.session}")
case "session.updated":
print("Session updated")
# Audio input events
case "input_audio_buffer.speech_started":
print(f"Speech started at {event.audio_start_ms}ms")
case "input_audio_buffer.speech_stopped":
print(f"Speech stopped at {event.audio_end_ms}ms")
# Transcription events
case "conversation.item.input_audio_transcription.completed":
print(f"User said: {event.transcript}")
case "conversation.item.input_audio_transcription.delta":
print(f"Partial: {event.delta}")
# Response events
case "response.created":
print(f"Response started: {event.response.id}")
case "response.audio_transcript.delta":
print(event.delta, end="", flush=True)
case "response.audio.delta":
audio = base64.b64decode(event.delta)
case "response.done":
print(f"Response complete: {event.response.status}")
# Function calls
case "response.function_call_arguments.done":
result = handle_function(event.name, event.arguments)
await conn.conversation.item.create(item={
"type": "function_call_output",
"call_id": event.call_id,
"output": json.dumps(result)
})
await conn.response.create()
# Errors
case "error":
print(f"Error: {event.error.message}")Common Patterns
Manual Turn Mode (No VAD)
await conn.session.update(session={"turn_detection": None})
# Manually control turns
await conn.input_audio_buffer.append(audio=b64_audio)
await conn.input_audio_buffer.commit() # End of user turn
await conn.response.create() # Trigger responseInterrupt Handling
async for event in conn:
if event.type == "input_audio_buffer.speech_started":
# User interrupted - cancel current response
await conn.response.cancel()
await conn.output_audio_buffer.clear()Conversation History
# Add system message
await conn.conversation.item.create(item={
"type": "message",
"role": "system",
"content": [{"type": "input_text", "text": "Be concise."}]
})
# Add user message
await conn.conversation.item.create(item={
"type": "message",
"role": "user",
"content": [{"type": "input_text", "text": "Hello!"}]
})
await conn.response.create()Voice Options
| Voice | Description |
|---|---|
alloy | Neutral, balanced |
echo | Warm, conversational |
shimmer | Clear, professional |
sage | Calm, authoritative |
coral | Friendly, upbeat |
ash | Deep, measured |
ballad | Expressive |
verse | Storytelling |
Azure voices: Use AzureStandardVoice, AzureCustomVoice, or AzurePersonalVoice models.
Audio Formats
| Format | Sample Rate | Use Case |
|---|---|---|
pcm16 | 24kHz | Default, high quality |
pcm16-8000hz | 8kHz | Telephony |
pcm16-16000hz | 16kHz | Voice assistants |
g711_ulaw | 8kHz | Telephony (US) |
g711_alaw | 8kHz | Telephony (EU) |
Turn Detection Options
# Server VAD (default)
{"type": "server_vad", "threshold": 0.5, "silence_duration_ms": 500}
# Azure Semantic VAD (smarter detection)
{"type": "azure_semantic_vad"}
{"type": "azure_semantic_vad_en"} # English optimized
{"type": "azure_semantic_vad_multilingual"}Error Handling
from azure.ai.voicelive.aio import ConnectionError, ConnectionClosed
try:
async with connect(...) as conn:
async for event in conn:
if event.type == "error":
print(f"API Error: {event.error.code} - {event.error.message}")
except ConnectionClosed as e:
print(f"Connection closed: {e.code} - {e.reason}")
except ConnectionError as e:
print(f"Connection error: {e}")Best Practices
This SDK is async-only; use the
.aionamespace throughout. Do not try to pair it with sync clients from other Azure SDKs in the same call path — keep the whole request path async.Always use context managers for clients and async credentials. Wrap every connection in
async with connect(...) as conn:. For asyncDefaultAzureCredentialfromazure.identity.aio, also useasync with credential:so tokens and transports are cleaned up.
References
Detailed API Reference: See references/api-reference.md
Complete Examples: See references/examples.md
All Models & Types: See references/models.md
Files
- ATTRIBUTION.mdAdded by AutoGineer974 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md11.3 KiB
- references/api-reference.md8.7 KiB
- references/examples.md16.9 KiB
- references/models.md18.0 KiB
references/api-reference.md
Azure AI Voice Live SDK - API Reference
Table of Contents
connect() Function
VoiceLiveConnection
SessionResource
ResponseResource
InputAudioBufferResource
OutputAudioBufferResource
ConversationResource
TranscriptionSessionResource
WebsocketConnectionOptions
Exceptions
connect() Function
Creates an async context manager for WebSocket connections.
from azure.ai.voicelive.aio import connect
async with connect(
credential: Union[AzureKeyCredential, AsyncTokenCredential],
endpoint: str,
api_version: str = "2025-10-01",
model: Optional[str] = None,
query: Optional[Mapping[str, Any]] = None,
headers: Optional[Mapping[str, Any]] = None,
connection_options: Optional[WebsocketConnectionOptions] = None,
credential_scopes: Optional[List[str]] = None,
**kwargs
) -> VoiceLiveConnection:
...Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
credential | AzureKeyCredential or AsyncTokenCredential | Yes | Authentication credential |
endpoint | str | Yes | Service endpoint URL |
api_version | str | No | API version (default: "2025-10-01") |
model | str | Sometimes | Model identifier (required unless using Agent scenario) |
query | Mapping[str, Any] | No | Additional URL query parameters |
headers | Mapping[str, Any] | No | Additional HTTP headers |
connection_options | WebsocketConnectionOptions | No | WebSocket transport options |
credential_scopes | List[str] | No | OAuth scopes (default: ["https://ai.azure.com/.default"]) |
VoiceLiveConnection
Main connection class with resource accessors.
Properties
| Property | Type | Description |
|---|---|---|
session | SessionResource | Session configuration |
response | ResponseResource | Response management |
input_audio_buffer | InputAudioBufferResource | Audio input buffer |
output_audio_buffer | OutputAudioBufferResource | Audio output buffer |
conversation | ConversationResource | Conversation items |
transcription_session | TranscriptionSessionResource | Transcription config |
Methods
async def recv() -> ServerEvent:
"""Receive and parse the next typed server event."""
async def recv_bytes() -> bytes:
"""Receive raw bytes from the connection."""
async def send(event: Union[Mapping[str, Any], ClientEvent]) -> None:
"""Send an event to the server."""
async def close(*, code: int = 1000, reason: str = "") -> None:
"""Close the WebSocket connection."""
async def __aiter__() -> AsyncIterator[ServerEvent]:
"""Iterate over server events until connection closes."""SessionResource
Manage session configuration.
Methods
async def update(
*,
session: Union[Mapping[str, Any], RequestSession],
event_id: Optional[str] = None
) -> None:
"""Update session configuration."""RequestSession Fields
| Field | Type | Description |
|---|---|---|
instructions | str | System prompt for the model |
modalities | List[Modality] | ["text"], ["audio"], or ["text", "audio"] |
voice | Voice | Voice for audio output |
input_audio_format | InputAudioFormat | Audio input format |
output_audio_format | OutputAudioFormat | Audio output format |
turn_detection | TurnDetection | VAD configuration or None for manual |
tools | List[Tool] | Function tools |
tool_choice | ToolChoice | "auto", "none", "required", or specific function |
temperature | float | Model temperature (0.6-1.2) |
max_response_output_tokens | int or "inf" | Max tokens per response |
input_audio_transcription | AudioInputTranscriptionOptions | Transcription settings |
ResponseResource
Manage model responses.
Methods
async def create(
*,
response: Optional[Union[ResponseCreateParams, Mapping[str, Any]]] = None,
event_id: Optional[str] = None,
additional_instructions: Optional[str] = None
) -> None:
"""Create a response (trigger inference)."""
async def cancel(
*,
response_id: Optional[str] = None,
event_id: Optional[str] = None
) -> None:
"""Cancel an in-progress response."""ResponseCreateParams Fields
| Field | Type | Description |
|---|---|---|
modalities | List[Modality] | Override session modalities |
instructions | str | Override session instructions |
voice | Voice | Override session voice |
temperature | float | Override temperature |
max_response_output_tokens | int | Override max tokens |
conversation | str | "auto" or "none" |
InputAudioBufferResource
Manage audio input buffer.
Methods
async def append(
*,
audio: str, # Base64-encoded audio
event_id: Optional[str] = None
) -> None:
"""Append audio data to the input buffer."""
async def commit(
*,
event_id: Optional[str] = None
) -> None:
"""Commit the buffer as a user message."""
async def clear(
*,
event_id: Optional[str] = None
) -> None:
"""Clear the input buffer without committing."""OutputAudioBufferResource
Manage audio output buffer.
Methods
async def clear(
*,
event_id: Optional[str] = None
) -> None:
"""Clear pending audio output (for interrupts)."""ConversationResource
Manage conversation state.
Properties
| Property | Type | Description |
|---|---|---|
item | ConversationItemResource | Item operations |
ConversationItemResource
CRUD operations on conversation items.
Methods
async def create(
*,
item: Union[ConversationRequestItem, Mapping[str, Any]],
previous_item_id: Optional[str] = None,
event_id: Optional[str] = None
) -> None:
"""Create a new conversation item."""
async def delete(
*,
item_id: str,
event_id: Optional[str] = None
) -> None:
"""Delete a conversation item."""
async def retrieve(
*,
item_id: str,
event_id: Optional[str] = None
) -> None:
"""Retrieve item details (server responds with event)."""
async def truncate(
*,
item_id: str,
audio_end_ms: int,
content_index: int,
event_id: Optional[str] = None
) -> None:
"""Truncate audio at specified time."""ConversationRequestItem Types
# User/Assistant/System message
{
"type": "message",
"role": "user" | "assistant" | "system",
"content": [
{"type": "input_text", "text": "..."},
{"type": "input_audio", "audio": "base64..."},
{"type": "text", "text": "..."},
{"type": "audio", "audio": "base64...", "transcript": "..."}
]
}
# Function call (from model)
{
"type": "function_call",
"call_id": "...",
"name": "function_name",
"arguments": "{...}"
}
# Function output (from client)
{
"type": "function_call_output",
"call_id": "...",
"output": "{...}"
}TranscriptionSessionResource
Configure input transcription.
Methods
async def update(
*,
session: Mapping[str, Any],
event_id: Optional[str] = None
) -> None:
"""Update transcription session configuration."""WebsocketConnectionOptions
Transport configuration for the WebSocket connection.
| Field | Type | Default | Description |
|---|---|---|---|
compression | bool or int | None | Enable per-message compression |
max_msg_size | int | 4MB | Maximum message size |
heartbeat | float | 30 | Keep-alive ping interval (seconds) |
autoclose | bool | True | Auto-close on close frame |
autoping | bool | True | Auto-respond to pings |
receive_timeout | float | None | Message receive timeout |
close_timeout | float | None | Close handshake timeout |
handshake_timeout | float | None | Connection establishment timeout |
vendor_options | Mapping | None | Implementation-specific options |
Exceptions
from azure.ai.voicelive.aio import ConnectionError, ConnectionClosed
class ConnectionError(AzureError):
"""Base WebSocket connection error."""
class ConnectionClosed(ConnectionError):
"""WebSocket connection was closed."""
code: int # Close code
reason: str # Close reasonCommon Close Codes
| Code | Meaning |
|---|---|
| 1000 | Normal closure |
| 1001 | Going away |
| 1006 | Abnormal closure |
| 1008 | Policy violation |
| 1011 | Server error |
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs an API key, Needs Python
Security
What our scanner noticed· Low risk
- Instructions that use the network
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Microsoft
- Publisher
- Microsoft (Official)
- Source
- microsoft/skills · .github/plugins/azure-sdk-python/skills/azure-ai-voicelive-py · commit 0696600
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Microsoft or Microsoft.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download azure-ai-voicelive-py.zip