Nemo Relay Plugin Build
NVIDIAOfficialCreated by NVIDIA Corporation and Affiliates
- Skill
- Workflow
- Software development
- Apache-2.0
- Medium risk
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured approach to developing and deploying reusable runtime behaviors for NeMo Relay. It covers the lifecycle of plugin development, from choosing between embedded components or dynamic packages (native Rust or gRPC workers) to implementing deterministic configuration validation and safe registration via PluginContext. The focus is on maintaining clean separation between reusable plugin logic and application startup code, ensuring robust error handling, and adhering to version-specific compatibility requirements.
What it does
- Defines the process for creating embedded or dynamic NeMo Relay plugins.
- Outlines requirements for deterministic, side-effect-free configuration validation.
- Provides patterns for safe runtime behavior registration using PluginContext.
- Details delivery models including native Rust dynamic libraries and gRPC workers.
- Specifies version-dependent callback and executor handling for Relay 0.7 and 0.8.
- Establishes best practices for configuration schema design and error diagnostics.
When to use it
- When you need to package reusable runtime behavior (e.g., guardrails, intercepts) across multiple applications.
- When behavior should be activated and managed via shared configuration rather than hardcoded startup logic.
- When you need to implement stable, versioned plugin kinds with clear activation lifecycles.
- When you are developing native Rust extensions or gRPC-based worker plugins for NeMo Relay.
Advantages
- Promotes modularity by separating reusable logic from application-specific startup code.
- Ensures system stability through deterministic validation and rollback-safe registration.
- Supports flexible deployment models ranging from embedded components to isolated dynamic packages.
- Provides clear guidance on handling version-specific API and executor constraints.
Usage examples
- “How do I package a new redaction guardrail as a reusable NeMo Relay plugin?”
- The agent will guide you through defining a stable 'kind' string, creating a JSON-compatible configuration schema, implementing validation logic that returns structured diagnostics, and using PluginContext to register the guardrail.
- “What is the correct way to implement a native Rust plugin for Relay 0.8?”
- The agent will explain the requirement to use the typed async SDK, configure the SDK-owned Tokio executor, and ensure the manifest reflects the correct SemVer compatibility range for Relay 0.8.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/nvidia/nemo-relay-plugin-build/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip nemo-relay-plugin-build.zip -d .agents/skills
Documentation by NVIDIA Corporation and Affiliates
Build a Plugin
Use this skill when a user wants to package reusable NeMo Relay runtime behavior behind plugin configuration. Keep reusable plugin behavior separate from one-off application startup code.
Use This When
Use this skill when the behavior should be activated by shared config and reused across applications, teams, or process startup paths.
Common cases:
Register subscribers, guardrails, intercepts, or a small bundle of related runtime behavior.
Validate operator-supplied config before changing runtime behavior.
Give reusable behavior a stable plugin
kindand activation lifecycle.Package behavior that should be enabled, disabled, or rolled out through plugin config rather than repeated application startup code.
Do Not Use This When
Do not build a plugin when a narrower NeMo Relay surface is enough:
One request or tenant needs temporary behavior -> use scope-local middleware.
The user only needs first-time scopes, tool calls, or LLM calls ->
nemo-relay-instrument-calls.The user only needs to choose an exporter path ->
nemo-relay-plugin-observability.The behavior depends on live callables, provider clients, file handles, credentials, or framework objects inside config.
Choose A Delivery Model
Choose the delivery model before designing config or registration:
Embedded component: Use the shared plugin document when behavior ships with the Relay host application. Follow the embedded component model below.
Discoverable dynamic package: Use a
relay-plugin.tomlmanifest when the plugin ships independently of the host. Userust_dynamicfor a trusted in-process native Rust library, orworkerfor a localgrpc-v1worker. Read the public native dynamic-plugin or gRPC worker guide before designing the package boundary. Do not reproduce native ABI or worker-protocol details from memory.
Native plugins are trusted C-ABI extensions that run in the Relay process and are not sandboxed. Worker plugins provide process isolation, not a security sandbox.
Embedded Component Model
Plugins package reusable process-level behavior.
A plugin exposes a stable
kindstring and receives component-local config from a shared plugin document.Plugin config must be JSON-compatible across Rust, Python, Node.js, files, tests, and deployment systems.
Validation is deterministic and side-effect free. It inspects config and returns structured diagnostics before runtime behavior changes.
Registration runs after validation and installs real behavior through
PluginContext, such as subscribers, guardrails, request intercepts, execution intercepts, or stream execution intercepts.PluginContextgives the plugin system enough ownership to qualify runtime names and roll back partial setup when activation fails.Disabled components should still validate when possible so operators can find config problems before rollout.
Default Path
Decide whether a plugin is actually needed. Prefer direct instrumentation or scope-local behavior when the use case is not reusable process-level behavior.
Choose an embedded component or a discoverable dynamic package. For a dynamic package, establish the manifest-backed native or worker boundary before implementing behavior.
For native dynamic plugins, determine the target Relay version from the package constraint, lockfile, or deployment target before choosing callback APIs.
Pick one first runtime surface: subscriber-oriented export, sanitize guardrail, conditional guardrail, request intercept, execution intercept, or stream execution intercept.
Choose a stable plugin
kindand the smallest JSON-compatible config shape.Define diagnostics for missing fields, unsupported values, unknown fields, unsafe config, and invalid field combinations.
Validate config before initialization. Validation must not open network connections, create clients, register middleware, or mutate process state.
If validation returns error diagnostics, return them and stop without initialization or registration.
Register runtime behavior through
PluginContext, not by hand-registering global behavior inside application startup.Test activation, disabled components, validation failures, and registration failure rollback.
Document how to enable the plugin, what config fields are supported, and how to roll back the component.
For a dynamic plugin that should provide structured fields in
nemo-relay plugins edit, declare theconfig_schemacapability and reference a local Draft 7 or Draft 2020-12 JSON Schema file from[config_schema].pathinrelay-plugin.toml. Schema-less plugins remain editable as raw JSON objects.
Config Shape
The top-level plugin document contains version, components, and policy.
Each component supplies the plugin kind, enabled, and component-local
config:
{
"version": 1,
"components": [
{
"kind": "redaction-policy",
"enabled": true,
"config": {
"preset": "strict"
}
}
],
"policy": {
"unknown_component": "warn",
"unknown_field": "warn",
"unsupported_value": "error"
}
}Keep business logic in plugin code, not in config. Use references to secrets or endpoints rather than embedding sensitive values.
Binding Pointers
Python:
nemo_relay.pluginNode.js:
nemo-relay-node/pluginRust:
nemo_relay::pluginGo and raw FFI are source-first or advanced surfaces.
Use the same canonical snake_case config keys across bindings and files. Node
helper functions can be camelCase, but plugin config objects remain
snake_case.
Dynamic Package Essentials
Keep the manifest package contract separate from the operator's plugin document.
The manifest must declare the lane-specific kind and load contract, a normal
SemVer Relay compatibility range, artifact integrity, and only the capabilities
the plugin needs. Use a local config_schema only when structured CLI editing
is needed.
Native Version Compatibility
Choose the native callback model from the target Relay version; do not present the 0.8 SDK as source-compatible with 0.7:
Relay 0.7: Keep typed Rust middleware callbacks synchronous. Use the raw native ABI v3 completion-based registration path only when asynchronous work is required, and constrain the manifest to
compat.relay = ">=0.7,<0.8".Relay 0.8: Return futures through the typed Rust SDK and constrain the manifest to
compat.relay = ">=0.8.0,<1.0". The SDK runs typed middleware on an SDK-owned Tokio executor; subscribers and raw synchronous ABI registrations remain synchronous. Do not block executor workers. Scope context does not automatically propagate to tasks created withtokio::spawn, and teardown must stop new callbacks and drain accepted work before unload.
The 0.8 typed SDK lets native components configure its executor with a positive
executor.worker_threads value. When their manifest exposes a
config_schema, include that SDK-owned object and field in the schema. For
native ABI details, callback settlement or cancellation, and the full worker
protocol, use the relevant public dynamic-plugin guide rather than expanding
this skill.
Failure Modes To Avoid
Do not put callables, clients, credentials, framework objects, file handles, or caches in plugin config.
Do not perform runtime registration during validation.
Do not skip validation for disabled components.
Do not register directly through global startup code when
PluginContextshould own the runtime behavior.Do not combine unrelated subscribers, request transforms, and policy checks in the first plugin unless one config document clearly owns the bundle.
Do not export raw production payloads or secrets. Add telemetry sanitization before data leaves the process.
Do not ignore partial activation failures. Roll back or surface a clear diagnostic.
Do not treat native process isolation as a security boundary, or claim that a worker is sandboxed.
Do not apply the 0.8 typed-async callback contract to Relay 0.7, or the 0.7 raw completion contract to typed 0.8 middleware.
Do not block the 0.8 SDK-owned executor.
Validation Checklist
[ ] Stable plugin
kindchosen.[ ] Delivery model selected: embedded component,
rust_dynamic, orworker.[ ] Config shape is JSON-compatible and uses
snake_case.[ ] Required fields and unsupported values produce stable diagnostics.
[ ] Unknown fields follow the configured policy.
[ ] Disabled components still report config problems where possible.
[ ] Initialization installs behavior through
PluginContext.[ ] A forced registration failure does not leave partial runtime behavior active.
[ ] Docs or examples show how to enable and roll back the plugin.
[ ] Dynamic plugins that need structured CLI editing package a valid local JSON Schema and declare
config_schemainrelay-plugin.toml.[ ] Dynamic manifests validate their lane-specific kind, load contract, SemVer compatibility, integrity, and disabled-record behavior.
[ ] Native callback APIs and compatibility constraints match the target Relay version: synchronous typed callbacks and raw ABI v3 completion work for 0.7; typed async SDK middleware and executor configuration for 0.8.
[ ] Async native paths cover cancellation, settlement, and drain-before- unload behavior.
Use Another Skill When
You only need to wrap direct tool or LLM calls ->
nemo-relay-instrument-callsYou need to set up traces or exporters without packaging a plugin ->
nemo-relay-plugin-observabilityYou need to debug plugin activation, missing events, or load failures ->
nemo-relay-debug-runtime-integration
Files
- ATTRIBUTION.mdAdded by AutoGineer954 B
- BENCHMARK.md4.6 KiB
- LICENSELicence file added by AutoGineer11.2 KiB
- SKILL.md10.0 KiB
- evals/evals.json10.5 KiB
- skill-card.md4.0 KiB
- skill.oms.sig4.5 KiB
evals/evals.json
[
{
"id": "nemo-relay-plugin-build-001",
"question": "I want to use the nemo-relay-plugin-build skill to create a plugin that registers a sanitization guardrail. The plugin kind should be 'pii-sanitizer' and it needs config fields for 'patterns' (array of regex strings) and 'action' (either 'redact' or 'mask'). Can you walk me through building this?",
"expected_skill": "nemo-relay-plugin-build",
"expected_script": null,
"ground_truth": "The agent used nemo-relay-plugin-build to guide the user through creating a 'pii-sanitizer' plugin with a JSON-compatible config shape containing 'patterns' and 'action' fields, deterministic validation logic, registration through PluginContext, and rollback-safe behavior.",
"expected_behavior": [
"The agent read the nemo-relay-plugin-build SKILL.md before providing guidance",
"The agent defined a JSON-compatible config shape with 'patterns' (array of strings) and 'action' (enum of 'redact' or 'mask') fields",
"The agent provided validation logic that checks for missing fields, invalid regex patterns, and unsupported 'action' values without side effects",
"The agent returned error diagnostics and stopped before initialization or registration when validation failed",
"The agent showed registration of the guardrail through PluginContext with rollback handling for partial setup failures",
"The agent did not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
},
{
"id": "nemo-relay-plugin-build-002",
"question": "I have a set of runtime guardrails and subscribers that multiple teams keep copy-pasting into their NeMo Relay application startup code. I want to package this as a reusable component that can be activated through shared configuration, validated before deployment, and safely rolled back if registration fails. How should I structure this?",
"expected_skill": "nemo-relay-plugin-build",
"expected_script": null,
"ground_truth": "The agent identified this as a plugin packaging use case and guided the user through the nemo-relay-plugin-build workflow: choosing a stable plugin kind, defining minimal JSON-compatible config, implementing side-effect-free validation with structured diagnostics, and registering behavior through PluginContext with rollback safety.",
"expected_behavior": [
"The agent recognized the need for a reusable config-activated plugin rather than scope-local middleware or direct instrumentation",
"The agent outlined the plugin document structure including version, components array with kind/enabled/config, and policy settings",
"The agent described validation requirements as deterministic and side-effect free, returning structured diagnostics before any runtime changes",
"The agent explicitly stopped initialization and registration when validation returned error diagnostics",
"The agent explained how PluginContext handles registration and rollback of partial setup on failure",
"The agent did not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
},
{
"id": "nemo-relay-plugin-build-003",
"question": "Our platform team is rolling out a new compliance requirement: all NeMo Relay services must apply a content-filtering policy that can be toggled per environment (dev/staging/prod) through config. We need operators to get clear error messages if they misconfigure it, and we need the ability to disable it in dev without breaking validation. The filter should intercept requests before they reach the LLM. What's the best approach?",
"expected_skill": "nemo-relay-plugin-build",
"expected_script": null,
"ground_truth": "The agent applied the nemo-relay-plugin-build skill to design a content-filtering plugin with a request intercept surface, environment-aware config with an 'enabled' toggle, validation that runs even when disabled to catch config errors before rollout, and clear diagnostic messages for operators.",
"expected_behavior": [
"The agent selected request intercept as the runtime surface for pre-LLM content filtering",
"The agent designed config with an 'enabled' field and environment-specific settings while keeping the shape JSON-compatible",
"The agent specified that validation runs even for disabled components so operators discover config problems before production rollout",
"The agent provided examples of structured diagnostics for missing fields, unsupported environment values, and invalid field combinations",
"The agent returned validation errors without registering the request intercept, including when the component was disabled",
"The agent did not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
},
{
"id": "nemo-relay-plugin-build-004",
"question": "I need to add some temporary logging for a specific tenant's requests in NeMo Relay. It should only apply to their session and I'll remove it after debugging. What's the best way to do this?",
"expected_skill": null,
"expected_script": null,
"ground_truth": "The agent correctly identified that this is a scope-local middleware use case rather than a plugin, since the behavior is temporary, tenant-specific, and not reusable across applications or teams. The agent directed the user toward scope-local middleware or direct instrumentation instead of nemo-relay-plugin-build.",
"expected_behavior": [
"The agent did NOT invoke the nemo-relay-plugin-build skill for this temporary, tenant-scoped task",
"The agent explained that scope-local middleware is more appropriate for temporary per-tenant behavior",
"The agent suggested an alternative approach such as scope-local middleware or nemo-relay-instrument-calls for this use case",
"The agent did not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
},
{
"id": "nemo-relay-plugin-build-005",
"question": "We distribute a Rust cdylib that adds asynchronous request and LLM intercepts to NeMo Relay 0.8 hosts. I need a manifest-backed plugin package with a configurable Tokio worker count and a form-friendly config editor. How should I package and validate it?",
"expected_skill": "nemo-relay-plugin-build",
"expected_script": null,
"ground_truth": "The agent chooses the discoverable rust_dynamic path, gives the essential 0.8 manifest and async SDK constraints, and routes detailed native ABI implementation to the public native dynamic-plugin guide.",
"expected_behavior": [
"The agent distinguishes a manifest-backed rust_dynamic package from an embedded component and identifies native plugins as trusted in-process extensions",
"The agent requires compat.relay = '>=0.8.0,<1.0' for typed async native middleware and keeps subscribers and raw synchronous ABI registrations synchronous",
"The agent describes an SDK-owned Tokio executor, a positive executor.worker_threads configuration value, non-blocking work, and drain-before-unload behavior",
"The agent requires the manifest's compatibility, load contract, integrity, and config_schema capability/path, with executor fields included in the schema when structured editing is exposed",
"The agent routes raw ABI settlement, cancellation, and protocol-level details to the public native dynamic-plugin guide rather than inventing them",
"The agent does not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
},
{
"id": "nemo-relay-plugin-build-006",
"question": "I want to ship a Python policy extension separately from the Relay host so operators can register it from a relay-plugin.toml file. The policy should run in a local process and intercept requests. What package model and safety guidance should I use?",
"expected_skill": "nemo-relay-plugin-build",
"expected_script": null,
"ground_truth": "The agent chooses a manifest-backed worker plugin, identifies grpc-v1 as the stable worker boundary, and routes detailed worker protocol authoring to the public worker guides.",
"expected_behavior": [
"The agent selects plugin.kind = 'worker' rather than an embedded component or rust_dynamic package",
"The agent identifies grpc-v1 as the worker boundary and requires lane-appropriate compatibility, load contract, capabilities, and artifact integrity in the manifest",
"The agent explains that a worker provides process isolation but is not a security sandbox",
"The agent keeps component config JSON-compatible, validates it without side effects, and registers behavior only after successful validation",
"The agent routes detailed gRPC protocol, worker activation, authentication, cancellation, and shutdown behavior to the public worker guides",
"The agent does not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
},
{
"id": "nemo-relay-plugin-build-007",
"question": "We need to distribute a Rust native plugin for NeMo Relay 0.7. It adds a synchronous policy guardrail today, but may perform asynchronous work later. How should its package and middleware guidance differ from a 0.8 plugin?",
"expected_skill": "nemo-relay-plugin-build",
"expected_script": null,
"ground_truth": "The agent chooses the rust_dynamic package path, preserves synchronous typed middleware for Relay 0.7, and distinguishes its raw ABI v3 completion path from Relay 0.8 typed async SDK middleware.",
"expected_behavior": [
"The agent selects a manifest-backed rust_dynamic package and identifies native plugins as trusted in-process extensions",
"The agent constrains a Relay 0.7-only plugin with compat.relay = '>=0.7,<0.8' and keeps typed Rust middleware callbacks synchronous",
"The agent identifies the raw native ABI v3 completion-based registration path as the 0.7 option for asynchronous work, without inventing low-level ABI mechanics",
"The agent distinguishes Relay 0.8 typed future-based middleware and its SDK-owned Tokio executor from the Relay 0.7 contract",
"The agent requires normal manifest compatibility, load contract, integrity, and deterministic config validation before registration",
"The agent does not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
}
]
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Node.js
Security
What our scanner noticed· Medium risk
- Large base64-encoded blobs
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- NVIDIA Corporation and Affiliates
- Publisher
- NVIDIA (Official)
- Source
- NVIDIA/skills · skills/nemo-relay-plugin-build · commit fce3cca
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE-APACHE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by NVIDIA Corporation and Affiliates or NVIDIA.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download nemo-relay-plugin-build.zip