Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 38 additions & 38 deletions docs/build-plugins/plugin-configuration-files.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ position: 4
SPDX-License-Identifier: Apache-2.0 */}


Use `plugins.toml` when the `nemo-relay` CLI gateway should activate plugins at
Learn how to use `plugins.toml` when the `nemo-relay` CLI gateway should activate plugins at
startup. The file contains the same generic plugin configuration document used
by the Rust, Python, and Node.js plugin APIs, but encoded as TOML at the file
root.

This page documents file discovery, precedence, merge behavior, editor behavior,
and conflict rules for the CLI gateway. Component-specific fields are documented
in the guide for each plugin component.
This tutorial demonstrates how to use file discovery, precedence, merge behavior, editor behavior,
and conflict rules for the CLI gateway. For each plugin component there are specific fields you
can configure to fit your needs.

<Note>
NeMo Relay plugin configuration keys use `snake_case` regardless of language or
Expand Down Expand Up @@ -56,7 +56,7 @@ The top-level fields are:
|---|---|---|
| `version` | `1` | Plugin configuration format version. Non-`1` versions fail validation by default. |
| `components` | `[]` | Ordered plugin components to validate and activate. |
| `policy` | warn unknown components and fields, error on unsupported values | Global validation policy. |
| `policy` | Warns unknown components and fields, error on unsupported values | Global validation policy. |

Each component has:

Expand All @@ -66,16 +66,17 @@ Each component has:
| `enabled` | `true` | Disabled components are validated but not initialized. |
| `config` | `{}` | Component-local configuration object. The shape depends on `kind`. |

The gateway reads only files named `plugins.toml`.
The gateway only reads files named `plugins.toml`.

## Discovery

The gateway resolves plugin configuration using two kinds of input: file and CLI
sources and an optional code-driven layer.
The gateway resolves plugin configuration using two kinds of input:
- File and CLI sources
- An optional code-driven layer

File and CLI configuration comes from one of three mutually exclusive source classes:

| Source | Use case |
| Source | Use Case |
|---|---|
| `plugins.toml` | Normal operator- and project-managed gateway plugin configuration. |
| `[plugins].config` in `config.toml` | Inline gateway config for small or generated setups. |
Expand All @@ -85,11 +86,11 @@ Use only one file and CLI source class for a given gateway run. The gateway fail
clearly if file-based plugin config and `--plugin-config` are both present, or if
`plugins.toml` and `[plugins].config` are both present.

When `--config path/to/config.toml` is supplied, plugin file discovery is scoped
to `path/to/plugins.toml`. Implicit system, project, and user plugin files are
not loaded for that run.
If you indicate `--config path/to/config.toml`, the plugin file discovery scopes
to `path/to/plugins.toml`. Implicit system, project, and user plugin files do not
load for that run.

When no explicit `--config` path is supplied, the gateway checks these
If you do not explicitly indicate the `--config` path, the gateway checks these
`plugins.toml` locations from lowest to highest precedence:

1. System: `/etc/nemo-relay/plugins.toml`
Expand All @@ -98,12 +99,12 @@ When no explicit `--config` path is supplied, the gateway checks these
3. User: `$XDG_CONFIG_HOME/nemo-relay/plugins.toml`, or
`~/.config/nemo-relay/plugins.toml` when `XDG_CONFIG_HOME` is not set

Missing files are skipped. If no plugin config source exists, the gateway starts
without process-level plugin activation.
If no plugin config source exists, the gateway starts
without process-level plugin activation and skips the missing files.

## Editing Files

Use the interactive editor for Observability and Adaptive plugin configuration:
Use the interactive editor for observability and adaptive plugin configuration:

```bash
nemo-relay plugins edit
Expand Down Expand Up @@ -156,7 +157,7 @@ menu to reset, clear, preview, or save.

## Precedence And Merge Behavior

When more than one `plugins.toml` file is discovered, later files have higher
After your CLI gateway discovers a `plugins.toml`, the files introduced thereafter have higher
precedence. User config overrides project config, and project config overrides
system config.

Expand Down Expand Up @@ -186,30 +187,28 @@ The effective Agent Trajectory Observability Format (ATOF) config keeps
`enabled` and `output_directory` from the system file and uses
`mode = "overwrite"` from the user file.

The top-level `components` array is special. Components are matched by `kind`
In the TOML file, the top-level `components` array is distinct as their components are matched by `kind`
across files. A higher-precedence component with the same `kind` merges into the
lower-precedence component. A component with a different `kind` is added to the
lower-precedence component. Then, a component with a different `kind` is added to the
effective configuration.

The `pricing` component has one additional merge rule: when both lower and
higher-precedence layers define `components.config.sources`, the
The `pricing` component has one additional merge rule where if both lower and
higher-precedence layers define `components.config.sources`, then the
higher-precedence sources are placed before lower-precedence sources instead of
replacing them. This lets a user or project file override one model while still
replacing them. This lets a user or project file override one model while
falling back to fleet-managed pricing from `/etc/nemo-relay/plugins.toml`.

Declare each `kind` at most once inside one `plugins.toml` file. Duplicate
component kinds in the same file fail before merge. Duplicate singleton
components that reach plugin validation also fail validation.
You can only declare `kind` once per `plugins.toml` file. Duplicate
component kinds in the same file and duplicate singleton
components that reach plugin validation fail validation.

Arrays inside component config are replaced by the higher-precedence value.
Tables inside component config merge recursively.

## Configuration Layering

Plugin settings can come from files and the code. The files are the
configuration base layer and the code sits on top of it. If there is a
conflict, the code will always take precedence over the files. The layering
process is as follows:
Plugin settings come from files and code. Files form the base layer; code sits
on top. When the two conflict, code wins. Layering works as follows:

1. Discover and merge the `plugins.toml` files from lowest to highest precedence
(system → project → user), using the [Precedence And Merge Behavior](#precedence-and-merge-behavior) rules above.
Expand All @@ -224,21 +223,22 @@ Files and code differ only in how they treat a setting you **omit**:
| `version`, `policy`, or the `enabled` flag of a component you declare | Inherited from a lower-precedence file | **Always taken from code** — its default if you did not set it |
| A whole component kind, or a key inside a component's `config` | Inherited from a lower-precedence file | Inherited from the file layer |

In other words, a file's gaps are filled by the layers beneath it, but code's
typed fields are never gaps — they always carry a value, so they always take precedence.
Only the open-ended parts of your code config (which components you include, and
the keys within each component's `config`) merge with the files.
The layers beneath a file fill its gaps. Code's typed fields are never gaps —
they always carry a value, so they always take precedence. Only the open-ended
parts of your code config which components you include, and the keys within
each component's `config` merge with the files.

Without a filesystem — for example, a WebAssembly (wasm) build no files are
Without a filesystem, such as a WebAssembly (wasm) build, no files are
read, so the base is empty and only your `initialize` config applies.

## Explicit Defaults And Overrides

The editor writes explicit defaults for edited Observability and Adaptive
The editor writes explicit defaults for edited observability and adaptive
sections. This is intentional. In a layered config model, omitting a field means
"inherit a lower precedence value"; it does not mean "delete that value."

For example, this user file disables ATOF even if a project file enables it:
For example, by entering the configuration below, the file disables ATOF
even if a project file enables it:

```toml
[[components]]
Expand All @@ -249,7 +249,7 @@ enabled = false
mode = "append"
```

The merged config may still contain inherited ATOF sibling fields such as
The merged config may still contain inherited ATOF sibling fields, such as
`output_directory`, but the runtime ignores the section because `enabled =
false`.

Expand Down Expand Up @@ -284,7 +284,7 @@ endpoints, and checks reachable OTLP endpoints when those settings are present.
For Pricing, doctor validates enabled file and inline sources and fails when a
source is unreadable or the catalog schema is invalid.

## Relationship To `config.toml`
## Relationship to `config.toml`

`config.toml` owns gateway and agent setup, such as upstream provider base URLs
and agent command configuration. `plugins.toml` owns reusable runtime behavior
Expand Down