diff --git a/docs/build-plugins/plugin-configuration-files.mdx b/docs/build-plugins/plugin-configuration-files.mdx index 803cb7e0d..e9c088133 100644 --- a/docs/build-plugins/plugin-configuration-files.mdx +++ b/docs/build-plugins/plugin-configuration-files.mdx @@ -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. NeMo Relay plugin configuration keys use `snake_case` regardless of language or @@ -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: @@ -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. | @@ -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` @@ -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 @@ -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. @@ -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. @@ -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]] @@ -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`. @@ -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