agentleFS
NVIDIAKnown publisherNVIDIA/NeMo-Relay/skills/nemo-relay-plugin-build/SKILL.md

nemo-relay-plugin-build

Skill238 starsChanged 2 months agoApache-2.0View on GitHub

Use this skill when building or packaging reusable NeMo Relay runtime behavior as an embedded configuration component or a manifest-backed `rust_dynamic` native or `worker` gRPC plugin, with deterministic validation and rollback-safe registration.

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

24 rules. About 0 are common, 20 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈20

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use this skill when a user wants to package reusable NeMo Relay runtime behavior behind plugin configuration.

    line 11
  2. Distinctive:

    Keep reusable plugin behavior separate from one-off application startup code.

    line 13
  3. Distinctive:

    Use this skill when the behavior should be activated by shared config and reused across applications, teams, or process startup paths.

    line 17
  4. Distinctive:

    Do not build a plugin when a narrower NeMo Relay surface is enough:

    line 31
  5. Distinctive:

    Embedded component: Use the shared plugin document when behavior ships with the Relay host application.

    line 45
  6. Very specific:

    Discoverable dynamic package: Use a relay-plugin.toml manifest when the plugin ships independently of the host.

    line 47
  7. Distinctive:

    Read the public native dynamic-plugin or gRPC worker guide before designing the package boundary.

    line 50
  8. Distinctive:

    If validation returns error diagnostics, return them and stop without initialization or registration.

    line 94
  9. Distinctive:

    Test activation, disabled components, validation failures, and registration failure rollback.

    line 98
  10. Distinctive:

    Document how to enable the plugin, what config fields are supported, and how to roll back the component.

    line 100
  11. Distinctive:

    Keep business logic in plugin code, not in config.

    line 134
  12. Very specific:

    Use the same canonical snake_case config keys across bindings and files.

    line 144
  13. Distinctive:

    Keep the manifest package contract separate from the operator's plugin document.

    line 150
  14. Very specific:

    Relay 0.7: Keep typed Rust middleware callbacks synchronous.

    line 161
  15. Distinctive:

    Do not put callables, clients, credentials, framework objects, file handles, or caches in plugin config.

    line 180
  16. Distinctive:

    Do not perform runtime registration during validation.

    line 182
  17. Distinctive:

    Do not skip validation for disabled components.

    line 183
  18. Very specific:

    Do not register directly through global startup code when PluginContext should own the runtime behavior.

    line 184
  19. Distinctive:

    Do not combine unrelated subscribers, request transforms, and policy checks in the first plugin unless one config document clearly owns the …

    line 186
  20. Distinctive:

    Do not export raw production payloads or secrets.

    line 188
  21. Distinctive:

    Do not ignore partial activation failures.

    line 190
  22. Distinctive:

    Do not treat native process isolation as a security boundary, or claim that a worker is sandboxed.

    line 192
  23. Distinctive:

    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.

    line 194
  24. Distinctive:

    Do not block the 0.8 SDK-owned executor.

    line 196

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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 kind and 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.toml manifest when the plugin ships independently of the host. Use rust_dynamic for a trusted in-process native Rust library, or worker for a local grpc-v1 worker. 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 kind string 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.
  • PluginContext gives 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

  1. Decide whether a plugin is actually needed. Prefer direct instrumentation or scope-local behavior when the use case is not reusable process-level behavior.
  2. Choose an embedded component or a discoverable dynamic package. For a dynamic package, establish the manifest-backed native or worker boundary before implementing behavior.
  3. For native dynamic plugins, determine the target Relay version from the package constraint, lockfile, or deployment target before choosing callback APIs.
  4. Pick one first runtime surface: subscriber-oriented export, sanitize guardrail, conditional guardrail, request intercept, execution intercept, or stream execution intercept.
  5. Choose a stable plugin kind and the smallest JSON-compatible config shape.
  6. Define diagnostics for missing fields, unsupported values, unknown fields, unsafe config, and invalid field combinations.
  7. Validate config before initialization. Validation must not open network connections, create clients, register middleware, or mutate process state.
  8. If validation returns error diagnostics, return them and stop without initialization or registration.
  9. Register runtime behavior through PluginContext, not by hand-registering global behavior inside application startup.
  10. Test activation, disabled components, validation failures, and registration failure rollback.
  11. Document how to enable the plugin, what config fields are supported, and how to roll back the component.
  12. For a dynamic plugin that should provide structured fields in nemo-relay plugins edit, declare the config_schema capability and reference a local Draft 7 or Draft 2020-12 JSON Schema file from [config_schema].path in relay-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.plugin
  • Node.js: nemo-relay-node/plugin
  • Rust: nemo_relay::plugin
  • Go 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 with tokio::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 PluginContext should 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 kind chosen.
  • Delivery model selected: embedded component, rust_dynamic, or worker.
  • 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_schema in relay-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-calls
  • You need to set up traces or exporters without packaging a plugin -> nemo-relay-plugin-observability
  • You need to debug plugin activation, missing events, or load failures -> nemo-relay-debug-runtime-integration

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.