The Discovery Engine is Synapse’s automated device detection system. It scans your network using protocol-specific adapters and registers newly found devices in the central registry.
Synapse ships with 8 discovery adapters, each specialized for a different protocol or device type:
| Adapter | Protocol | Discovery Method | What It Finds |
|---|---|---|---|
| NDI/mDNS | NDI | mdns | NDI-enabled sources and receivers via mDNS/Bonjour |
| Dante | Dante/AES67 | dante_discovery | Dante audio endpoints on the network |
| USB | USB | usb_enumeration | Locally connected USB cameras, capture cards, microphones |
| Fleet | Fleet heartbeat | heartbeat_registration | Fleet-managed remote devices reporting via heartbeat |
| Desktop/QR | WAVE Desktop | qr_code | Desktop app instances paired via QR code |
| Network Scan | IP | network_scan | Generic IP devices found by subnet scanning |
| LiveKit | LiveKit | livekit_room | Participants in active LiveKit rooms |
| Zoom | Zoom | zoom_bridge | Zoom meeting participants and Zoom Room appliances |
Each adapter implements the DiscoveryAdapter interface:
interface DiscoveryAdapter {
readonly protocolName: string;
readonly discoveryMethod: DiscoveryMethod;
discover(
orgId: string,
segmentId?: string
): Promise<ServiceResult<DiscoveredDevice[]>>;
}
Trigger a discovery scan by specifying which protocols to scan:
const response = await fetch('/api/ncp/discovery', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
},
body: JSON.stringify({
protocols: ['mdns', 'dante_discovery', 'usb_enumeration', 'network_scan'],
segment_ids: ['segment-uuid'], // Optional: limit to specific segments
}),
});
const { data: session } = await response.json();
The response is a DiscoverySession record with:
| Field | Description |
|---|---|
id | Unique session identifier |
status | running, completed, failed, or cancelled |
protocols_scanned | Array of protocols that were scanned |
segments_scanned | Array of segment IDs that were targeted (null = all) |
devices_found | Count of new devices discovered |
devices_approved | Count of devices approved so far |
started_at | When the scan began |
completed_at | When the scan finished (null while running) |
The discovery-scheduler Inngest function runs periodic discovery scans based on a configurable schedule. Scheduled scans run all configured adapters and respect subnet allowlisting (see below).
const response = await fetch('/api/ncp/discovery', {
headers: { 'Authorization': `Bearer ${accessToken}` },
});
const { data: sessions } = await response.json();
// Returns the 50 most recent discovery sessions, ordered by created_at descending
Discovery is governed by the ncp_discovery_permissions table, which defines which subnets can be scanned and which methods are permitted:
| Field | Description |
|---|---|
allowed_subnet | CIDR notation of the allowed subnet (e.g., 10.0.1.0/24) |
allowed_methods | Array of permitted discovery methods for this subnet |
rate_limit_per_hour | Maximum number of scans per hour for this subnet (default: 10) |
Only organization admins can create or modify discovery permissions. Discovery adapters check these permissions before scanning a subnet, ensuring that the engine does not probe unauthorized network segments.
Devices found by auto-discovery are registered with approved: false and status: 'pending_approval'. This prevents unknown devices from immediately participating in signal routing.
To list pending devices:
const response = await fetch('/api/ncp/devices?approved=false', {
headers: { 'Authorization': `Bearer ${accessToken}` },
});
To approve a device:
await fetch(`/api/ncp/devices/${deviceId}/approve`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${accessToken}` },
});
The discovery engine emits Inngest events for downstream processing:
| Event | Trigger |
|---|---|
wave/ncp.discovery.completed | Discovery session finishes (includes devicesFound count) |
wave/ncp.discovery.device-found | Individual device detected during scan |
These events power notifications, audit trails, and automated approval workflows for organizations that want hands-free discovery.
Relies on mDNS multicast traffic. Devices must be on the same subnet or multicast must be routed across VLANs. The adapter reads NDI version and capability metadata from the mDNS TXT records.
Uses the Dante Discovery protocol to enumerate Dante-enabled devices. Returns channel count, sample rate, and Dante device name. Requires that the scanning host is on a Dante-enabled network segment with multicast enabled.
Enumerates locally connected USB devices on the host running the Synapse agent. Detects cameras, capture cards, and audio interfaces. Only available on hosts running the WAVE Desktop application.
Scans a subnet by probing known ports for common broadcast equipment protocols. Less targeted than protocol-specific adapters but useful for finding generic_ip devices and equipment that does not advertise via mDNS or Dante.
These adapters query the LiveKit server or Zoom API respectively to discover active participants. Participants are registered as livekit_participant, zoom_participant, or zoom_room device classes. These adapters require API credentials configured in the organization settings.