Dynamic action discovery

Every connected service exposes two action surfaces: a small curated set that ships in tools/list on every turn, and a much larger long-tail the model reaches on demand through search. Dynamic discovery is the layer that keeps the long-tail out of context until it is needed.

Why it exists

A gateway with ~20 connected services and a read/write tool split puts roughly 40 tool definitions — on the order of 50,000 tokens — into the model's context on every turn, before the user has typed anything. That overruns the 30–50-tool selection ceiling at which tool-selection accuracy degrades, and it bills for tool prose nobody reads.

The catalog also has a long tail. Auto-importing a full OpenAPI spec (Microsoft Graph, BigQuery, and others) yields thousands of endpoints — the catalog currently exceeds 17,000 long-tail actions. Shipping all of that in tools/list is not viable. Dynamic discovery makes the full surface reachable without paying for it on every turn.

Curated vs long-tail

  • Curated actions are hand-picked, carry written descriptions and parameter prose, and appear in the default <service>_read_actions / <service>_write_actions enums. These load on every turn. The action counts on the Services page are the curated surface.
  • Long-tail actions are auto-generated from the upstream OpenAPI spec, marked curated: false in YAML. They are indexed for search and do not appear in tools/list until activated.

How the model reaches the long-tail

Two gateway-level meta-tools drive the flow:

  1. Search. gateway_search_actions(query, service?, limit) runs BM25 over the long-tail index and returns ranked candidates with their service, HTTP method, endpoint, risk tier, and whether they are already active for the session. If nothing clears the relevance floor, it returns an empty result and a hint rather than a fabricated top match.
  2. Activate. gateway_activate(name="<service>.<action>") activates the action for the current session. It emits tools/list_changed for spec-compliant clients, and returns the full tool signature inline so clients that ignore that notification still work. Only after activation can the action be called.

The activation is per session. It does not change the default tool list for anyone else, and it does not persist across sessions.

Search visibility is not execution

This is the distinction that makes the default safe. Being discoverable in search is separate from being callable:

  • Search visibility is what the per-service toggle controls — whether a service's curated: false actions show up in gateway_search_actions.
  • Execution always requires an explicit gateway_activate for the session first. A long-tail action is never callable just because it surfaced in a search result.

So turning a service's long-tail on widens what the model can find, not what can fire unattended.

Risk tiers

Each long-tail action carries a risk tier derived from its HTTP method plus a path-keyword scan, with maintainer YAML overrides on top:

  • read — GET, no body. The model can activate and call autonomously.
  • write — POST/PUT/PATCH. Carries a body, mutates state. Activation requires the model to pass user_confirmed=true and is recorded in the audit log.
  • destructive — DELETE, or a POST whose path matches a keyword list (/delete, /revoke, /terminate, /wipe). The same user_confirmed=true gate as write, and the model is expected to surface the consequence in plain language first. Catastrophic actions (permanent delete, container destroy, bulk delete, generic API passthrough) sit behind an additional admin-approval gate the AI cannot self-grant — see destructive-action governance.

Retrieving an action correctly is not the same as executing it safely — the risk tier keeps the two as separate decisions.

The same protections apply

Long-tail actions are not a side door. The PII pseudonymization-and-rehydration pipeline and the two-layer policy hooks that govern curated actions apply identically to an auto-imported endpoint. Hooks see the call and can deny it before the gateway dispatches; every activation and call lands in the same audit log.

Turning it on and off

As of May 2026, long-tail discovery defaults to ON for every connected service. The control is opt-out:

  • Per service, from the dashboard. Each service's page in the dashboard carries a "Find more by tool search" toggle — the authoritative control. Switch it off to exclude that service's long-tail from search.
  • For IaC-managed deployments. Set DYNAMIC_DISCOVERY_DISABLED_SERVICES to a comma-separated denylist of service ids. Empty (the default) means long-tail is visible for every service. The value hot-reloads across containers; no restart required.

What is still open

  • Published retrieval benchmark. BM25 is fast and predictable at the current catalog size, but a public recall number (scoped and unscoped) is owed.
  • Semantic retrieval. Pure BM25 has a known ceiling versus hybrid BM25-plus-semantic. The plan is to revisit as the catalog grows or once ground-truth labels exist.
  • Swarm promotion. When many tenants activate the same long-tail action, it should graduate to a curated first-class tool with hand-written prose. The telemetry exists; the promotion pipeline does not yet.

Related