Skip to main content
A plugin declares parameters under gcs.contributes.parameters[] (or nested inside a settings section). The GCS renders each as a native, dark-themed control, validates and clamps the committed value against the schema, and writes it to the binding you name. No iframe, no custom form code. A parameter has three parts:
schema is the only required part beyond key. A missing or malformed schema drops the parameter at parse time (with a console warning); the rest of the manifest still loads.

schema: the data contract

schema is a Draft-07 JSON-Schema subset, deliberately scoped to what a drone-plugin parameter needs. Unknown keywords are ignored (forward-compatible), never an error. Validation and clamping. On every commit the host validates the value against the schema. Numbers are clamped to [minimum, maximum] and quantized to step; an integer is rounded. A string is checked against pattern. An enum value must be a member. An invalid value is rejected and the control reverts; a clampable value is clamped silently.
integer is a schema type, not a widget. Both number and integer render with the number (or range) widget; integer adds the round-to-whole rule on commit.

ui: the presentation layer

ui never affects validation. It only controls how a parameter is shown and grouped.

Widgets

When ui.widget is omitted, the host infers: an enum schema becomes the enum widget, a boolean becomes boolean, a number/integer becomes number, and everything else becomes string.

Grouping and conditional reveal

Parameters are grouped by ui.group (groups order by first appearance, controls within a group by ui.order then declaration order). A control with visible_if shows only when the referenced parameter’s committed value matches.

binding: where the value is written

The binding field routes the committed value. It defaults to plugin.config when absent.
On a plugin.config commit the host writes optimistically and rolls the control back if the agent does not accept the write, so the surface never shows a value the agent rejected.

The model parameter: switch the vision detector

A model (or model_upload) parameter binds to engine.detector and renders the board-filtered model picker. Selecting a model switches the drone’s active vision detector engine-wide; every vision consumer on that drone then runs against the new model.
When the operator picks a model, the picker writes the engine-wide detector on the agent directly and reports the new active id back, so no second write happens and there is no optimistic rollback for this widget. Use model_upload instead of model when you want the operator to be able to upload their own model file.
A model widget needs a drone context to write to. On a detached preview (no selected drone) it falls back to a read-only display of the current value rather than rendering a picker with nowhere to write.

Full worked example

A small follow-behavior plugin’s parameter block, mixing a range, a toggle, a conditional enum, and a model switch:

Next steps

Contribution points

The settings and parameters contributions in context.

Scaffolder walkthrough

A plugin that contributes parameters end to end.

Vision plugins

How the engine detector is consumed on the agent.

Lifecycle

How the agent half reads live config.
Last modified on October 11, 2026