Basic Guide: Define a Plugin#
Use this guide when you want to package reusable NeMo Flow behavior as a plugin that can be activated from configuration.
What You Build#
You will define the plugin’s purpose, stable kind name, configuration boundary, runtime surfaces, and activation lifecycle. The result is a small plugin contract that can be validated and registered through the more focused follow-on guides.
Before You Start#
You need:
A reusable behavior that belongs outside one application call site.
A stable plugin kind name.
A JSON-compatible config shape.
A decision about which runtime surfaces the plugin installs.
A teardown plan for tests and applications that need to clear active configuration.
Plugin Shape and Requirements#
A plugin needs a stable shape before operators can activate it from config:
Requirement |
Why It Matters |
|---|---|
Stable |
The plugin registry uses this string to match config to implementation. |
JSON-compatible config |
Config must move across Python, Node.js, Rust, files, tests, and deployment systems. |
Validation hook |
Operators need diagnostics before runtime behavior changes. |
Registration hook |
Runtime behavior should be installed through |
Runtime ownership |
The plugin should clearly own subscribers, middleware, adaptive behavior, or a small bundle of related surfaces. |
Keep runtime objects out of config. Provider clients, callbacks, file handles, caches, and credentials should be created inside plugin code or resolved from safe references during registration.
What a Plugin Can Install#
A plugin can install one or more of these runtime surfaces:
Subscribers
Tool sanitize-request guardrails
Tool sanitize-response guardrails
Tool conditional-execution guardrails
Tool request intercepts
Tool execution intercepts
LLM sanitize-request guardrails
LLM sanitize-response guardrails
LLM conditional-execution guardrails
LLM request intercepts
LLM execution intercepts
LLM stream execution intercepts
Start with one surface. Add a bundle only when one configuration document clearly controls related behavior, such as a subscriber plus the request intercepts needed to add correlation metadata.
Registration Lifecycle#
The diagram below shows how plugin configuration turns into registered runtime behavior.
flowchart TB
Kind[Plugin kind<br/>registered once]
Config[Plugin config<br/>version + components + policy]
Validate{{Validate component config}}
Diagnostics[/Structured diagnostics/]
Initialize[Initialize enabled components]
Context[PluginContext<br/>component-scoped registrar]
Runtime[Runtime registrations<br/>subscribers + middleware]
Rollback[Rollback partial setup<br/>if initialization fails]
Kind --> Validate
Config --> Validate
Validate --> Diagnostics
Validate -->|valid or warning-only| Initialize
Initialize --> Context
Context --> Runtime
Initialize -->|error| Rollback
Context -->|registration error| Rollback
The lifecycle is staged: register the plugin kind, validate component config, initialize enabled components, and let PluginContext install runtime behavior. If registration fails partway through, the plugin system can roll back partial setup.
Keep the First Plugin Small#
The easiest first plugin is one of these:
A subscriber-oriented plugin that exports events.
A request-intercept plugin that adds one provider header.
A sanitize guardrail plugin that redacts one field family.
A policy plugin that registers one conditional-execution guardrail.
Avoid a first plugin that combines unrelated subscribers, request transforms, policy checks, and adaptive behavior. Multi-surface bundles are useful later, but they need stronger validation and rollout controls.
Minimal Config Contract#
The top-level config document has version, components, and policy. Each component chooses a plugin kind and passes component-local JSON config to that plugin.
{
"version": 1,
"components": [
{
"kind": "header-plugin",
"enabled": true,
"config": {
"header_name": "x-tenant",
"value": "tenant-a"
}
}
],
"policy": {
"unknown_component": "warn",
"unknown_field": "warn",
"unsupported_value": "error"
}
}
Use this document as the boundary between operator intent and plugin implementation. Keep business logic in the plugin code, not in the config parser.
Design Checklist#
Before you write the plugin implementation, answer these questions:
What is the stable plugin
kind?What runtime surface does it install first?
Which config fields are required?
Which fields are safe to expose as JSON?
What diagnostic should appear when each required field is missing?
What should happen when the component is disabled?
What should happen when registration fails halfway through?
Next Steps#
Use these links to continue from this workflow into the next related task.
Define validation behavior with Basic Guide: Validate Plugin Configuration.
Register runtime behavior with Basic Guide: Register Plugin Behavior.
Add rollout controls with Advanced Guide: Design Plugin Configuration.
Review complete examples in Code Examples.