Package Discoverable Plugins
A discoverable plugin is a package containing one relay-plugin.toml manifest, its
native library or worker entrypoint, and an optional component JSON Schema. The manifest
lets Relay validate compatibility and integrity before code is loaded or a process is
started. Runtime activation still comes from a component in plugins.toml or an
equivalent binding configuration.
Manifest Responsibilities
For native packages, compat.native_api = "1" is the authored manifest contract. It is
not the C host-table ABI number. The
current SDK requests ABI v4 and the host retains frozen v3 and v2 compatibility for
older compiled plugins. For workers, declare compat.worker_protocol = "grpc-v1"; the
handshake still negotiates the exact
protocol, surfaces, authentication token, and lifecycle at startup.
Start from a Complete Manifest
These are the complete manifest shapes used by the checked examples. The path in
source.artifact is the file whose bytes the digest covers. The native loader opens that
same library; a worker loader either starts the compiled program or imports the Python
entrypoint from the managed environment.
Python Worker
Native Rust
Rust Worker
The Python package has one extra responsibility: source.manifest_root identifies the
directory Relay installs into its managed environment. The digest still covers only the
declared artifact, so regenerate it whenever worker.py changes. A compiled worker has
no managed Python environment and starts the executable named by load.entrypoint.
Relay 0.8 keeps grpc-v1 as the worker protocol identifier, but changes its tool-result
messages. Both worker manifests therefore begin their Relay compatibility range at
0.8.0. Rebuild SDK workers and regenerate bindings in a custom worker before packaging;
the unchanged protocol name does not make an earlier worker wire-compatible.
Package and Register the Artifact
Use the following procedure to turn the checked manifest template into an artifact that Relay can validate and activate:
-
Build the shared library or worker from a clean checkout and place the entrypoint at the relative path declared by
relay-plugin.toml. -
Validate the component schema against valid, invalid, and disabled example configurations. Keep unknown-field behavior aligned between the schema and the plugin’s validation callback.
-
Generate the artifact digest with
shasum -a 256 <artifact>on macOS,sha256sum <artifact>on Linux, orGet-FileHash -Algorithm SHA256 <artifact>in PowerShell. Do this after the finalsource.artifactbytes are in place; changing that artifact invalidates the digest.For example, this Linux command materializes a usable Rust worker manifest without changing the checked template:
The local manifest is deliberately untracked. Rebuilding the executable changes its bytes, so recalculate the digest before every validation attempt.
-
Validate the materialized manifest. For the compiled example above, run
nemo-relay plugins validate ./relay-plugin.local.toml. The Python example keeps its checked digest and uses./relay-plugin.tomldirectly. A successful command confirms manifest structure, compatibility syntax, entrypoint resolution, schema loading, and integrity metadata without activating the component. -
Register the same path with
nemo-relay plugins add --user <materialized-manifest>, or add an explicit[[plugins.dynamic]]reference to the intendedplugins.toml. -
Activate a valid component, inspect the runtime report, execute a representative managed call, then clear and unload or stop the plugin.
Success means package validation passes before activation, tampering causes integrity validation to fail, the runtime report identifies the dynamic component, and teardown removes its registrations before the library unloads or worker exits. The operator-side trust policy and file layout are documented in Configure Discoverable Plugins.