---
title: "Sets"
description: "A set installs plugins that were evaluated together, each pinned to an exact version and source, as one decision; afterwards they are ordinary plugins, and removing the set removes what nothing else uses."
canonical_url: "https://docs.oz0.ai/build/plugins/sets"
---
# Sets

> A set installs plugins that were evaluated together, each pinned to an exact version and source, as one decision; afterwards they are ordinary plugins, and removing the set removes what nothing else uses.

For: tenant administrators and plugin authors.

Install a set when you want one decision for a tested combination of plugins. A set has `kind: set` and lists its members at exact versions and sources. It can suggest settings and model mappings and carry evals for the combination.

A set has no tools, agents, skills, flows, hooks, connections or secrets of its own. [Essentials](https://docs.oz0.ai/build/plugins/verified/essentials) is the verified set. See [the set format](https://docs.oz0.ai/build/plugins/structure#sets-the-fourth-kind) to write one.

## Install a set

```bash [Terminal]
oz0 plugin install hub:ai.oz0/essentials
```

A set installs from any source a plugin installs from: a plugin index, a Git URL, an OCI reference or a folder. Its
members come from the sources the set pins: `hub:<publisher>/<name>` at the member's version, a Git repository at a
full commit, or an OCI image by digest.

The install is one decision, as the install of a plugin with [dependencies](https://docs.oz0.ai/build/plugins/install/grants#plugins-that-use-other-plugins)
is. Before anything is installed it reads every member at its pin and refuses:

- a member whose source gives another plugin, another version, or bytes other than the pinned commit or digest (or,
for a set from a plugin index, other than what the index lists the pin at);
- a member that is itself a set;
- pins that do not go together: a member whose `uses:` range the set's pin of the used member is outside.

A member that reaches hosts your tenant does not permit yet stops the install too, before anything is installed: a
wider egress allowlist is a [reviewed change](https://docs.oz0.ai/govern/reviewed-changes) of its own, which the set's decision does not
make for you. The refusal names the hosts by member and the `oz0 tenant egress` command that asks for them.

Then it shows, on one screen, the set's members and what the install does with each, and each member's own
[needs, what it may do and what it reaches](https://docs.oz0.ai/build/plugins/install/review#what-the-install-shows-first):

```text
SET essentials 1.1.1: 9 members, installed as one decision
  github          1.5.1  installs it                     hub:ai.oz0/github
  email           1.0.0  keeps it: installed at the pin  hub:ai.oz0/email
  pr-reviewer     1.1.0  installs it                     hub:ai.oz0/pr-reviewer
  ...

MEMBER github 1.5.1 (installs it)
NEEDS
  connection github: not connected: oz0 connection start github --tenant default
...
```

<table>
<thead>
  <tr>
    <th>
      A member you have
    </th>
    
    <th>
      What the install does
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      none
    </td>
    
    <td>
      installs it at the pin
    </td>
  </tr>
  
  <tr>
    <td>
      at the set's version
    </td>
    
    <td>
      keeps it, and asks nothing
    </td>
  </tr>
  
  <tr>
    <td>
      an older version
    </td>
    
    <td>
      updates it to the pin, checked against the plugins that use it
    </td>
  </tr>
  
  <tr>
    <td>
      a newer version
    </td>
    
    <td>
      keeps it, and marks it as different from the combination the set's evals ran on
    </td>
  </tr>
  
  <tr>
    <td>
      the set's version or another, from another source (another publisher's listing, a fork, another folder or image, or another commit at the set's version)
    </td>
    
    <td>
      keeps it as it is, and marks it as different from the combination; the install never moves a plugin to another source
    </td>
  </tr>
</tbody>
</table>

One yes installs the members, the plugins they use that the tenant lacks, and grants what each member uses of the
others, under one digest: a script passes it as `--accept-uses <digest>`, which `oz0 plugin preview` prints.

The members install one after another, a used one first, each through the ordinary install, so each passes its own checks
(names, tool IDs, egress, custody, its gate); the set's own row is saved last.

If one is refused, the members this
install installed are removed again, newest first, and the error names them; a member it updated stays updated, and the
error says that too.

### Suggested settings and model mappings

A set may suggest values for its members' settings and mappings for the model aliases they ask for. The screen fills them in, for you to confirm: on a terminal, yes takes them, and `--suggested` takes them in a script; the console's install dialog shows them in the members' forms. A suggestion fills only a setting the tenant has not set, of a member the install installs or updates: a value you set before stays.

A set never suggests a secret: the loader refuses a value that looks like one, and a member's secrets and connections are yours to set, as for any plugin. A suggested mapping only adds an alias the tenant lacks (as [`--map`](https://docs.oz0.ai/spend/models-and-keys/mapping#map-a-plugins-models) does at an install); two members that suggest different targets for one alias get the first, and the screen says so.

## After the install

The members are ordinary plugins: configure, update, retire and remove each as you would any plugin. The set's pins
say which versions its evals ran on together, not what must stay installed.

- An update of a member is checked against every plugin that uses it, the other members included, and refused
with the list if it would break one ([Updates and the plugins that use them](https://docs.oz0.ai/build/plugins/install/update#updates-and-the-plugins-that-use-them)).
- The set's page lists its members, each at its pin, or marked: newer than the pin or from another source (each
differs from the combination the evals ran on), older, or not installed. `oz0 plugin list` says the same under the set.
- The set itself has no queue, no agents and nothing a node runs: nodes never receive it.

## Update a set

```bash [Terminal]
oz0 plugin update essentials
```

A new version of a set moves its members to its new pins as one decision, with the same screen. A member the new
version no longer lists is offered for removal, if the set installed it and nothing else uses it; the update never
removes it.

## Remove a set

```bash [Terminal]
oz0 plugin remove essentials
```

```text
Removed essentials from tenant default.
Its members, newest first:
  support-triage  1.0.0  removed
  pr-reviewer     1.1.0  removed
  email           1.0.0  kept: it was installed before the set, which found it
  github          1.6.0 (the set pins 1.5.1)  kept: used by plugin team-bot (uses oz0_github.get_issue)
```

Removing a set removes, newest first, the members it installed that nothing else uses: no other plugin's grant or
`uses:`, an optional one included, and no other set (a set that lists it too takes it over and removes it when it goes). Each removal is checked
as any removal is and audited as `plugin.remove` with the set named. A member that was installed before the set, by
hand or by another install, stays; so does one something depends on. The answer lists each one with why.

## List a set

A set is listed on a plugin index like any plugin, signed and kept in custody the same way: see
[List a plugin](https://docs.oz0.ai/build/plugins/list-a-plugin#list-a-set).


## Sitemap

See the full [sitemap](https://docs.oz0.ai/sitemap.md) for all pages.
