# `PhoenixKit.API.Registry`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.64.1/lib/phoenix_kit/api/registry.ex#L1)

The tools the API can serve right now.

A tool is callable when its module is enabled, it is not hidden by the
`api_disabled_tools` setting, its module's API is not switched off in
`api_disabled_modules` (a module key; every module is on until listed), and it passed
`PhoenixKit.API.Tool.validate/1`. The list is the enabled modules'
`c:PhoenixKit.Module.api_tools/0` (through `PhoenixKit.ModuleRegistry.all_api_tools/0`)
plus core's own `PhoenixKit.API.CoreTools.tools/0`.

Nothing here is cached: modules can be enabled and disabled at runtime, and a settings
change must take effect on the next request. A caller that serves a request should ask
once and keep the answer.

## Cost

A call asks every enabled module for its tools (`api_tools/0`) and validates each of them
again. Measured with 60 tools in one module: about 1.1 ms for `all_tools/0` or a `find/2`
hit, about 2 ms for a `find/2` miss, which also asks the switched-off modules. A caller
that an anonymous client can reach (the public endpoint) must count the request against a
rate bucket **before** it looks a tool up, so repeated unknown names are not free CPU.

# `all_tools`

```elixir
@spec all_tools() :: [PhoenixKit.API.Tool.t()]
```

Every callable tool: the enabled modules' tools (tagged with `:module`) followed by
core's, minus the names in `api_disabled_tools` (newline separated) and minus every tool
of a module listed in `api_disabled_modules`. A module cannot declare a `system.*` tool
(`PhoenixKit.ModuleRegistry.all_api_tools/1` drops it), so it cannot shadow one of core's,
and core's tools belong to no module, so no module switch reaches them. When either list
cannot be read at all, nothing is callable.

# `find`

```elixir
@spec find(String.t(), PhoenixKit.API.Tool.audience()) ::
  {:ok, PhoenixKit.API.Tool.t()} | {:error, :not_found | :module_disabled}
```

Finds the callable tool `name` of `audience`.

Answers `{:error, :module_disabled}` when a registered module that is switched off
declares a tool of that name, and `{:error, :not_found}` for every other miss: an unknown
name, a tool of the other audience, a tool hidden by `api_disabled_tools` or by a module
switched off in `api_disabled_modules` (even when its module is also disabled), and every
name when a hidden list cannot be read.

# `visible_tools`

```elixir
@spec visible_tools(PhoenixKit.API.Tool.audience(), [String.t()] | :all | :none) :: [
  PhoenixKit.API.Tool.t()
]
```

The tools of `audience` a caller may see.

  * `:all` - every callable tool of the audience (public listings, the admin UI).
  * `:none` - nothing. So is anything that is not a list of scopes (an anonymous actor
    has no scopes).
  * a list of scopes - the tools whose `:scope` is in the list, plus the tools that have
    no scope (core's `system.*` tools and public tools), which every caller may use.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
