# Promote and demote

> How a tool moves in and out of an agent's working set: by the agent's own call, and by the cap and idle rule that keeps the list from growing without end.

Source: https://docs.getgraft.ai/graft/toolbox/promote-and-demote

An agent's tool list from Graft is its working set: the meta-tools, plus exactly the authored tools currently promoted for it, each first-class with its own schema under the name `<vendor>__<name>`. Promoting a tool puts it in that list; demoting takes it out. Nothing else changes. The tool stays in the toolbox with every version it ever had, and so does what you have said about it.

Two things move a tool. The agent does, with `promote` and `demote`, when it knows it needs a tool or is done with one. A rule does, when the agent has not: a tool unused past the agent's idle window, or beyond the agent's cap, is demoted for it. Both fire `tools/list_changed`, and a harness that listens re-reads the list.

## The agent's own calls

**`find_tool { query }`** searches the toolbox, demoted tools included, by vendor, name and description, case-insensitively. Each hit carries the tool's `vendor` and `name`, which the other three calls take, whether it is `promoted` right now, and its `readOnlyHint` and `destructiveHint`. When nothing matches, the answer says so and points at `acquire`.

**`promote { vendor, name }`** moves a tool into the working set and answers the set's new size. **`demote { vendor, name }`** takes it out and answers the same. Neither asks anyone: promotion is harmless, since a tool that writes still asks on its first call, and demotion deletes nothing. A name not in the toolbox is refused as `tool_not_found`.

**`run_tool { vendor, name, input }`** runs a tool without promoting it, exactly as calling it first-class would: the same input validation, the same approval rule, the same answer. It exists for the turn in which a tool was just published, before the harness has re-fetched its list, and for a tool the agent wants once and does not want to keep. With `dryRun: true`, reads reach the vendor and every other method stops at the proxy with a preview.

Graft's server instructions and the Hermes skill both tell the agent to call `find_tool` before `acquire`, since a demoted tool is one `promote` from coming back and needs no authoring. A publish promotes on its own, so a tool `acquire` just built is in the list without a separate call.

## The rule

Each agent has a **cap** and an **idle window**, set when you create it and editable on its page in the console under **Name, cap and idle window**, or from **Edit** in the agents list. The defaults are a cap of 20 tools and an idle window of 21 days. A sweep runs every five minutes, and for each agent it does two things in order:

1. **Idle.** A tool whose last use is older than the window is demoted with cause `idle`. A tool never called since it was promoted counts from its promotion, so a tool promoted and forgotten ages out like one used and forgotten.
2. **Cap.** If more tools remain than the cap allows, the least recently used beyond the cap are demoted with cause `cap`. The cap never demotes a tool used inside the window. A promotion is not a use, so the cap's candidates are tools promoted inside the window and not yet called, oldest promotion first.

The consequence of the second rule is deliberate: a working set whose every tool was used inside the window sits above the cap until some of them age out. The cap is a backstop against a list that never shrinks, not a hard limit, because a limit that demoted a tool the agent used yesterday would break the very task the rule protects.

Two guards make the rule safe. **Nothing is demoted while the agent has a run in flight**, a call waiting on an approval included, so a tool is never pulled from under a turn that is using it. And **nothing is ever deleted by the system**: a demoted tool is in the toolbox, `find_tool` finds it, and `promote` brings it back. A monthly job whose tool aged out degrades to those two calls, not to a failure.

> **Note**
>
> Demotion changes the tool list and nothing else. The tool's versions, its default connection and the approval you gave it for that agent all stand, so a re-promoted write tool runs without asking again.

## Seeing it in the console

Each agent's page shows the working set as the harness sees it, with a **Promoted by** column reading *the agent*, *a publish* or *the rule*, and a **Last used** column, which is the clock the idle rule reads. The **History** card below lists every promotion and demotion with its cause: *the agent asked*, *published by the agent*, *unused past the idle window*, *over the working-set cap*, or *its connection was revoked*. Raising the cap or lengthening the window on the same page takes effect at the next sweep. The cap accepts 1 to 500 and the window 1 to 3650 days.

Two agents of yours share one toolbox and see different working sets over it. That is the intent: the Hermes on your laptop and the OpenClaw on your server hold different jobs, and each list fits its job.

## Prompts to try

```text
Find the Unleashed tool that lists sales orders and promote it.
```

```text
Demote every tool you have not used in this conversation.
```

```text
Run the notion__search-pages tool once for "Q3 planning" without adding it to your list.
```

## Where next

- [The working set](https://docs.getgraft.ai/graft/concepts/the-working-set.md): Why the list is per agent, and how expansion and contraction stay literal.
- [Agents](https://docs.getgraft.ai/graft/console/agents.md): Where the cap, the idle window and the history live in the console.
