Skip to content

xAI Grok Voice

XaiRealtimeModel brings Grok Voice into the typed, server-side realtime agent loop. Start with the realtime quickstart or the text-to-audio example.

Setup

To use Grok Voice, install pydantic-ai-slim with the xai-realtime optional group. Alongside xai-sdk, the bundle includes the openai package, because Grok Voice’s realtime API reuses the OpenAI Realtime protocol’s event types:

Terminal
pip install "pydantic-ai-slim[xai-realtime]"

Set XAI_API_KEY as described in the xAI model documentation. Use provider='xai' or pass an XaiProvider with api_key=. Custom api_host is unsupported, and a provider constructed with only xai_client= cannot open the WebSocket because the connection requires the API key.

Model names

Use a Grok Voice ID such as grok-voice-latest or a pinned grok-voice-think-* model. grok-voice-latest follows xAI’s current flagship and can change underneath an application; pin a version when behavior must remain stable. Use the official xAI voice documentation for the canonical model list.

Settings

XaiRealtimeModelSettings — the realtime counterpart of model run settings — extends the shared settings:

from pydantic_ai.realtime.xai import XaiRealtimeModel, XaiRealtimeModelSettings

settings = XaiRealtimeModelSettings(
    xai_voice='eve',
    turn_detection={'sensitivity': 'low'},
    input_transcription_model='auto',
)
model = XaiRealtimeModel('grok-voice-latest', settings=settings)

xai_voice selects the provider voice; when unset, xAI picks its own server-side default (currently eve). For an exact server-VAD threshold, prefix padding, or silence duration, set xai_turn_detection= with ServerVAD; it fully overrides shared turn_detection. xAI echoes create_response: False back but still responds when the user stops speaking, so use turn_detection=False for push-to-talk instead.

xAI accepts the shared max_tokens and parallel_tool_calls settings but ignores them: replies aren’t capped, and the model can still call several tools at once.

Input transcription defaults to 'auto'. Unlike the incremental deltas described in live captions, xAI sends cumulative transcript snapshots that can revise earlier words, so caption UIs should render the full TranscriptUpdate.transcript rather than append deltas.

Reasoning

grok-voice-latest and grok-voice-think-* models support the shared thinking setting. The provider exposes only 'high' and 'none': every enabled effort maps to 'high', while False maps to 'none'. Other Grok Voice models ignore the setting.

Feature support and limitations

FeatureSupportNotes
Audio formatLimited parameter supportMono PCM16 at 24 kHz by default, input and output; the other PCM rates xAI lists (8 to 48 kHz) by setting audio_input_sample_rate and audio_output_sample_rate through profile=. The API also offers G.711 and Opus, which Pydantic AI does not expose
Text outputUnsupportedGrok Voice always produces audio
Image inputUnsupportedGrok Voice doesn’t see images: xAI accepts an image item but ignores it, so send() rejects images with a UserError before sending
Manual turnsFull feature supportturn_detection=False plus commit/create verbs
InterruptionLimited parameter supportinterrupt() works, and played_bytes= also discards the unheard audio; played_ms raises, because xAI’s truncation is unreliable at barge-in
Input transcriptionFull feature supportDedicated provider path; 'auto' by default
Native toolsUnsupportedxAI offers web search, X search, file search, and MCP tools, which Pydantic AI does not expose yet; configure local fallbacks for web capabilities
Async tool callsFull feature supportGrok Voice keeps talking, and answers the user, while a tool runs
UsageFull feature supportAudio-token buckets and billable_audio_seconds in RunUsage.details
ReconnectionFull feature supportPydantic AI replays completed local history into a new conversation; in-flight media is lost

See Audio, images, and transcripts, Turns and interruptions, Tools, and Connection lifecycle for the provider-agnostic workflows.

Gateway

Grok Voice is not currently available through the Pydantic AI Gateway. Connect through provider='xai' or an XaiProvider.

Session length

A conversation that runs past xAI’s maximum duration ends with a max_duration error, and the session raises a RealtimeError instead of reconnecting.

Provider-specific quirks

  • Grok Voice always speaks: its profile reports supports_text_output=False, so output_modality='text' raises a UserError before connecting. Read the answer from the transcript on the SpeechPart.
  • xAI documents conversation.item.truncate and confirms it with conversation.item.truncated, but in our testing it only takes effect once the response has ended, and not reliably even then. Sent just before the cancel, as barge-in needs, it changes nothing, so the profile reports supports_output_truncation=False. interrupt(played_bytes=...) still discards the unheard audio and cancels the response, while a plain interrupt() only cancels. Either way xAI keeps everything generated up to the cancel, which can be more than the user heard.
  • The protocol resembles OpenAI Realtime, but feature support comes from the xAI model profile; avoid assuming every OpenAI behavior is available.