Third-party adapter plugins¶
SchemaRouter supports installed third-party source adapters through Python entry points.
Plugin loading is opt-in because importing an installed entry point executes local Python code.
Package an adapter¶
A third-party package can declare:
The resolved object must satisfy the normal SourceAdapter contract:
An adapter instance, adapter class, or zero-argument factory is accepted.
Discover without importing¶
from schemarouter import discover_adapter_plugins
for plugin in discover_adapter_plugins():
print(plugin.name, plugin.value, plugin.distribution, plugin.version)
Discovery reads entry-point metadata only. It does not call EntryPoint.load().
Load explicitly¶
or:
from schemarouter import AdapterRegistry, load_adapter_plugins
registry = AdapterRegistry()
load_adapter_plugins(
registry,
allowlist={"graphql"},
)
An empty allowlist is rejected. Unknown requested names fail before any plugin is imported.
Runnable external-package example¶
The repository includes a tiny package that is deliberately separate from the
schemarouter distribution:
Its package metadata declares a real entry point:
[project.entry-points."schemarouter.adapters"]
demo_static = "schemarouter_demo_adapter:DemoStaticAdapter"
The quickstart checks the trust boundary directly:
discover_adapter_plugins()sees the entry-point metadata whileschemarouter_demo_adapteris still absent fromsys.modules;router.load_adapter_plugins(allowlist={"demo_static"})explicitly imports and registers it;router.add_url(..., kind="demo_static")compiles a normalToolSpecand trusted invoker;- normal planning, argument/output validation, field projection, and execution return
{"value": 5}.
The source URL is example.invalid and the adapter never performs network I/O. The URL exists only
to demonstrate that a plugin can recognize a structured source identifier while keeping the demo
deterministic.
Source:
examples/adapter_plugin_demo/
Downstream installed-wheel compatibility smoke¶
Required package CI also exercises the plugin from a separate clean virtual environment:
- build the SchemaRouter wheel;
- install that wheel into a fresh venv;
- install
examples/adapter_plugin_demoas a separate distribution with its realschemarouter.adaptersentry point; - run
scripts/downstream_adapter_plugin_smoke.py.
The smoke asserts that SchemaRouter was imported from the venv's site-packages, not from the
repository source tree. It then proves that metadata discovery does not import plugin code, explicit
allowlisting does import exactly the requested plugin, valid execution succeeds, an input violating
the registered JSON Schema is rejected, and a trusted local deny rule still blocks the
plugin-supplied invoker.
This is a downstream compatibility and authority-boundary smoke, not a provider-quality, routing-accuracy, or performance benchmark. It uses no network access and no credentials.
Security model¶
Treat adapter plugins like any other installed application dependency. They execute with the Python process's privileges once explicitly loaded.
SchemaRouter does not:
- auto-import every plugin it discovers;
- accept a wildcard/implicit allow-all mode;
- let remote schema content request plugin loading;
- let a planner or model choose which installed package to import.
After loading, the adapter still uses the same registry, policy, schema validation, and binding-drift boundaries as built-in adapters.
Protocol-specific recipes¶
For STAC, gRPC/Protobuf, SOAP/WSDL, and bounded AsyncAPI request/reply cases, see Protocol plugin recipes. The recipes explain when to prefer OpenAPI or typed Python wrappers, when a SourceAdapter plugin adds real value, and which streaming/event lifecycles must stay outside the ordinary ToolCall abstraction.