> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ixo.world/llms.txt
> Use this file to discover all available pages before exploring further.

# Set visibility

> Control whether a plugin's tools are bound at boot, discoverable on demand, or invisible to the agent.

`manifest.visibility` sets the default for every tool the plugin ships. Individual tools can override it. Three values: `'always'`, `'on-demand'` (default), `'silent'`.

<Steps>
  <Step title="Set plugin-wide visibility on the manifest">
    The manifest's `visibility` flag is the default applied to every tool the plugin returns.

    ```ts theme={"system"}
    import type { PluginManifest } from '@ixo/oracle-runtime';

    const manifest: PluginManifest = {
      title: 'Weather',
      summary: 'Current weather + forecast lookups for cities.',
      whenToUse: ['Current weather', 'Forecasts', 'Outfit recommendations'],
      visibility: 'on-demand',
    };
    ```

    Three tiers: `'always'` (bound to the agent at boot, listed in the Tier-1 prompt), `'on-demand'` (default — discoverable via `list_capabilities`, loaded via `load_capability`), `'silent'` (not advertised — see the warning below). Canonical source: [weather.plugin.ts](https://github.com/ixoworld/ixo-oracles-boilerplate/blob/main/apps/qiforge-example/src/plugins/weather/weather.plugin.ts).

    <Warning>
      `'silent'` controls **advertising, not access** — it is not a security boundary. A silent plugin is left out of the Tier-1 capability block, excluded from `list_capabilities` (by default), and rejected by `load_capability`. But if a silent plugin returns tools, the capability gate passes them straight through to the model, exactly like `'always'`-tier tools. Use `'silent'` for transport/middleware/Nest-module plugins (e.g. Slack transport, credits/billing) that have nothing to advertise to the agent — never to "hide" a sensitive capability.
    </Warning>
  </Step>

  <Step title="Override visibility per tool">
    Set `visibility` directly on the `PluginTool` when one tool needs a different tier from the rest of the plugin.

    ```ts theme={"system"}
    import { tool, z, type PluginTool } from '@ixo/oracle-runtime';

    const currentTool: PluginTool = tool(handler, {
      name: 'get_current_weather',
      description: 'Get the current weather for a city.',
      schema: z.object({ city: z.string() }),
    });
    currentTool.visibility = 'always';

    const forecastTool: PluginTool = tool(handler, {
      name: 'get_weather_forecast',
      description: 'Get a daily forecast for a city.',
      schema: z.object({ city: z.string(), days: z.number().optional() }),
    });
    forecastTool.visibility = 'on-demand';

    return [currentTool, forecastTool];
    ```

    `PluginTool` shape: see [types.ts](https://github.com/ixoworld/ixo-oracles-boilerplate/blob/main/packages/oracle-runtime/src/plugin-api/types.ts).
  </Step>

  <Step title="Pick the right tier">
    Use this decision tree.

    ```mermaid theme={"system"}
    graph TD
        A["Does this plugin expose<br/>agent-callable tools?"]
        A -->|No — middleware / transport only| Silent[silent]
        A -->|Yes| B["Should the agent use it<br/>on most turns?"]
        B -->|Yes| Always[always]
        B -->|No — discover on demand| OnDemand[on-demand]
    ```

    Promoting to `'always'` costs \~80 tokens per plugin in the Tier-1 prompt plus the tool schemas on every turn. `'silent'` simply stops advertising the plugin to the agent — it does not hide or disable any tools the plugin returns.
  </Step>
</Steps>

## What to know before shipping

* Default is `'on-demand'`. A plugin without an explicit `manifest.visibility` is treated as on-demand.
* `'on-demand'` plugins live in a per-thread `loadedPlugins` set. The set is monotonic — loading is forever for that thread; a new thread resets it.
* Per-tool overrides let you ship a mixed plugin (one `'always'` tool + several `'on-demand'` tools) without splitting it.
* `'silent'` plugins still run their middleware and Nest modules, and any tools they return stay callable by the agent — they're just never advertised. Use it for instrumentation, rate limiting, billing, and transports. It is not a way to hide a capability for security.
* A fork with 50 `'on-demand'` plugins can usually keep 3–5 loaded per thread — the budget stays bounded as the catalog grows.

## Where to read next

<CardGroup cols={2}>
  <Card title="Visibility tiers concept" icon="eye" href="/build-an-oracle/understand/visibility-tiers">
    Costs and trade-offs for each tier.
  </Card>

  <Card title="Meta-tools" icon="magnifying-glass" href="/build-an-oracle/understand/meta-tools-and-loading">
    How `list_capabilities` and `load_capability` work.
  </Card>
</CardGroup>
