oz0-plugin.yaml

Plugin sets and policies

Look up the fields for plugin sets and policies.

For: Plugin authors looking up manifest fields.

Look up the fields for plugin sets and policies.

members

A plugin of kind: set has no parts of its own. It lists plugins, each pinned to an exact version and source, with settings and model mappings it suggests, and evals that run them together. Installing a set installs its members as one decision; afterwards they are ordinary plugins.

oz0-plugin.yaml
apiVersion: oz0/v1
name: starter
version: 1.0.0
kind: set
description: The connectors and the capabilities that use them, evaluated together
members:
  - plugin: github
    version: 1.4.2
    source: hub:ai.oz0/github
    settings: {GITHUB_ORG: acme}
    models: {default: smart}
  - plugin: pr-reviewer
    version: 1.2.0
    source: hub:ai.oz0/pr-reviewer
evals: [evals/]
plugin
string required
The member's name, unique in the set.
version
string required
The member's exact version. A range is refused: "a set pins exact versions; ranges belong in uses:".
source
string required
Where the member comes from, pinned: hub:<publisher>/<name>, a Git URL at a full commit (https://github.com/acme/notes.git@<40-hex commit>), or an image by digest (oci://<image>@sha256:<64 hex>). A tag or a branch is refused, since it can move.
settings
map
Values of the member's own settings the set suggests, by setting name. Never a secret: a value that looks like a token or a password is refused.
models
map
A model alias the member asks for, mapped to an alias of the tenant or <provider>/<model>.
  • At least one member; a set of one is a warning.
  • A set's evals name its members' agents and flows by address (pr-reviewer/oz0-pr-reviewer).
  • Nothing else: tools, agents, skills, flows, hooks, harnesses, events, channels, connections, egress, requires.secrets, optional secrets and settings, provides, reads, records, startup, mail, procedure, uses, policy and runtime are each refused with "a set has no parts of its own: move <key> into a member plugin".

policy

The plugin's suggested policy: its word on its own functions, as rules that only tighten. An install writes them as the tenant's rules, attributed to the plugin (Tool policy).

oz0-plugin.yaml
policy:
  - match: oz0_github.merge_pull_request
    action: ask
    when: 'args.base == "main"'
    reason: the plugin asks before it merges
  - match: oz0_github.delete_branch
    action: judge
    question: Is this branch merged and no longer needed?
    reason: the plugin asks before it deletes
match
string required
This plugin's own functions: <tool>.<function> or <tool>.* of one of its tools, or the same with its own address (github/oz0_github.*). Any other pattern, a bare * among them, is refused: "a suggestion covers only this plugin's functions".
action
string required
ask, refuse or judge. allow is refused: a suggestion only tightens.
when
string
A condition over each call, in the tool policy's expression language, such as args.base == "main".
reason
string required
Why the plugin asks, as a person reads it, at most 200 characters.
question
string
Required with judge, refused otherwise: what the judge decides.

Two rules with the same match and when are refused. The keys are a tool policy rule's, so an install writes each as an ordinary rule.

What a suggestion does at install. The install writes each rule into the tenant's tool policy after the tenant's own rules, marked as the plugin's, with its reason (ask and judge as an Ask, refuse as a Refuse). An installer needs no governance permission for it, since it never overrides the tenant's own rules and only tightens what a function's type gives it. A function's default is then the first that applies:

  1. a rule the tenant already has that decides the function's calls;
  2. the plugin's suggestion;
  3. what the function declares (its annotations), and the plugin's requires_approval, which asks whatever comes first unless the tenant refuses.

Where the tenant's policy is already stricter than a suggestion (it refuses destructive calls, say), the stricter word stays and the install says so. A pattern is written as one rule only where none of the tenant's defaults is stricter than it; otherwise one rule per function the plugin lists, so a function it does not list is decided by the tenant's defaults.

The check reads the measured listing, and, at an update, what nodes listed of the installed version; when the first node's listing of the version is recorded, the server checks the rules again against it, and narrows a rule that would decide a function it lists more loosely than the tenant's policy.

The installer may switch a suggested Ask to Allow, for a function or a group, with a reason and a second admin where four eyes are on; the switched rule is then the tenant's own. An update writes the new version's rules, keeps a rule the new version drops or loosens (and says which), and keeps asking about a function the new version takes off requires_approval.

Uninstalling the plugin removes its rules, and the rules written for its functions when the tenant tightened a default, except the ones the tenant switched.

Only stricter. plugin lint reads each rule against the measured listing (and a remote tool's snapshot): a rule that would let a call run that the function's annotations or requires_approval already ask a person about is an error, such as a judge on a destructive function, and an install refuses it too. A rule that covers no listed function is a warning. A verified plugin asks about each write function this way (OZ-S018).

A judge is written as an Ask until judges ship, and the install screen says so; its question is kept with the rule.

Back to oz0-plugin.yaml.

On this page
Copyright © 2026