Hivemind Websocket Client
Project description
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; setFalsein production - Trusted peers: Only peers with a public key in
NodeIdentity.trusted_keyscan 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:
- Installation — PyPI, optional extras, dependencies
- API Reference —
HiveMessage,HiveMessageBusClient,NodeIdentity,HiveMapper - Client API — WebSocket and HTTP client usage
- Async Client — asyncio-native
AsyncHiveMessageBusClient - Message Types — Routing modes, QUERY, CASCADE, PING
- Identity & Credentials — Credentials, RSA keys, trusted peers
- Binary Handlers — TTS audio and file transfer callbacks
- Serialization — Binary wire format
- CLI Reference — All
hivemind-clientcommands - Examples — Chat, TTS, INTERCOM, QUERY, CASCADE, trust management
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hivemind_bus_client-0.9.2a1.tar.gz.
File metadata
- Download URL: hivemind_bus_client-0.9.2a1.tar.gz
- Upload date:
- Size: 418.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de73870190bacc5c98d74d8a3834f3a92f776c6a1c9039e1e69ce2ec8955ec88
|
|
| MD5 |
10956ed339c19d6b023677faff72aff5
|
|
| BLAKE2b-256 |
78d2b45bccf4c4cebf47003393e7df7ce0316454e5955727d16caef7165dc92f
|
File details
Details for the file hivemind_bus_client-0.9.2a1-py3-none-any.whl.
File metadata
- Download URL: hivemind_bus_client-0.9.2a1-py3-none-any.whl
- Upload date:
- Size: 61.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d7b1c2352ae67ce5d4f6745fdc40e3767b3b648bd5b87b720c60dab39c9e147
|
|
| MD5 |
d889e2cbeef6d8cf7c4a585d354effb1
|
|
| BLAKE2b-256 |
82e2f43ed8a00579cf3710a371e8e4fc50149a8b3629aaaa6c440b7ca4309e7f
|