Client Module

The client module provides an abstract base class for implementing Neuro API websocket clients. This module defines the core interface and message handling functionality for communicating with the Neuro Game Interaction API.

Overview

The client module contains the foundational components needed to build a websocket client that can communicate with the Neuro system. It provides message parsing, validation, and abstract methods that must be implemented by concrete client classes.

Classes

NeuroMessage

class neuro_api.client.NeuroMessage

Schema for incoming message.

Represents the structure of both a server or client message as specified in the Neuro Game SDK API documentation.

command

Unique identifier for the websocket command.

Type:

str

game

Game name, used as an identifier. Messages from server will not include this field, but should always be present in messages from clients.

Type:

NotRequired[str]

data

Data associated with the command. This field is not required and can be omitted for some commands.

Type:

NotRequired[dict[str, object]

Reference:

Specification details: https://github.com/VedalAI/neuro-sdk/blob/main/API/SPECIFICATION.md#neuro-api-specification

A TypedDict that defines the schema for incoming messages from both server and client connections.

The message structure follows the Neuro Game SDK API specification:

  • command (str): Unique identifier for the websocket command

  • game (NotRequired[str]): Game name identifier (present in client messages, absent in server messages)

  • data (NotRequired[dict[str, object]]): Optional data associated with the command

See also

For complete specification details, see the Neuro SDK API Specification.

AbstractNeuroAPIClient

class neuro_api.client.AbstractNeuroAPIClient

Abstract client for the Neuro Game Interaction API.

Provides a foundational interface for interactions with the Neuro system. This class is designed to be subclassed by specific client implementations.

Note

This is an abstract base class that requires implementation of specific game interaction methods in subclasses.

Abstract base class providing the core interface for Neuro API websocket clients.

This class defines the essential methods for websocket communication and message handling. Concrete implementations must provide the websocket I/O operations while inheriting the message parsing and command handling functionality.

abstractmethod async write_to_websocket(data: str) None

Abstract method to write a message to the websocket.

This method must be implemented by subclasses to define the specific mechanism for sending data over a websocket.

Parameters:

data (str) – The message to be sent over the websocket.

abstractmethod async read_from_websocket() bytes | bytearray | memoryview | str

Abstract method to read a message from the websocket.

This method must be implemented by subclasses to define the specific mechanism for receiving data from a websocket.

Returns:

The message received from the websocket, supporting anything orjson.loads can handle.

Return type:

bytes | bytearray | memoryview | str

async send_command_data(data: bytes) None

Send command data over the websocket.

Converts the input bytes to a UTF-8 encoded string and writes it to the websocket.

Parameters:

data (bytes) – The command data to be sent over the websocket.

Raises:
async read_raw_full_message() NeuroMessage

Read a command and its associated data from Neuro websocket connection.

Waits and reads a message from the websocket. The method will not return until a message is successfully read.

Returns:

Server or client Neuro API message.

Return type:

NeuroMessage

Raises:
  • orjson.JSONDecodeError – If the received message is invalid JSON.

  • AssertionError – If the received JSON message contains unexpected types for command or data.

async read_raw_server_message() tuple[str, dict[str, object] | None]

Read a command and its associated data from Neuro websocket server.

Waits and reads a message from the websocket. The method will not return until a message is successfully read.

Returns:

A tuple containing:
  • The command name as a string

  • Associated data as a dictionary or None

Return type:

tuple[str, dict[str, object] | None]

Raises:
  • orjson.JSONDecodeError – If the received message is invalid JSON.

  • AssertionError – If the received JSON message contains unexpected types for command or data.

async read_raw_client_message() tuple[str, str, dict[str, object] | None]

Read a command and its associated data from Neuro websocket client.

Waits and reads a message from the websocket. The method will not return until a message is successfully read.

Returns:

A tuple containing:
  • The command name as a string

  • The name of the game client connected as a string

  • Associated data as a dictionary or None

Return type:

tuple[str, str, dict[str, object] | None]

Raises:
  • orjson.JSONDecodeError – If the received message is invalid JSON.

  • AssertionError – If the received JSON message contains unexpected types for command or data.

async handle_unknown_command(command: str, data: dict[str, object] | None) None

Handle unknown command from Neuro.

Parameters:
  • command (str) – Unhandled command name

  • data (dict[str, object] | None) – Data associated with unknown command.

Note

Base implementation just prints an error message.

async read_message() None

Read message from Neuro websocket.

You should call this function in a loop as long as the websocket is still connected.

Calls handle_unknown_command for all commands. Implement specific handling in a subclass.

Note

Does not catch any exceptions read_raw_server_message raises.

Abstract Methods

These methods must be implemented by subclasses:

abstractmethod async AbstractNeuroAPIClient.write_to_websocket(data: str) None

Abstract method to write a message to the websocket.

This method must be implemented by subclasses to define the specific mechanism for sending data over a websocket.

Parameters:

data (str) – The message to be sent over the websocket.

abstractmethod async AbstractNeuroAPIClient.read_from_websocket() bytes | bytearray | memoryview | str

Abstract method to read a message from the websocket.

This method must be implemented by subclasses to define the specific mechanism for receiving data from a websocket.

Returns:

The message received from the websocket, supporting anything orjson.loads can handle.

Return type:

bytes | bytearray | memoryview | str

Concrete Methods

These methods are provided by the base class:

async AbstractNeuroAPIClient.send_command_data(data: bytes) None

Send command data over the websocket.

Converts the input bytes to a UTF-8 encoded string and writes it to the websocket.

Parameters:

data (bytes) – The command data to be sent over the websocket.

Raises:
async AbstractNeuroAPIClient.read_raw_full_message() NeuroMessage

Read a command and its associated data from Neuro websocket connection.

Waits and reads a message from the websocket. The method will not return until a message is successfully read.

Returns:

Server or client Neuro API message.

Return type:

NeuroMessage

Raises:
  • orjson.JSONDecodeError – If the received message is invalid JSON.

  • AssertionError – If the received JSON message contains unexpected types for command or data.

async AbstractNeuroAPIClient.read_raw_server_message() tuple[str, dict[str, object] | None]

Read a command and its associated data from Neuro websocket server.

Waits and reads a message from the websocket. The method will not return until a message is successfully read.

Returns:

A tuple containing:
  • The command name as a string

  • Associated data as a dictionary or None

Return type:

tuple[str, dict[str, object] | None]

Raises:
  • orjson.JSONDecodeError – If the received message is invalid JSON.

  • AssertionError – If the received JSON message contains unexpected types for command or data.

async AbstractNeuroAPIClient.read_raw_client_message() tuple[str, str, dict[str, object] | None]

Read a command and its associated data from Neuro websocket client.

Waits and reads a message from the websocket. The method will not return until a message is successfully read.

Returns:

A tuple containing:
  • The command name as a string

  • The name of the game client connected as a string

  • Associated data as a dictionary or None

Return type:

tuple[str, str, dict[str, object] | None]

Raises:
  • orjson.JSONDecodeError – If the received message is invalid JSON.

  • AssertionError – If the received JSON message contains unexpected types for command or data.

async AbstractNeuroAPIClient.handle_unknown_command(command: str, data: dict[str, object] | None) None

Handle unknown command from Neuro.

Parameters:
  • command (str) – Unhandled command name

  • data (dict[str, object] | None) – Data associated with unknown command.

Note

Base implementation just prints an error message.

async AbstractNeuroAPIClient.read_message() None

Read message from Neuro websocket.

You should call this function in a loop as long as the websocket is still connected.

Calls handle_unknown_command for all commands. Implement specific handling in a subclass.

Note

Does not catch any exceptions read_raw_server_message raises.

Usage Example

Here’s a basic example of how to implement a concrete client:

import asyncio
import websockets
from neuro_api.client import AbstractNeuroAPIClient

class MyNeuroClient(AbstractNeuroAPIClient):
    def __init__(self, websocket):
        self.websocket = websocket

    async def write_to_websocket(self, data: str) -> None:
        await self.websocket.send(data)

    async def read_from_websocket(self) -> str:
        return await self.websocket.recv()

    async def handle_unknown_command(self, command: str, data: dict | None) -> None:
        print(f"Received command: {command} with data: {data}")

async def main():
    uri = "ws://localhost:8000"
    async with websockets.connect(uri) as websocket:
        client = MyNeuroClient(websocket)

        # Read messages in a loop
        while True:
            try:
                await client.read_message()
            except websockets.exceptions.ConnectionClosed:
                break

asyncio.run(main())

Message Flow

The client handles two types of message flows:

Server Messages

Messages received from the Neuro server contain:

  • command: The command identifier

  • data (optional): Associated command data

Use read_raw_server_message() to parse these messages.

Client Messages

Messages from other game clients contain:

  • command: The command identifier

  • game: The source game identifier

  • data (optional): Associated command data

Use read_raw_client_message() to parse these messages.