Skip to main content

Hivemind Websocket Client

Project description

Ask DeepWiki

HiveMind Bus Client

hivemind-websocket-client (package hivemind_bus_client) is the foundation library for every HiveMind satellite. It provides an authenticated, encrypted WebSocket client that extends the standard OVOS bus client, enabling secure and routed communication between a satellite and a hivemind-core hub.

All satellite packages — hivemind-mic-satellite, HiveMind-voice-relay, HiveMind-voice-sat, and HiveMind-cli — build on this library. If you are building a custom satellite or integration, this is your starting point.

Where it fits in the satellite spectrum

HiveMind satellites are differentiated by how much audio and language processing happens locally. hivemind-websocket-client sits below all of them:

Satellite Local processing Remote processing
HiveMind-cli nothing (text input) everything
hivemind-mic-satellite mic + VAD STT, TTS, intent, skills
HiveMind-voice-relay mic + VAD + wakeword STT, TTS
HiveMind-voice-sat mic + VAD + wakeword + STT + TTS skills only
This library WebSocket transport + encryption

Every satellite in that table uses HiveMessageBusClient from this library to open the connection, complete the handshake, and exchange HiveMessage packets with the hub. Server-side STT and TTS are provided by the hub's hivemind-audio-binary-protocol plugin; the satellite cannot choose the engine — the hub operator configures it.

See the whitepaper for protocol details.

Hardware and OS requirements

  • Python 3.9 or later
  • No special hardware required — runs on any machine with network access to the hub
  • The async client (hivemind-bus-client[async]) requires Python 3.10+

Install

pip install hivemind_bus_client

Async client (asyncio-native applications):

pip install "hivemind_bus_client[async]"

Verify:

hivemind-client --help

Quickstart: pair with a hub and send your first message

1. Generate an access key on the hub

On the machine running hivemind-core:

hivemind-core add-client --name "my-satellite" --access-key KEY --password PASS

add-client prints an access key and a password. Keep both — you need them on every satellite you pair.

2. Configure the satellite

On the satellite machine:

hivemind-client set-identity \
  --key   "your-access-key" \
  --password "your-password" \
  --host  ws://192.168.1.10 \
  --port  5678 \
  --siteid living-room

Credentials are saved to ~/.config/hivemind/_identity.json and are read automatically by the client.

3. Verify connectivity

hivemind-client ping --host ws://192.168.1.10 --port 5678

4. Open a terminal session

hivemind-client terminal

Type an utterance, and the hub processes it. Spoken responses are printed to stdout.

5. Use the library

from hivemind_bus_client import HiveMessageBusClient
from hivemind_bus_client.message import HiveMessage, HiveMessageType
from ovos_bus_client.message import Message

# Credentials are loaded from the identity file set in step 2.
# Pass them explicitly if you prefer:
#   client = HiveMessageBusClient(key="...", password="...", host="ws://192.168.1.10", port=5678)
client = HiveMessageBusClient()
client.connect()

# React to spoken responses from the hub
client.on_mycroft("speak", lambda msg: print("Hub says:", msg.data["utterance"]))

# Send an utterance
client.emit(HiveMessage(
    HiveMessageType.BUS,
    Message("recognizer_loop:utterance", {"utterances": ["hello world"]}),
))

# Block until you're done
input("Press Enter to disconnect...\n")
client.close()

Library guide

Connecting

HiveMessageBusClient extends ovos_bus_client.MessageBusClient. The constructor accepts credentials either directly or through a saved NodeIdentity.

from hivemind_bus_client import HiveMessageBusClient

# All parameters optional if identity file is populated
client = HiveMessageBusClient(
    key="access-key",           # access key from hivemind-core add-client
    password="password",        # password from hivemind-core add-client
    host="ws://192.168.1.10",   # hub address, ws:// or wss://
    port=5678,                  # default 5678
    useragent="my-satellite",   # shown in hub logs
    self_signed=True,           # accept self-signed TLS certs
    share_bus=False,            # share the local OVOS bus with the hub (trusted satellites only)
    compress=True,              # zlib-compress binary frames
    binarize=True,              # use binary wire format instead of JSON
)
client.connect()                # blocks until the handshake completes

connect() runs the WebSocket in a background thread and calls wait_for_handshake(). After it returns the connection is live.

Sending messages

Any OVOS Message can be sent directly — the client wraps it in a HiveMessage(BUS, ...) automatically:

from ovos_bus_client.message import Message

client.emit(Message("recognizer_loop:utterance", {"utterances": ["what time is it"]}))

For explicit HiveMessage control:

from hivemind_bus_client.message import HiveMessage, HiveMessageType

client.emit(HiveMessage(HiveMessageType.BUS,
                        Message("recognizer_loop:utterance", {"utterances": ["what time is it"]})))

Receiving messages

Register handlers for OVOS (inner) message types:

client.on_mycroft("speak", lambda msg: print(msg.data["utterance"]))
client.on_mycroft("ovos.common_play.play", handle_play)

Register handlers for HiveMind protocol messages:

from hivemind_bus_client.message import HiveMessageType

client.on(HiveMessageType.BROADCAST, lambda hm: print("Broadcast:", hm.payload))
client.on(HiveMessageType.PING, lambda hm: print("Ping from", hm.metadata))

Wait helpers

# Send and block until a reply arrives
response = client.wait_for_response(
    Message("recognizer_loop:utterance", {"utterances": ["what time is it"]}),
    reply_type="speak",
    timeout=10,
)
if response:
    print(response.payload.data["utterance"])

# Wait for the next message of a given HiveMind type
hive_msg = client.wait_for_message(HiveMessageType.BROADCAST, timeout=30)

# Wait for the next inner OVOS message of a given type wrapped in BUS
bus_msg = client.wait_for_mycroft("speak", timeout=10)

ESCALATE, QUERY, CASCADE, BROADCAST, PROPAGATE

# ESCALATE — forward up the authority chain (supervisor hubs)
client.emit(HiveMessage(HiveMessageType.ESCALATE,
                        Message("recognizer_loop:utterance", {"utterances": ["call admin"]})))

# QUERY — first answering node wins
inner = HiveMessage(HiveMessageType.BUS,
                    Message("intent.request", {"utterance": "what time is it"}))
client.emit(HiveMessage(HiveMessageType.QUERY, payload=inner))

# BROADCAST — admin pushes to all connected satellites (requires admin access key)
client.emit(HiveMessage(
    HiveMessageType.BROADCAST,
    payload=HiveMessage(HiveMessageType.BUS,
                        Message("speak", {"utterance": "System update in 5 minutes"}))
))

Peer-to-peer encrypted messages (INTERCOM)

INTERCOM uses hybrid encryption (random AES-256-GCM key per message, RSA-encrypted key exchange):

target_pubkey = "-----BEGIN PUBLIC KEY-----\n..."
client.emit_intercom(
    HiveMessage(HiveMessageType.BUS, Message("speak", {"utterance": "private message"})),
    pubkey=target_pubkey,
)

Incoming INTERCOM messages are only injected into the internal bus if the sender's public key is in NodeIdentity.trusted_keys.

Async client

For asyncio-native applications (FastAPI, aiohttp, async chat bots):

from hivemind_bus_client import AsyncHiveMessageBusClient

async def main():
    client = AsyncHiveMessageBusClient(key="...", password="...", host="ws://192.168.1.10")
    await client.connect()
    await client.emit(Message("recognizer_loop:utterance", {"utterances": ["hello"]}))

Requires: pip install "hivemind_bus_client[async]"

Binary payloads (TTS audio, files)

Override BinaryDataCallbacks to handle incoming binary data:

from hivemind_bus_client.client import BinaryDataCallbacks, HiveMessageBusClient

class MyCallbacks(BinaryDataCallbacks):
    def handle_receive_tts(self, bin_data: bytes, utterance: str, lang: str, file_name: str):
        with open(file_name, "wb") as f:
            f.write(bin_data)

client = HiveMessageBusClient(bin_callbacks=MyCallbacks())
client.connect()

Message types

Type Direction Description
BUS satellite ↔ hub Standard OVOS bus message forwarded to the hub's skill engine
ESCALATE upstream Forward up the authority chain (supervisor hubs)
QUERY upstream + response First answering node wins
BROADCAST downstream Admin pushes to all connected satellites
PROPAGATE flood Forward to all peers in all directions
CASCADE flood + responses Collect answers from all nodes
INTERCOM any → any End-to-end hybrid-encrypted (AES-GCM + RSA)
PING inside PROPAGATE Flood-based network topology discovery
BINARY hub → satellite Raw binary payload (TTS audio, file transfer)

Security

  • Per-link encryption: AES-GCM or ChaCha20-Poly1305, negotiated at handshake via poorman_handshake
  • Hybrid INTERCOM encryption: Random AES-256 key per message, RSA-encrypted key exchange — no payload size limit
  • Self-signed TLS: self_signed=True (default) accepts self-signed certificates; set False in production
  • Trusted peers: Only peers with a public key in NodeIdentity.trusted_keys can inject BUS messages via PROPAGATE and INTERCOM; untrusted messages are silently dropped

Identity and credentials

from hivemind_bus_client.identity import NodeIdentity

identity = NodeIdentity()            # loads from ~/.config/hivemind/_identity.json
print(identity.access_key)
print(identity.default_master)

identity.add_trusted_key("home-hub", "-----BEGIN PUBLIC KEY-----\n...")
identity.save()

See Identity & Credentials for the full field reference.

CLI

# Persist credentials
hivemind-client set-identity --key KEY --password PASS --host ws://hub.local --port 5678 --siteid home

# Interactive terminal (type utterances, see spoken responses)
hivemind-client terminal

# Ping the hub and print round-trip info
hivemind-client ping --host ws://hub.local --port 5678

# Send a single OVOS message
hivemind-client send-mycroft \
  --msg "recognizer_loop:utterance" \
  --payload '{"utterances": ["hello world"]}'

# Send as ESCALATE or PROPAGATE
hivemind-client escalate --msg "recognizer_loop:utterance" --payload '{"utterances": ["hello"]}'
hivemind-client propagate --msg "recognizer_loop:utterance" --payload '{"utterances": ["hello"]}'

Troubleshooting

RuntimeError: NodeIdentity not set — Run hivemind-client set-identity or pass key, password, and host to the constructor.

RuntimeError: timed out waiting for handshake — The hub is unreachable or the port is wrong. Verify the hub is running (hivemind-core listen) and the firewall allows port 5678. Try hivemind-client ping first.

got encrypted message, but could not decrypt! — The access key or password does not match what was registered on the hub. Re-run hivemind-core add-client and update the satellite identity.

Connection drops immediately — The hub may have rejected the access key (wrong key, key revoked, or blacklisted). Check hub logs: journalctl -u hivemind-core -f.

Documentation

Full reference in /docs:

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hivemind_bus_client-0.9.1a1.tar.gz (415.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hivemind_bus_client-0.9.1a1-py3-none-any.whl (61.9 kB view details)

Uploaded Python 3

File details

Details for the file hivemind_bus_client-0.9.1a1.tar.gz.

File metadata

  • Download URL: hivemind_bus_client-0.9.1a1.tar.gz
  • Upload date:
  • Size: 415.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hivemind_bus_client-0.9.1a1.tar.gz
Algorithm Hash digest
SHA256 c28d938dd84bf8122b0f856feaa78467e232f91a1f8fd81bf058fe24fdb54c66
MD5 caf1bd805d50faab21082783cf01101b
BLAKE2b-256 6d507f2873e07cbaaf83dee2054b2888392570f6273cabbaa57d8c4c2e66497f

See more details on using hashes here.

File details

Details for the file hivemind_bus_client-0.9.1a1-py3-none-any.whl.

File metadata

File hashes

Hashes for hivemind_bus_client-0.9.1a1-py3-none-any.whl
Algorithm Hash digest
SHA256 9d344af4158c3a6b32f884c48aec3858d331319a41d6c3fbc2386296ec1e9bbc
MD5 fd9fd4f411296db4342f90e783ae81ae
BLAKE2b-256 b795817a61b921fe2832ea92076d95292042a141a2f5476948668958befa9393

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page