Discoverable Plugins

View as Markdown

Use discoverable plugins when you need to package reusable behavior outside the Relay host binary. A package includes a relay-plugin.toml manifest and one of two execution lanes:

LaneUse whenStable boundary
rust_dynamicBehavior must run in the Relay process.Versioned native ABI (v2–v4)
workerBehavior should run in a separate local process.grpc-v1

The manifest describes compatibility, capabilities, artifact integrity, and the load contract. Operators register the manifest reference and component configuration in plugins.toml, then enable the plugin through the CLI lifecycle. Keep the package contract separate from the operator workflow: refer operators to Configure Discoverable Plugins.

Manifest Contract

Every manifest uses the common fields shown below, followed by lane-specific compatibility, capability, source, and load fields. This complete example defines a Python worker:

1manifest_version = 1
2
3[plugin]
4id = "acme.example"
5kind = "worker"
6
7[compat]
8relay = ">=0.8.0,<1.0"
9worker_protocol = "grpc-v1"
10
11[defaults]
12enabled = false
13
14[capabilities]
15items = ["plugin_worker"]
16
17[source]
18manifest_root = "."
19artifact = "acme_example/worker.py"
20
21[integrity]
22sha256 = "sha256:<artifact-sha256>"
23
24[load]
25runtime = "python"
26entrypoint = "acme_example.worker:main"

compat.relay is a normal SemVer requirement. Dynamic plugins on the Relay 0.8 canonical result baseline must exclude earlier Relay versions; use >=0.8.0,<1.0 unless you deliberately need a narrower or open-ended 0.8-or-newer range. The manifest is the plugin author’s compatibility assertion; it does not attest how an artifact was built. The 0.8 migration guide describes the required rebuild. Keep defaults.enabled = false: operators must enable a registered dynamic plugin explicitly. Declare only the capabilities the plugin needs. Add config_schema.path only with the config_schema capability.

The following requirements vary by execution lane:

Manifest areaNative dynamic pluginWorker plugin
plugin.kindrust_dynamicworker
compatnative_api = "1"worker_protocol = "grpc-v1"
capabilities.itemsIncludes plugin_nativeIncludes plugin_worker
loadlibrary and symbolruntime and entrypoint
source.manifest_rootOptionalRequired for runtime = "python"; nemo-relay plugins add uses it to create and retain the managed worker environment.

Relay 0.8 retains the native API 1 and grpc-v1 identifiers while establishing the canonical ToolExecutionResult contract. Native application JSON semantics and worker protobuf tool-result types change; see the 0.8 migration guide. Future incompatible contract changes must increment the corresponding native API or worker protocol version.

Use runtime = "python" for a module:function entrypoint, runtime = "rust" for a Rust executable, or runtime = "command" for another local executable that implements grpc-v1.

The CLI verifies source.artifact against integrity.sha256 during plugins add and plugins validate. After a native artifact or non-Python worker changes, update its digest and rerun validation. After Python worker source or dependency changes, remove and add the worker again so Relay rebuilds its managed environment. Native loading also verifies load.library against integrity.sha256. Add integrity.signature when an operator’s policy can require Ed25519 signature verification. Treat these fields as release artifacts: update the digest and signature whenever the declared artifact changes.

Choose a Discoverable Plugin Type

Discoverable plugins always use a manifest. Choose the guide that matches the manifest-backed package you distribute:

For the complete comparison of manifest-backed packages and in-process, code-driven language binding plugins, refer to Build Plugins.