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

The OpenAPI 3.1 document of the machine API, generated from the tool registry.

`GET /api/admin/v1/openapi.json` and `GET /api/public/v1/openapi.json` serve
it (`PhoenixKit.API.REST`). An agent or a client generator reads it to learn
every tool, its input and output schemas and the error format.

  * every tool is `POST /<tool name>` (the dot is part of the path);
    `operationId` is that same dotted name;
  * `x-agent-safety` is `read` for a read-only tool, `destructive` for one
    whose `annotations.destructive` is set, else `write` (`irreversible` does
    not occur in v1); `x-idempotent` is `annotations.idempotent`;
    `x-required-scope` is the scope an admin tool needs;
  * the request body schema is `PhoenixKit.API.Executor.input_schema/1`, the
    schema the validator enforces; the `200` schema is
    `PhoenixKit.API.OutputShape.for_tool/1`, the same as MCP's
    `outputSchema` (a write tool may answer with a preview instead);
  * a write tool (`PhoenixKit.API.ControlFields.write_tool?/1`) that can replay
    (`PhoenixKit.API.ControlFields.replay_tool?/1`) also takes the
    optional `Idempotency-Key` request header, can answer with the
    `Idempotent-Replayed` header on a replay (for the admin API also on the
    held answer of an operation that already waits for approval), and lists
    `409` (a confirmation code that is not valid, an idempotency key reused
    for another request or still in progress);
  * errors are RFC 9457 `application/problem+json`, defined once in
    `components.schemas.Problem`.

`build/3` is pure. `respond/2` builds the document for the tools the caller
may use (a key sees only what its effective scopes unlock; a module that is
switched off is absent) and sends it.

# `build`

```elixir
@spec build([PhoenixKit.API.Tool.t()], PhoenixKit.API.Tool.audience(), keyword()) ::
  map()
```

Builds the document for `tools` (the tools of one `audience`).

Options: `:server_url` (the REST base URL, required), `:title` (required),
`:version` (the version of the API description, default `"1"`).

# `respond`

```elixir
@spec respond(Plug.Conn.t(), PhoenixKit.API.Tool.audience()) :: Plug.Conn.t()
```

Sends the document for the tools the caller may use. Costs one rate-limit
unit, like the discovery list; answers the executor's error otherwise.

---

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