Providers

OpenAI voice and speech

Voice and speech

Speech synthesis (TTS)

The bundled openai plugin registers speech synthesis for the tts surface.

Setting Config path Default
Model tts.providers.openai.model gpt-4o-mini-tts
Voice tts.providers.openai.speakerVoice coral
Speed tts.providers.openai.speed (unset)
Instructions tts.providers.openai.instructions (unset, gpt-4o-mini-tts family only)
Format tts.providers.openai.responseFormat opus for voice notes, mp3 for files
API key tts.providers.openai.apiKey Falls back to OPENAI_API_KEY
Base URL tts.providers.openai.baseUrl https://api.openai.com/v1
Extra body tts.providers.openai.extraBody / extra_body (unset)

Available models: gpt-4o-mini-tts, gpt-4o-mini-tts-2025-12-15, tts-1, tts-1-hd. Available voices: alloy, ash, ballad, cedar, coral, echo, fable, juniper, marin, onyx, nova, sage, shimmer, verse.

extraBody is merged into /audio/speech request JSON after OpenClaw's generated fields, so use it for OpenAI-compatible endpoints that require additional keys such as lang. Prototype keys are ignored.

json5
{  tts: {    providers: {      openai: { model: "gpt-4o-mini-tts", speakerVoice: "coral" },    },  },}
Speech-to-text

The bundled openai plugin registers batch speech-to-text through OpenClaw's media-understanding transcription surface.

Batch transcription can use the selected OpenAI API-key or ChatGPT OAuth profile on the standard transcription endpoint when the account permits it. Configured models, prompts, and language hints work through the same request path. Access and quota errors are reported without switching credential classes; OAuth support does not imply included or unlimited transcription. Custom endpoints and request overrides require an API-key profile. See Audio and voice notes for selecting a separate audio API-key profile when desired.

  • Default model: gpt-4o-transcribe
  • Endpoint: OpenAI REST /v1/audio/transcriptions
  • Input path: multipart audio file upload
  • Used wherever inbound audio transcription reads tools.media.audio, including Discord voice-channel segments and channel audio attachments

To force OpenAI for inbound audio transcription:

json5
{  tools: {    media: {      models: [        {          type: "provider",          provider: "openai",          model: "gpt-4o-transcribe",          capabilities: ["audio"],        },      ],      audio: {        enabled: true,      },    },  },}

Language and prompt hints are forwarded to OpenAI when supplied by the shared audio media config or per-call transcription request.

Realtime transcription

The bundled openai plugin registers realtime transcription for the Voice Call plugin.

Setting Config path Default
Model plugins.entries.voice-call.config.streaming.providers.openai.model gpt-4o-transcribe
Language ...openai.language (unset)
Prompt ...openai.prompt (unset)
Silence duration ...openai.silenceDurationMs 800
VAD threshold ...openai.vadThreshold 0.5
Auth ...openai.apiKey, OPENAI_API_KEY, or openai API-key profile Platform API key required
Realtime voice

The bundled openai plugin registers realtime voice for the Voice Call plugin.

Setting Config path Default
Model plugins.entries.voice-call.config.realtime.providers.openai.model gpt-realtime-2.1
Voice ...openai.voice alloy
Temperature (Azure deployment bridge) ...openai.temperature 0.8
VAD threshold ...openai.vadThreshold 0.5
Silence duration ...openai.silenceDurationMs 500
Prefix padding ...openai.prefixPaddingMs 300
Reasoning effort ...openai.reasoningEffort (unset)
Auth openai auth profile, ...openai.apiKey, or OPENAI_API_KEY Released GPT-Live: OAuth first; ordinary GA browser: Platform first; Platform required for other routes

Available built-in Realtime voices for gpt-realtime-2.1: alloy, ash, ballad, coral, echo, sage, shimmer, verse, marin, cedar. OpenAI recommends marin and cedar for the best Realtime quality. This is a separate set from the Text-to-speech voices above; a TTS-only voice such as fable, nova, or onyx is not valid for Realtime sessions. Set the model explicitly to gpt-realtime-2.1-mini when you prefer the smaller, lower-cost Realtime 2.1 variant.

Gateway-controlled Realtime call cleanup

Closing a Gateway-controlled GA Realtime WebRTC session retires its Gateway authority and closes the local sideband before asking OpenAI to hang up the provider call. These are separate events; control closure does not establish provider acknowledgment or recall already queued media.

If hangup fails, explicit cancellation or cleanup reports the failure. The broker retries automatically after 1 second, then 5 seconds, with the existing 30-second timeout for each attempt. After all three attempts fail, the log reports cleanup INCOMPLETE. The exact cleanup obligation and its capacity remain reserved, including across plugin replacement: eight sessions globally and two per Gateway client. Restore provider connectivity; a later OpenAI broker/plugin runtime cleanup can retry these retained calls. Repeating End or talk.client.close is not that retry boundary because the Gateway session may already be retired.

Cleanup obligations are in memory only. Gateway exit, crash, or restart can lose them; restarting is not proof that the provider call ended. The adapter's 30-minute active-session lease is not a remote-lifetime guarantee or a fallback after failed hangup.

GA Realtime browser authentication

Ordinary GA browser Talk tries Platform auth first in this order: the configured realtime key, an openai API-key profile, then OPENAI_API_KEY. When a Platform credential is available, the Gateway mints an ephemeral client secret and the browser performs the SDP exchange directly.

When no Platform credential source is configured, ordinary GA browser Talk falls back to the OpenClaw ChatGPT OAuth subscription profile. The single-use Gateway offer broker keeps OAuth server-side, exchanges the browser's SDP, and returns only the answer SDP. An explicitly configured but unavailable Platform credential fails instead of falling back to OAuth.

Gateway-controlled GA relay, iOS client-owned WebRTC, Voice Call, direct backend sockets, and Discord realtime voice require Platform auth.

Released GPT-Live browser and Gateway relay authentication

Released GPT-Live browser and Gateway-relay WebRTC try the OpenClaw ChatGPT OAuth subscription profile first. When OAuth is unavailable, the Gateway falls back to Platform auth in this order: the configured realtime key, an openai API-key profile, then OPENAI_API_KEY. Create the OAuth profile with openclaw models auth login --provider openai.

Both credential types stay in the Gateway. The single-use offer broker exchanges the browser's SDP and returns only the answer SDP; it does not send an OAuth token, Platform key, or ephemeral client secret to the browser.

Gateway-relay WebRTC calls conceal malformed incoming audio packets and continue playing later audio. One rejected audio packet send does not end an otherwise connected call. Unusable codec state, unexpected stream changes, and terminal connection states still end the call. Packet-drop diagnostics omit raw error details.

The enabled OpenAI plugin starts the broker automatically, including when you sign in after the Gateway has started. The broker opens a provider session only when you start Talk; signing in does not open the microphone or start a voice session. Returning to the browser after sign-in refreshes the chat microphone's readiness.

Unlisted and private realtime transport paths

Unlisted or private browser Talk uses Platform-key client WebRTC with Gateway-owned control. Gateway relay and other direct backend consumers use the Platform-key bidirectional transport. Credentials and provider control remain on the Gateway.

Use the account-issued realtime model value. Unlisted model values are accepted as free-form Talk config but are not published through catalogs or diagnostics. Opt in explicitly with talk.realtime.model; the released model remains the default.

Current Platform-key sessions accept marin and cedar. OpenClaw defaults to marin and maps unsupported configured voices back to it.

Unlisted or private browser WebRTC prerequisites, in order:

  1. A Platform API key configured through talk.realtime.providers.openai.apiKey, an openai API-key profile, or OPENAI_API_KEY.
  2. talk.realtime.model set to the account-issued value — via Settings → Talk in the Control UI or the config below.
  3. The bundled openai plugin registered in full mode. A restrictive plugins.allow list fails with "OpenAI realtime browser session broker is unavailable".
json5
{  talk: {    realtime: {      provider: "openai",      model: "<account-issued-realtime-model>",      transport: "webrtc",    },  },}

Gateway relay uses the direct bidirectional transport:

json5
{  talk: {    realtime: {      provider: "openai",      model: "<account-issued-realtime-model>",      transport: "gateway-relay",    },  },}

Browser Talk uses transport: "webrtc".

Consumer Unlisted/private route status
Browser Talk Supported with Platform-key client WebRTC and Gateway-owned sideband
Gateway-relay Talk Supported with direct Platform-key transport
Discord bidirectional voice Supported with the Platform-key backend WebSocket
Voice Call and telephony Supported with the Platform-key backend WebSocket
iOS client-owned Talk Implemented; device live verification pending
Android realtime Talk Pending an Android device live-proof flip; Android stays on native Talk

These rows describe implemented transports, not account entitlement or complete model capability parity. See the Discord voice policy limits and Voice Call tool limits before selecting an unlisted or private route for those consumers.

A 403 Voice session access denied response is overloaded and does not by itself prove an account entitlement problem: an invalid voice produces the same response. First verify the model and voice against the accepted lists above, then verify the Platform key and configured model against the same project.

The released Gateway-owned WebRTC route uses OAuth first with Platform fallback, routes sideband delegations through the configured OpenClaw agent, and keeps credentials away from relay clients. Unlisted or private browser WebRTC and the direct backend socket remain Platform-only. The direct socket enables Discord voice and Voice Call/telephony; OpenClaw converts G.711 u-law telephony audio to and from the provider's 24 kHz PCM stream. Android's client-side gate stays closed until the Gateway relay path has live proof from an Android device.

The WebRTC path creates a provider call and joins its sideband. The direct backend path opens one bidirectional session, sends a Frameless session.update, then carries PCM audio, transcripts, delegations, and delegation results over that socket.

Maintainers can exercise the Platform direct path and the separate GA browser OAuth path with the opt-in live tests. The account-issued realtime model is read from talk.realtime.model; missing credentials or model config produce sanitized skips, and the tests never print either value:

bash
OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_GPT_LIVE=1 node --import tsx scripts/test-live.mts -- extensions/openai/realtime-quicksilver.live.test.tsOPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_GPT_LIVE=1 node --import tsx scripts/test-live.mts -- extensions/openai/realtime-quicksilver-gateway-bridge.live.test.ts
Was this useful?
On this page

On this page