---
title: "Retire or remove a plugin"
description: "Wind down plugin use, inspect dependents and remove old versions."
canonical_url: "https://docs.oz0.ai/build/plugins/install/retire-and-remove"
---
# Retire or remove a plugin

> Wind down plugin use, inspect dependents and remove old versions.

For: tenant administrators and plugin authors.

Wind down plugin use, inspect dependents and remove old versions.

## Retire

Retiring a plugin stops new use of it while what uses it carries on: the way to wind a plugin down.

```bash [Terminal]
oz0 plugin retire github-tools --reason "replaced by github-app"
oz0 plugin unretire github-tools
```

While it is retired:

- people and apps start no new jobs of its agents and flows and call none of its tools by hand (the edge refuses them, and the picker leaves them out);
- no new routine may name its agents, and no other plugin gets a new grant of it or a wider one: an install whose `uses:` needs more of it than its plugin was granted before is refused with the fix;
- routines, webhooks and event routes set up before, plugins granted it before (their delegations and calls), running jobs and updates of the plugin itself carry on.

Retiring an agent or a tool in the [inventory](https://docs.oz0.ai/govern/inventory#retiring-and-deleting) is stronger: it stops every new job of that agent, routines included. A [kill switch](https://docs.oz0.ai/govern/kill-switches) stops what runs.

`plugin list`, the Plugins page and the inventory mark a retired plugin, and every plugin and agent that reaches it shows it as a badge: retired via github-tools, with the chain when it is further away. The same badge says vulnerable via a plugin it reaches that has a [known vulnerability](https://docs.oz0.ai/build/plugins/vulnerabilities), and retired version via one whose installed hub version its index deprecated, withdrew or quarantined.

The owners of the retired plugin's agents are told (`plugin.retired`), and so are the owners and team admins of what depends on it (`dependency.retired`); see [notifications](https://docs.oz0.ai/admin/notifications). Retiring and unretiring are audited as `plugin.retire` and `plugin.unretire`, and take the permission to remove plugins.

## Remove

```bash [Terminal]
oz0 plugin remove github-tools
```

Nodes stop the plugin's processes and delete it. A rollout of it that waits or runs ends.

A removal is refused while anything depends on the plugin, and the refusal lists who, each with its owner (a person or a team), so that removing a plugin is a decision that names them:

- other plugins whose grants reach it, directly or through plugins that reach it in turn (to five levels, with the chain: `grant deep (through mid): of mid: delegates to mid-adder`), and plugins that declare it under `uses:` without a grant yet;
- routines that start its agents or flows, list its tools or fire on its event sources, and other plugins' flows whose steps call its tools or agents or wait for its events;
- jobs of its agents that run now, and the records it keeps for the tenant. A job counts while the edge keeps its summary fresh (it looks at running jobs every 30 seconds); one whose summary has not been refreshed for ten minutes may have ended without the summary learning it, and is listed as "may still run" without refusing anything (the removal cancels it if it still runs).

Its own argument bindings go with it and are listed without refusing anything; people who may not read the tenant's settings do not see them, since they name secrets and hosts. A dependent plugin also shows its own badges (below), such as vulnerable via a plugin further along.

```bash [Terminal]
oz0 plugin dependents github-tools
# KIND     NAME         OWNER          BLOCKS  WHAT
# grant    pr-reviewer  user:ada       yes     tools oz0_github.merge_pull_request
# grant    release-bot  team:release   yes     through pr-reviewer; of pr-reviewer: delegates to pr-reviewer
# routine  nightly      team:platform  yes     starts agent oz0-github
```

Two ways on from a refusal:

- Retire it first, so that nothing new starts to use it while what uses it moves off (below), and remove it when `plugin dependents` lists nothing.
- Remove it anyway, with `--force` and a `--reason` (at most 500 characters): the audit log keeps the reason with the list as `plugin.remove.forced`, its running jobs are cancelled, and the answer lists what it went past.

```bash [Terminal]
oz0 plugin remove github-tools --force --reason "replaced by github-app; owners told on 3 October"
```

When a plugin goes, so do its agents and flows, and what named them is dealt with so that a new agent of the same name, from another plugin or a later version, inherits none of it. The removal lists each, and `oz0 inventory tombstones` keeps the list:

### Marked

The platform marks these entries so they no longer grant access: API key scopes (`agent:billing` becomes `agent:billing#gone`; the key stays scoped, so make a new one for a new agent), people's agent grants and identity providers' group rules that grant it, and routines that start it, which pause with the reason. A marked entry matches no agent and is accepted as it is, so a membership or an identity provider is edited as before; remove the entry when you like (an empty agent grant would reach every agent, which is why it is marked rather than dropped).

- Dropped: the tenant's keep-for rule for it (the jobs it left keep the period they started with) and its own legal bases (a new agent states its own).
- Listed for a person to change: tool-policy rules whose condition names it (a governance change, with a reason) and notification rules that filter on it.

Its inventory item is retired, and comes back when the same plugin is installed again; an agent of the same name from another plugin starts with a new item. Installing a version that no longer has an agent does the same for that agent. A version that becomes the installed one later, when its quality gate passes or its rollout ends, does not yet.

## Old versions

Every version a tenant installs keeps its artifact, the packed files nodes download, in the cluster's database. The server keeps an artifact while it belongs to:

- The installed version.
- A candidate under its quality gate or a rollout.
- Either version of a plugin rollout whose queues may still run jobs.
- A version named by a [retained](https://docs.oz0.ai/govern/personal-data) job's summary, so [comparing versions](https://docs.oz0.ai/improve/search-and-compare#compare-two-versions-of-an-agent) can still show its files.

Once nothing uses an artifact, the server deletes it after a grace period of 7 days. The server that holds the lease checks once an hour, one server at a time. Reinstalling a deleted version builds it again.

```bash [Terminal]
oz0 plugin gc --dry-run          # what a pass would delete now
oz0 plugin gc                    # one pass now (cluster admins)
oz0 plugin gc --grace 24h        # with a shorter grace period
```

`server start --artifact-gc dry-run` makes the hourly pass log what it would delete and delete nothing, and `--artifact-gc off` turns it off. A pass that deletes something is in the audit log as `artifact.collect`: the hourly pass under the actor `system:artifact-gc`, a `plugin gc` under the admin who ran it. The metrics `oz0_artifact_gc_passes_total`, `oz0_artifact_gc_collected_total`, `oz0_artifact_gc_collected_bytes_total`, `oz0_artifact_gc_kept` and `oz0_artifact_gc_young` count what it did.


## Sitemap

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