What HUP is
HUP is FERAL’s equivalent — for heterogeneous hardware — of what the USB HID class spec was for input devices: a stable, versioned, vendor-neutral protocol that lets any vendor plug hardware into any FERAL brain without proprietary glue. Current version:HUP v1.4.0 (stable, Apache-2.0 licensed)
Full normative spec: feral-nodes/HUP_SPEC.md
How a daemon connects
- Daemon opens a WebSocket to
wss://<brain>:<port>/v1/node. - Sends a
node_registerframe with itsnode_id, capabilities, sensors, actuators, firmware version. - Brain replies with
node_ack— session token, expected heartbeat interval, granted capabilities, denied capabilities. - From that point the daemon can send
device_eventframes (sensor readings, button presses, camera frames) and respond tohup_action_requestframes the Brain sends to trigger actuators (buzz, LED, motor, etc.).
Message types (abbreviated)
Every frame is a JSON object with a
type key. Schemas are Pydantic (Python SDK)
and Zod (TypeScript SDK) — both enforce the same contract.
Writing a daemon
Two SDKs are published and maintained by FERAL:Python SDK
pip install feral-node-sdk. Async FeralNode class with auto-reconnect, mDNS discovery, and 6-digit pairing.TypeScript SDK
npm install @feral-ai/node-sdk. Same surface as the Python SDK for Node.js 20+.Cookiecutter template
Ship a new daemon in under an hour:manifest.json, mock hardware, two
placeholder @on_action handlers, and one placeholder event stream.
Replace the mocks with your real integration and feral publish --daemon .
when ready.
Publishing to the registry
Once your daemon is stable:kind=daemon. Any FERAL user can install it with:
Pairing + security
- First-time pairing uses a 6-digit code the daemon prints to its own log. The user types that code into Settings → Devices → Pair. The Brain returns an API key the daemon saves locally.
- Steady-state: daemon sends
Authorization: Bearer <key>in the WebSocket upgrade. - Per-capability gating: the user approves each capability (camera, audio,
actuator) in Settings. The Brain only sends
hup_action_requestframes for capabilities the user has granted.
Compliance
- Licensed Apache-2.0 — any vendor may implement, fork, or extend.
- No certification program — vendors self-declare conformance by passing
the schemas in
feral-node-sdk/@feral-ai/node-sdk. - Bug reports + protocol additions go through github.com/FERAL-AI/FERAL-AI/issues.
Full spec
For the complete normative specification — all frame schemas, error codes, example wire traces, pairing flow details, and reserved fields — read the canonical document: feral-nodes/HUP_SPEC.md.Brain-side self-description (feral-core)
The wire protocol above covers daemon ↔ brain transport. On the brain, HUP is also a generic hardware hub for any device that self-describes:-
Wire format — devices return an
actions[]envelope documented asHUP_ACTION_SCHEMAinferal-core/hardware/protocol.py. Convertersdevice_capability_from_action()anddevice_manifest_from_capabilities()map it toDeviceManifest/DeviceCapability(including optionalaction_typeandverifyhonesty contracts). -
Transport adapters —
GenericSelfDescribingAdapterpassthrough-executes any self-describing companion library;BridgedPeripheralAdapterroutes actions to phone-bridged BLE peripherals viamesh.invoke; mesh nodes useWebSocketNodeAdapter. -
Registration —
state.register_generic_hardware_skill_for()runs on every ingress (brain-local discovery, meshon_node_connectedwith node-supplieddevice_manifest,peripheral_bridge_register). It registersGenericHardwareSkill, which auto-generates LLM tools (hwdev_<device>__<capability>), enforces safety tiers andrate_limit_per_minute, and runs the closed-loop honesty loop whenverifyis declared. -
Discovery — brain-local USB devices are listed in
DEVICE_DISCOVERY_SPECS(hardware/discovery.py); override CuteBot path withFERAL_CUTEBOT_PATH. -
Fleet API —
GET /api/hardware/fleetreturns manifests, derived safety tiers, last verification state, mesh nodes, and announced devices for companion-app rendering. -
Kill switch —
FERAL_GENERIC_HARDWARE_SKILLS(default"1") enables the generic path;"0"falls back to hand-written skill manifests only.
