Skip to content

Resolution and Defaults

When you call get_connection() or connect(), the SDK must select exactly one plugin from all registered candidates. This page describes the resolution algorithm, default handling, and what happens when the selection is ambiguous.


Resolution Inputs

The resolver receives four criteria from the call site:

Input Source Required
platform device.platform.short_name or device.platform (string) Always
connection_type Argument (e.g., "ssh", "api", "netconf") No
connection_library Argument (e.g., "scrapli", "netmiko") No
Required capabilities Capability interfaces inherited by the proxy class Automatic

Resolution Algorithm

flowchart TD
    A["Filter by platform"] --> B["Filter by connection_type<br/>(if provided)"]
    B --> C["Filter by connection_library<br/>(if provided)"]
    C --> D{"Candidates<br/>found?"}
    D -- No --> E["PluginNotFoundError"]
    D -- Yes --> F["Filter by required<br/>capabilities"]
    F --> G{"Exactly<br/>one match?"}
    G -- Yes --> H["Return plugin"]
    G -- No --> I{"Full capability<br/>matches exist?"}
    I -- Yes, multiple --> K{"fallback_to_default<br/>= True?"}
    I -- No full matches --> J["Best-match fallback<br/>(highest capability score)"]
    J -- "single best" --> H
    J -- "tie" --> M["AmbiguousPluginError"]
    K -- Yes --> L{"Default<br/>exists in<br/>candidates?"}
    L -- Yes --> H
    L -- No --> M
    K -- No --> M

Step-by-step

  1. Filter by platform -- only plugins registered for device.platform survive.
  2. Filter by connection_type -- if provided, narrows to that type. If omitted, all types for the platform remain.
  3. Filter by connection_library -- if provided, exact match. If omitted, all libraries for the platform+type remain.
  4. Filter by capabilities -- if the proxy declares capabilities, prefer plugins implementing all of them.
  5. Best-match fallback -- if no plugin implements every required capability, select the one with the highest score (most capabilities matched). Ties raise AmbiguousPluginError.
  6. Single match -- if exactly one candidate remains, return it.
  7. Multiple matches -- if fallback_to_default=True, try defaults. Otherwise raise AmbiguousPluginError.

Default Plugins

Plugins register as defaults via the decorator:

@register_connection_plugin(
    default_for_platform=True,
    default_for_connection_type=True,
)

Defaults are checked in order:

  1. (platform, connection_type) default -- checked first, but only when connection_type was specified.
  2. platform default -- checked second as a broader fallback.

Important

Defaults only participate when fallback_to_default=True is passed to get_connection() or connect(). Without this flag, multiple candidates always raise AmbiguousPluginError.


AmbiguousPluginError

This error is raised when multiple plugins match and no default can break the tie. The error message lists all matching plugins and their capabilities, plus resolution suggestions:

  • Specify connection_library explicitly.
  • Register a default with @register_connection_plugin(default_for_connection_type=True).

User Plugins vs SDK Plugins

The registry distinguishes plugins by module location. Any class defined within the neops_worker_sdk package is an SDK plugin; everything else is a user plugin.

Scenario Behavior
User default replaces SDK default Allowed -- logged at info level
SDK default tries to replace user default Skipped -- user takes precedence
Two user defaults for the same scope PluginRegistrationError
Two SDK defaults for the same scope PluginRegistrationError (SDK bug)

This means you can safely override any SDK default by registering your own plugin with default_for_platform=True or default_for_connection_type=True.


Capability Validation

After resolution, the proxy validates that the plugin implements all required capability methods (validate_capabilities=True by default). Missing methods are logged as warnings -- they do not block proxy creation. Calling a missing method at runtime raises NotImplementedForThisPlatform.


Common Gotchas

  1. Omitting connection_library creates ambiguity -- if both Scrapli and Netmiko plugins exist for "ios" + "ssh", you must either specify the library or opt into defaults.
  2. Best-match ties are not resolved by defaults -- when no plugin fully matches and multiple plugins tie on score, AmbiguousPluginError is raised immediately. Defaults only apply after capability filtering.
  3. Defaults require opt-in at the call site -- fallback_to_default=True must be passed explicitly.

Next Steps