Resolution, Defaults, and Ambiguity (How Plugins Are Selected)
This page explains how a ConnectionProxy selects a plugin and what happens when resolution is ambiguous or incomplete.
- For concepts: 30-device-connections.md
- For basic usage: 31-connection-methods.md
- For writing capabilities/proxies: 33-writing-capabilities-and-proxies.md
- For implementing plugins: 34-writing-base-plugins.md and 35-platform-plugins-and-defaults.md
Inputs to plugin resolution
When you call:
the resolver considers:
- platform: derived from
device.platform.short_name(preferred) ordevice.platform(string) - connection_type:
"ssh","api","netconf","restconf", … - connection_library:
"netmiko","scrapli","httpx","ncclient", … - required capabilities: the capability interfaces your proxy inherits from
Note: If
device.platformis missing or not a string and has no usableshort_name, resolution raisesConnectionValidationError.
Resolution algorithm (high level)
Step A: filter by platform / type / library
Candidates are pulled from the registry based on the provided criteria:
- if you specify a library, it’s an exact match
- if you omit the library, all libraries for that platform+type are candidates
- if you omit connection_type, all plugins for the platform are candidates (rarely what you want)
Step B: filter by required capabilities
If your proxy declares required capabilities, the resolver prefers plugins that implement all of them.
Step C: if no plugin fully matches → best-match fallback
If no plugin implements all required capabilities, the resolver selects the best-match plugin (the one implementing the most required capabilities).
- it logs a warning describing the selection, missing capabilities, and other candidates
- the resulting proxy may still raise
NotImplementedForThisPlatformif you call a missing capability method (see 33-writing-capabilities-and-proxies.md)
If multiple plugins tie for best score, the resolver raises AmbiguousPluginError.
Ambiguity is explicit
If multiple plugins qualify after filtering (and after capability filtering/best-match selection), resolution is not silent:
- if
fallback_to_default=False(default): raiseAmbiguousPluginError - if
fallback_to_default=True: try to select a configured default plugin
This is a deliberate design choice to avoid accidentally picking the wrong backend library.
Defaults (platform vs platform+type)
Plugins can register defaults via the registry decorator:
default_for_platform=True: default for the entire platform (used when type/library are not specified)default_for_connection_type=True: default for(platform, connection_type)(used when library is not specified)
Defaults are only used when you pass fallback_to_default=True.
Default selection checks in this order:
(platform, connection_type)default (only ifconnection_typewas specified)platformdefault
Warning: Defaults are used to resolve ambiguity between multiple qualifying plugins after capability filtering (including best-match selection) has completed.
Defaults are not used to break best-match ties when no plugin fully matches the required capabilities. In that case, best-match ties raise
AmbiguousPluginErrorimmediately and you must resolve ambiguity explicitly.
Default override rules
Only one default can be active per scope (platform or platform+connection_type). The SDK distinguishes plugins by their module location (SDK package vs your app code):
- User overrides SDK: If you register a default that conflicts with an SDK default, your plugin silently replaces it. A log message confirms the override.
- SDK yields to user: If an SDK plugin tries to register a default but a user default already exists, the SDK plugin is skipped.
- User vs user conflict: If two user-defined plugins both try to register as default for the same scope, registration fails with
PluginRegistrationError. - SDK vs SDK conflict: Same as user vs user - raises
PluginRegistrationError(indicates an SDK bug).
Detection is automatic based on module path. Any plugin defined within the SDK package is treated as an SDK plugin; plugins defined elsewhere are treated as user plugins. This means you can safely subclass SDK plugins - your subclass will still be identified as a user plugin.
What “validate_capabilities” does (and doesn’t do)
validate_capabilities=True (default) warns early when the resolved plugin doesn’t implement capability methods required by the proxy.
- it does not block creation
- it helps you notice that certain methods will raise at runtime
Missing capability calls raise NotImplementedForThisPlatform with rich context:
- proxy class name
- method name
- interface name
- platform / plugin / device id (when available)
Common “gotchas” (read before debugging)
- Omitting
connection_libraryoften creates ambiguity
If you have both Scrapli and Netmiko plugins registered for "ios"+"ssh", calling MyProxy.get_connection(device, "ssh") will usually be ambiguous unless you opted into defaults.
- Defaults require opt-in
You must pass fallback_to_default=True to let defaults participate.
- Best-match can “work” but still fail later
Best-match selection keeps workflows moving, but if you call a missing method you’ll get NotImplementedForThisPlatform. Use capability validation warnings and proxy overrides to make this predictable.
- Missing third-party dependencies fail at runtime
Base plugins lazy-import dependencies inside BaseConnection.connect(). Missing libraries raise ConnectionCreationError at connection time (not during module import).