Skip to main content
The Voice API lets clients stream microphone audio to the gateway and let the gateway create a normal turn after transcription. Voice is not a second conversation model. A successful voice session becomes an ordinary turn/start flow owned by the gateway:
  1. The client starts a voice session with minimal routing context.
  2. The client streams microphone PCM chunks over the WebSocket binary channel.
  3. The client finalizes with frozen composer context.
  4. The gateway transcribes audio.
  5. The gateway prepends the transcript as UserInput::Text and starts the normal turn.
  6. Clients render the result from existing turn and timeline notifications.
Cancelled and no-speech sessions create no turn and no timeline user message.

Methods

MethodParamsResultPurpose
voice/statusVoiceStatusParamsVoiceStatusResponseRead gateway voice availability and active session state.
voice/session/startVoiceSessionStartParamsVoiceSessionStartResponseReserve a gateway voice session for one workspace/thread/turn context.
voice/session/finalizeVoiceSessionFinalizeParamsVoiceSessionFinalizeResponseCommit a session for transcription and turn materialization.
voice/session/cancelVoiceSessionCancelParamsVoiceSessionCancelResponseCancel a session without creating a turn.

Notifications

EventParamsMeaning
voice/chunk/ackVoiceChunkAckNotificationThe gateway accepted an audio chunk sequence for a session.
voice/session/resultVoiceSessionResultNotificationA voice session reached a terminal outcome.
voice/session/result does not carry transcript text. A successful transcript is visible through the normal turn/started, user-message, item, and timeline notifications for the created turn.

Status

voice/status can be scoped by workspace:
{
  "method": "voice/status",
  "params": {
    "workspace_id": "ws_000000000000000001"
  }
}
Response:
{
  "status": "ready",
  "active_session_id": null,
  "error": null
}
VoiceStatus values are:
StatusMeaning
unavailableVoice is unavailable for this gateway/workspace.
model_downloadingThe gateway is downloading the voice model.
model_loadingThe gateway is loading the voice model.
readyThe gateway can accept voice input.
busyThe gateway cannot accept another session right now.
recordingA session is receiving chunks.
transcribingA finalized session is being transcribed.
errorVoice is in an error state; inspect error.

Starting A Session

voice/session/start uses a minimal VoiceSessionStartContext so capture can begin without waiting for all non-audio composer preparation:
{
  "method": "voice/session/start",
  "params": {
    "context": {
      "workspace_id": "ws_000000000000000001",
      "thread_id": "thr_000000000000000001",
      "turn_id": "trn_000000000000000001"
    },
    "audio_format": {
      "sample_rate_hz": 16000,
      "channels": 1,
      "encoding": "pcm_s16le"
    }
  }
}
Response:
{
  "session_id": "voice_session_000000000000000001",
  "status": "recording"
}
The gateway validates that workspace_id, thread_id, and turn_id are present and that the audio format matches the streaming target.

Audio Format

The initial streaming contract is microphone PCM only:
FieldRequired value
encodingpcm_s16le
sample_rate_hz16000
channels1
Target chunk duration20 ms
Maximum chunk duration100 ms
Target chunk size640 bytes
Maximum chunk size3200 bytes
pcm_f32le is reserved in the enum for future adapters. The current streaming gateway contract accepts only pcm_s16le.

Binary Audio Chunks

Audio chunks are sent as WebSocket binary frames, not JSON-RPC requests. Each frame uses the VOC1 envelope:
4 bytes   magic: VOC1
4 bytes   big-endian JSON header length
N bytes   JSON VoiceChunkFrameHeader
M bytes   raw audio payload
VoiceChunkFrameHeader contains:
FieldMeaning
session_idGateway session id returned by voice/session/start.
sequenceMonotonic chunk sequence number.
sample_rate_hzMust be 16000.
channelsMust be 1.
encodingMust be pcm_s16le.
payload_lenRaw payload byte length.
captured_at_unix_msOptional capture timestamp.
duration_msOptional chunk duration.
The frame header must not carry workspace, thread, turn, attachments, capabilities, text input, or permission data. Non-audio context belongs to finalize. When a chunk is accepted, the gateway can publish:
{
  "method": "voice/chunk/ack",
  "params": {
    "session_id": "voice_session_000000000000000001",
    "sequence": 42
  }
}

Finalizing

Finalize commits the voice session and supplies the frozen non-audio composer context:
{
  "method": "voice/session/finalize",
  "params": {
    "session_id": "voice_session_000000000000000001",
    "context": {
      "workspace_id": "ws_000000000000000001",
      "thread_id": "thr_000000000000000001",
      "turn_id": "trn_000000000000000001",
      "prepared_input": [],
      "capabilities": [],
      "model": "gpt-5.5",
      "model_provider": "openai",
      "mode": "Agent",
      "permission_profile": {
        "mode": "supervised"
      }
    }
  }
}
VoiceTurnContext can carry the same non-audio turn material as a normal composer send: prepared attachments/artifact references, capabilities, model, provider, thread mode, execution backend, reasoning, permission profile, and CLI runtime options. It must not contain the future transcript. The gateway owns transcription and inserts the transcript when it starts the turn. Response:
{
  "status": "transcribing"
}
Clients should keep a finalizing UI until they receive voice/session/result.

Result

Terminal outcomes are:
OutcomeMeaning
turn_startedThe gateway transcribed speech and started the normal turn.
cancelledThe session was cancelled and no turn was created.
no_speechThe gateway found no speech and no turn was created.
failedTranscription or turn materialization failed.
Example:
{
  "method": "voice/session/result",
  "params": {
    "session_id": "voice_session_000000000000000001",
    "outcome": "turn_started",
    "turn_id": "trn_000000000000000001",
    "error": null
  }
}
For turn_started, clients should render the new work from normal turn notifications plus thread timeline-page and turn work-page APIs. For cancelled and no_speech, clear the voice composer state without creating a message.

Cancelling

{
  "method": "voice/session/cancel",
  "params": {
    "session_id": "voice_session_000000000000000001",
    "reason": "user_cancelled"
  }
}
Response:
{
  "cancelled": true
}
The gateway also publishes voice/session/result with outcome cancelled.

Permissions

Voice has two permission layers:
LayerOwnerMeaning
Platform microphone permissionClient OS/platformControls whether the client can capture microphone audio. No gateway turn exists before capture succeeds.
Pioneer agent permission profileGateway turnControls tools, filesystem, network, process policy, MCP, skills, computer use, and subagents for the eventual turn.
Do not map microphone permission prompts to turn/permission/request/respond. Agent permission prompts still use the normal turn permission API after the voice-created turn starts.

Generated Schemas

  • /schemas/voice_status.json
  • /schemas/voice_status_params.json
  • /schemas/voice_status_response.json
  • /schemas/voice_audio_encoding.json
  • /schemas/voice_audio_format.json
  • /schemas/voice_chunk_frame_header.json
  • /schemas/voice_chunk_ack_notification.json
  • /schemas/voice_error.json
  • /schemas/voice_error_kind.json
  • /schemas/voice_turn_context.json
  • /schemas/voice_session_start_context.json
  • /schemas/voice_session_start_params.json
  • /schemas/voice_session_start_response.json
  • /schemas/voice_session_finalize_params.json
  • /schemas/voice_session_finalize_response.json
  • /schemas/voice_session_cancel_params.json
  • /schemas/voice_session_cancel_response.json
  • /schemas/voice_session_outcome.json
  • /schemas/voice_session_result_notification.json
  • /schemas/client/prepare_voice_composer_snapshot_request.json
  • /schemas/client/prepared_voice_composer_snapshot.json
  • /schemas/client/voice_composer_lock_state.json
  • /schemas/client/voice_composer_snapshot_discard_reduction.json
  • /schemas/client/voice_finalize_response_reduction.json
  • /schemas/client/voice_finalize_ui_action.json
  • /schemas/client/voice_session_result_reduction.json
  • Turns API explains normal turn creation and permission profiles.
  • Client Architecture explains the shared Rust client core and mobile shell boundary.
  • Permission System explains agent permission profiles and turn sandbox/resource policy.