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
- Filter by platform -- only plugins registered for
device.platformsurvive. - Filter by connection_type -- if provided, narrows to that type. If omitted, all types for the platform remain.
- Filter by connection_library -- if provided, exact match. If omitted, all libraries for the platform+type remain.
- Filter by capabilities -- if the proxy declares capabilities, prefer plugins implementing all of them.
- Best-match fallback -- if no plugin implements every required capability, select the one with the highest score (most capabilities matched). Ties raise
AmbiguousPluginError. - Single match -- if exactly one candidate remains, return it.
- Multiple matches -- if
fallback_to_default=True, try defaults. Otherwise raiseAmbiguousPluginError.
Default Plugins
Plugins register as defaults via the decorator:
Defaults are checked in order:
- (platform, connection_type) default -- checked first, but only when
connection_typewas specified. - 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_libraryexplicitly. - 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
- Omitting
connection_librarycreates ambiguity -- if both Scrapli and Netmiko plugins exist for"ios" + "ssh", you must either specify the library or opt into defaults. - Best-match ties are not resolved by defaults -- when no plugin fully matches and multiple plugins tie on score,
AmbiguousPluginErroris raised immediately. Defaults only apply after capability filtering. - Defaults require opt-in at the call site --
fallback_to_default=Truemust be passed explicitly.
Next Steps
- Writing Plugins -- implement a new plugin
- Architecture Deep Dive -- resolution internals