Build a Rust Native Plugin

View as Markdown

Use the nemo-relay-plugin crate to create an in-process native plugin without writing the C ABI by hand. The SDK exports the stable ABI entry point and provides typed helpers for the supported registration surfaces.

This example builds a native plugin that registers an event subscriber. The repository also includes an extended example in examples/rust-native-plugin with validation, middleware, marks, scopes, and a configuration schema.

Create the Project

Create a Rust library project with this Cargo.toml file:

1[package]
2name = "acme-native-policy"
3version = "0.1.0"
4edition = "2024"
5
6[lib]
7crate-type = ["cdylib"]
8
9[dependencies]
10nemo-relay-plugin = "0.5.0"
11serde_json = "1"

Add the following implementation to src/lib.rs:

1use nemo_relay_plugin::{Json, NativePlugin, PluginContext, Result};
2use serde_json::Map;
3
4struct NativePolicy;
5
6impl NativePlugin for NativePolicy {
7 fn plugin_kind(&self) -> &str {
8 "acme.native_policy"
9 }
10
11 fn register(
12 &mut self,
13 _config: &Map<String, Json>,
14 context: &mut PluginContext<'_>,
15 ) -> Result<()> {
16 context.register_subscriber("audit", |_| {})
17 }
18}
19
20nemo_relay_plugin::nemo_relay_plugin!(nemo_relay_register_plugin, || NativePolicy);

Create the Manifest

Create relay-plugin.toml with the following content:

1manifest_version = 1
2
3[plugin]
4id = "acme.native_policy"
5kind = "rust_dynamic"
6
7[compat]
8relay = ">=0.5,<1.0"
9native_api = "1"
10
11[defaults]
12enabled = false
13
14[capabilities]
15items = ["plugin_native"]
16
17[source]
18artifact = "target/release/<platform-library-file>"
19
20[integrity]
21sha256 = "sha256:<artifact-sha256>"
22
23[load]
24library = "target/release/<platform-library-file>"
25symbol = "nemo_relay_register_plugin"

Update the library filename for your platform: use .dylib on macOS, .so on Linux, or .dll on Windows. Replace <platform-library-file> in both manifest fields with that filename.

Build, Register, and Validate

Build the library, calculate its digest, and register the plugin with the following commands. The digest command requires Python 3.

$cargo build --release
$python - <<'PY'
$from hashlib import sha256
$from pathlib import Path
$
$artifact = Path("target/release/<platform-library-file>")
$print(f"sha256:{sha256(artifact.read_bytes()).hexdigest()}")
$PY
$nemo-relay plugins add ./relay-plugin.toml
$nemo-relay plugins enable acme.native_policy
$nemo-relay plugins validate acme.native_policy

Use the following PowerShell command on Windows:

1$artifact = ".\\target\\release\\<platform-library-file>"
2$hash = (Get-FileHash -Algorithm SHA256 $artifact).Hash.ToLower()
3"sha256:$hash"

Replace <platform-library-file> in the digest command, then replace sha256:<artifact-sha256> with its output before you run plugins add. The command writes a [[plugins.dynamic]] manifest reference. Use nemo-relay plugins edit or edit that record to add component fields when the plugin accepts configuration.

Keep tests outside src, use the shared DTOs re-exported by nemo-relay-plugin, and do not retain host-owned ABI handles after a callback returns. Refer to Configure Discoverable Plugins for trust-policy configuration.