asyncapi: 3.1.0
info:
  title: Assistant Core Voice API
  version: 1.0.0-preview
  description: >-
    Canonical Preview WebSocket contract for standard and realtime voice. The
    short-lived token is delivered in session.start, never in a URL. With
    standard auto detection or realtime server_vad, open input once and stream
    continuously without input_audio.commit.
  contact:
    name: Assistant Core Support
    url: https://support.assistantcore.com
servers:
  production:
    host: api.assistantcore.com
    protocol: wss
    pathname: /v1/voice
channels:
  voice:
    address: /v1/voice
    messages:
      sessionStart: { $ref: "#/components/messages/sessionStart" }
      inputAudioStart: { $ref: "#/components/messages/inputAudioStart" }
      inputAudioCommit: { $ref: "#/components/messages/inputAudioCommit" }
      inputAudioAppend: { $ref: "#/components/messages/inputAudioAppend" }
      inputTextCreate: { $ref: "#/components/messages/inputTextCreate" }
      responseCancel: { $ref: "#/components/messages/responseCancel" }
      ping: { $ref: "#/components/messages/ping" }
      serverEvent: { $ref: "#/components/messages/serverEvent" }
      outputAudioFrame: { $ref: "#/components/messages/outputAudioFrame" }
operations:
  receiveClientEvent:
    {
      action: receive,
      channel: { $ref: "#/channels/voice" },
      messages:
        [
          { $ref: "#/channels/voice/messages/sessionStart" },
          { $ref: "#/channels/voice/messages/inputAudioStart" },
          { $ref: "#/channels/voice/messages/inputAudioCommit" },
          { $ref: "#/channels/voice/messages/inputAudioAppend" },
          { $ref: "#/channels/voice/messages/inputTextCreate" },
          { $ref: "#/channels/voice/messages/responseCancel" },
          { $ref: "#/channels/voice/messages/ping" },
        ],
    }
  sendServerEvent:
    {
      action: send,
      channel: { $ref: "#/channels/voice" },
      messages:
        [
          { $ref: "#/channels/voice/messages/serverEvent" },
          { $ref: "#/channels/voice/messages/outputAudioFrame" },
        ],
    }
components:
  messages:
    sessionStart: { payload: { $ref: "#/components/schemas/SessionStart" } }
    inputAudioStart:
      {
        payload:
          {
            type: object,
            required: [type],
            properties: { type: { const: input_audio.start } },
          },
      }
    inputAudioCommit:
      {
        payload:
          {
            type: object,
            required: [type],
            properties: { type: { const: input_audio.commit } },
          },
      }
    inputAudioAppend:
      {
        contentType: application/octet-stream,
        payload: { type: string, format: binary },
      }
    inputTextCreate:
      {
        payload:
          {
            type: object,
            required: [type, text],
            properties:
              {
                type: { const: input_text.create },
                text: { type: string, minLength: 1 },
              },
          },
      }
    responseCancel:
      {
        payload:
          {
            type: object,
            required: [type],
            properties: { type: { const: response.cancel } },
          },
      }
    ping:
      {
        payload:
          {
            type: object,
            required: [type],
            properties: { type: { const: ping } },
          },
      }
    serverEvent: { payload: { $ref: "#/components/schemas/ServerEvent" } }
    outputAudioFrame:
      {
        contentType: application/octet-stream,
        payload: { type: string, format: binary },
      }
  schemas:
    SessionStart:
      {
        type: object,
        required: [type, token],
        properties:
          {
            type: { const: session.start },
            token: { type: string },
            conversation_id: { type: string, format: uuid },
          },
        additionalProperties: false,
      }
    ServerEvent:
      {
        oneOf:
          [
            { $ref: "#/components/schemas/SessionCreated" },
            { $ref: "#/components/schemas/SequencedEvent" },
            { $ref: "#/components/schemas/Error" },
          ],
      }
    SessionCreated:
      {
        type: object,
        required: [type, sequence, session_id],
        properties:
          {
            type: { const: session.created },
            sequence: { type: integer, minimum: 1 },
            session_id: { type: string },
            conversation_id: { type: string, format: uuid },
          },
      }
    SequencedEvent:
      {
        type: object,
        required: [type, sequence],
        properties:
          {
            type:
              {
                type: string,
                enum:
                  [
                    conversation.created,
                    input_audio.speech_started,
                    input_audio.speech_stopped,
                    transcript.completed,
                    response.text.delta,
                    output_audio.started,
                    output_audio.sentence_start,
                    output_audio.stopped,
                    response.completed,
                    pong,
                  ],
              },
            sequence: { type: integer, minimum: 1 },
            delta: { type: string },
            text: { type: string },
            display_text: { type: string },
            status: { type: string, enum: [completed, cancelled] },
            transcript: { type: string },
            conversation_id: { type: string, format: uuid },
          },
      }
    Error:
      {
        type: object,
        required: [type, sequence, error],
        properties:
          {
            type: { const: error },
            sequence: { type: integer, minimum: 1 },
            error:
              {
                type: object,
                required: [code, message, retryable],
                properties:
                  {
                    code: { type: string },
                    message: { type: string },
                    retryable: { type: boolean },
                  },
              },
          },
      }
