Setup walkthrough: pairing a satellite with a hub
August 2, 2026 · View on GitHub
This guide walks through installing the library, registering a satellite on a hub, and verifying the connection.
Prerequisites
- A running hivemind-core hub (the machine that hosts the OVOS skill engine)
- Python 3.10+ on the satellite machine
- Network access from the satellite to the hub on port 5678 (WebSocket) or 5679 (HTTP)
1. Install the library
pip install hivemind_bus_client
2. Register this satellite on the hub
On the hub machine, create an access key for this satellite:
hivemind-core add-client --name "living-room-satellite"
Output:
Credentials added to database!
Node ID: 1
Friendly Name: living-room-satellite
Access Key: 42caf3d2405075fb9e7a4e1ff44e4c4f
Password: 5ae486f7f1c26bd4645bd052e4af3ea3
Keep the access key and password. You need them on the satellite.
To give the satellite admin rights (able to send BROADCAST messages), pass the node id:
hivemind-core make-admin 1
2b. Grant the message types the satellite sends
A new client has an empty whitelist and the hub denies everything it sends, binary payloads included. Admin clients are no exception. Grant the types now:
hivemind-core allow-msg "recognizer_loop:utterance" 1
hivemind-core allow-msg "speak" 1
3. Save credentials on the satellite
On the satellite machine:
hivemind-client set-identity \
--key "42caf3d2405075fb9e7a4e1ff44e4c4f" \
--password "5ae486f7f1c26bd4645bd052e4af3ea3" \
--host ws://192.168.1.10 \
--port 5678 \
--siteid living-room
Credentials are written to ~/.config/hivemind/_identity.json. The --siteid value is injected into every outgoing OVOS message context so the hub can route responses back to the right room.
For an encrypted (TLS) connection use wss:// instead of ws://. The library accepts self-signed certificates by default (self_signed=True).
4. Verify connectivity
hivemind-client ping --host ws://192.168.1.10 --port 5678
ping floods the hive and prints the nodes that answered, as an ASCII tree:
== connected to HiveMind, sending PING (timeout=5.0s)
PING from living-room-hub::def456 site=living-room
== Hive Map ==
[self] living-room-satellite::abc123
└── living-room-hub::def456 site=living-room latency=12ms
Add --json for the raw topology instead.
5. Open an interactive terminal
hivemind-client terminal
Type a sentence and press Enter. The hub processes it and the spoken response is printed:
== connected to HiveMind
Utterance: what time is it
> It is 3:45 PM.
Press Ctrl-C to disconnect.
6. Use the library in code
from hivemind_bus_client import HiveMessageBusClient
from hivemind_bus_client.message import HiveMessage, HiveMessageType
from ovos_bus_client.message import Message
# Loads credentials from ~/.config/hivemind/_identity.json
client = HiveMessageBusClient()
client.connect()
client.on_mycroft("speak", lambda msg: print("Hub says:", msg.data["utterance"]))
client.emit(HiveMessage(
HiveMessageType.BUS,
Message("recognizer_loop:utterance", {"utterances": ["hello world"]}),
))
input("Press Enter to disconnect...\n")
client.close()
Or pass credentials directly without saving them:
client = HiveMessageBusClient(
key="42caf3d2405075fb9e7a4e1ff44e4c4f",
password="5ae486f7f1c26bd4645bd052e4af3ea3",
host="ws://192.168.1.10",
port=5678,
)
client.connect()
SSL / TLS
For production deployments where the hub uses a signed certificate:
client = HiveMessageBusClient(
host="wss://hub.example.com",
port=5678,
self_signed=False, # enforce certificate verification
)
For self-hosted hubs with a self-signed certificate keep self_signed=True (the default).
Troubleshooting
Connection refused or timeout
- Confirm the hub is running:
systemctl status hivemind-core - Check the firewall allows port 5678:
sudo ufw allow 5678/tcp - Use
ws://(nothttp://) for the host URL
Handshake timeout
RuntimeError: timed out waiting for handshake
The TCP connection opened but the hub rejected or did not complete the handshake. Common causes:
- Wrong access key or password: re-run
hivemind-core add-clientand updateset-identity - The access key was deleted on the hub: check
hivemind-core list-clients - The hub requires a higher protocol version than this client offers: check
min_protocol_versionin the hub'sserver.json - Firewall is stateful and drops the upgrade: ensure WebSocket upgrades are not filtered
Decryption error
got encrypted message, but could not decrypt!
The password does not match what the hub stored for this access key. The handshake uses the password to derive the AES session key. A mismatch means every message is unreadable.
Multiple satellites on the same machine
Each satellite needs its own NodeIdentity. Pass a custom identity store:
from json_database import JsonConfigXDG
from hivemind_bus_client.identity import NodeIdentity
from hivemind_bus_client import HiveMessageBusClient
identity = NodeIdentity(
identity_file=JsonConfigXDG("kitchen-satellite", subfolder="hivemind"))
identity.access_key = "..."
identity.password = "..."
identity.default_master = "ws://192.168.1.10"
identity.default_port = 5678
identity.site_id = "kitchen"
identity.save()
client = HiveMessageBusClient(identity=identity)
client.connect()