All tools are bound; visibility controls exposure
A common misconception: thatvisibility decides whether a plugin’s tools are bound to the agent. It doesn’t. Every plugin tool — always, on-demand, and silent — is bound to the agent at compile time. What visibility controls is three separate things: whether the plugin is advertised in the Tier-1 prompt block, whether it is discoverable via the meta-tools, and whether the LLM can call its tools right now (the CapabilityGate enforces this last one per model call).
The three tiers
Default:
on-demand. A plugin without an explicit visibility is treated as on-demand.
What each tier is for
How on-demand gating actually works
Because all tools are bound at compile time, “loading” a plugin is not about binding — it’s about lifting a filter. TheCapabilityGateMiddleware runs on every model call. It reads the thread’s loadedPlugins set and trims the tool list the model sees:
alwaysandsilenttools → always pass the gate (the model can call them).on-demandtools → pass only when their plugin is inloadedPlugins.
createAgent({ tools }) freezes the bound list, so a load_capability call updating state mid-run would otherwise have no effect until the next request rebuilt the agent. Filtering inside the middleware lets a load decision take effect on the very next LLM call. The gate is one of the always-on middlewares.
Picking a tier
Promoting toalways is a deliberate budget choice — it pays Tier-1 tokens on every turn. silent is for plugins that don’t need to be advertised or discovered (they work through middleware or HTTP). Most plugins should stay on the default — on-demand.
Loading and unloading
on-demand plugins live in a per-thread loadedPlugins state field. The set is monotonic — it only grows. Loading a plugin makes its tools available for the rest of that thread; a new thread starts with an empty loadedPlugins.
There is no “unload” operation. If a thread accumulates too many loaded plugins, starting a new thread is the reset.
Per-tool override
A plugin can override visibility per tool by settingvisibility on the PluginTool itself. This lets one plugin ship a mix — e.g. one always tool and several on-demand tools — without splitting into two plugins.
Read next
Set visibility (recipe)
How to declare each tier in plugin code.
Meta-tools
How
list_capabilities and load_capability work.PluginManifest.