Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

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. This lets a satellite and a hivemind-core hub communicate securely, with messages routed between them.

All satellite packages build on this library: hivemind-mic-satellite, HiveMind-voice-relay, HiveMind-voice-sat, and HiveMind-cli. If you build a custom satellite or integration, start here.

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 none

Every satellite in that table uses HiveMessageBusClient from this library to open the connection, complete the handshake, and exchange HiveMessage packets with the hub. The hub's hivemind-audio-binary-protocol plugin provides server-side STT and TTS. 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. It 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
    websocket_ping_interval=25,  # keep long-lived proxy connections warm
    websocket_ping_timeout=10,   # fail fast enough for reconnect to take over
)
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.

Ping settings can also be supplied with environment variables. Client-specific variables (HIVEMIND_WEBSOCKET_CLIENT_PING_INTERVAL, HIVEMIND_WEBSOCKET_CLIENT_PING_TIMEOUT) win over shared hub defaults (HIVEMIND_WEBSOCKET_PING_INTERVAL, HIVEMIND_WEBSOCKET_PING_TIMEOUT). Set the interval to 0 to disable client pings.

Sending messages

You can send any OVOS Message 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 it to False in production.
  • Trusted peers: Only peers with a public key in NodeIdentity.trusted_keys can inject BUS messages via PROPAGATE and INTERCOM. The client silently drops untrusted messages.

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, revoked key, or blacklisted key). Check hub logs: journalctl -u hivemind-core -f.

Documentation

Full reference in /docs:

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.10.6a1.tar.gz (442.8 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.10.6a1-py3-none-any.whl (75.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: hivemind_bus_client-0.10.6a1.tar.gz
  • Upload date:
  • Size: 442.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for hivemind_bus_client-0.10.6a1.tar.gz
Algorithm Hash digest
SHA256 e09ac9865dda56797c473d979528653ceb1decf57cd5340ac38c49d74ffe376b
MD5 7e3c7016410de4f8eba955e0e48072cd
BLAKE2b-256 c0aec2d7ef45e643a722d3cc3806df8dbd8c23127f8b1813787a8750446b6123

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for hivemind_bus_client-0.10.6a1-py3-none-any.whl
Algorithm Hash digest
SHA256 e1c506b9b45820de2e6da663308975f20d471457fa77388154a2ccb1dcf7ed28
MD5 0e3893e2912afcdcefce266f82ce4fc5
BLAKE2b-256 ff51f57155db86c8195e7f35d432ab33785aae46ac186a5d257781b3a4f8007b

See more details on using hashes here.

Release history Release notifications | RSS feed

Supported by

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