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. Because there is no config read-back, a freshly-loaded plugin.config control shows the schema default until the operator commits a value.

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:

See also