# Custom Models

A custom model connects SleekAI to an endpoint that accepts OpenAI-style chat
completion requests: a provider SleekAI has no built-in support for, a model
server you run, or your own gateway. OpenRouter is built in and needs no custom
model.

Requests to a custom model go through WordPress, which adds the stored API key
on the server, so the key never reaches the browser.

## Creating a custom model

1. Store the endpoint's API key. A provider key from
   [API Keys](/docs/ai/settings/api-keys.md) works for that provider's own API;
   for any other endpoint, store a separate key with
   `wp sleek ai key set custom-<name>`.
2. Under AI, open **Settings > Custom models** and select
   **Create custom model**. `create=1` in the address, before the `#`, opens
   that dialog directly.
3. Enter a name of lowercase letters, digits and hyphens, such as `my-model`.
   SleekAI prefixes it with `custom-`, and `custom-my-model` becomes the
   model's identifier.
4. Fill in the model's fields and save.

The **Custom models** list shows every custom model with actions to edit and
delete it; an open custom model also has **Delete custom model** beside
**Save**. Deleting one cannot be undone.

## Fields

**Label** is the name shown in model selectors; without one the identifier is
shown.

**Model** is the model identifier the endpoint expects. It is not sent on its
own: add it to the request body, as below.

**Endpoint URL** is the URL that receives chat completion requests, usually
ending in `/chat/completions`:

```txt
https://api.example.com/v1/chat/completions
```

The endpoint has to be a public address. WordPress refuses one on the site's
own machine or private network unless the site allows that host with
WordPress's `http_request_host_is_external` filter, and it does not follow
redirects. A provider key from API Keys is sent only to its provider's API
over HTTPS, such as `api.openai.com` for the OpenAI key, so an endpoint
elsewhere needs a `custom-` key.

**API key** selects one of the keys you stored. If the provider expects the
key in the URL, write `{apiKey}` where it belongs, and SleekAI replaces it on
the server:

```txt
https://api.example.com/v1/chat/completions?key={apiKey}
```

**Body** is JSON merged into every request. Put the upstream model identifier
and any provider-specific fields here:

```json
{
  "model": "provider-model-name"
}
```

SleekAI adds the conversation's `messages` and the `stream` flag when it sends
the request. The body must be valid JSON, and it may use `{apiKey}` too.

**Headers** adds request headers. SleekAI always sends
`Content-Type: application/json` and `Authorization: Bearer {apiKey}`; add a
header only when the provider needs another one, for example
`X-API-Key: {apiKey}`. A header with exactly the same name replaces
SleekAI's.

**System instruction** is placed before the conversation when you chat with
this model in [Chats](/docs/ai/chat.md). **Context limit**, **Max tokens** and
**Temperature** are saved with the model but are not sent to the endpoint; put
a limit or a temperature in the body to send it.

## Using a custom model

Custom models appear in the model selectors of Chats and the
[chatbot editor](/docs/ai/chatbots/model.md), grouped apart from the provider
models. Alt text needs a vision model from a built-in provider and does not
offer custom models.

A custom model belongs to the user who created it: it is listed only for that
user, and it finds only an API key that user stored. A chatbot that uses a
custom model resolves it as the chatbot's author, so visitors can use it. Code
that runs without a signed-in user, such as a WP-CLI command without `--user`
or a scheduled task, needs a provider model instead.
