# AI

Add AI chat to your application with the [AI SDK](https://ai-sdk.dev), through Vercel AI Gateway, OpenAI or Anthropic.

### Syntax

```
$ vela enable ai [--provider <gateway|openai|anthropic>]
```

Without `--provider` you're prompted to pick one. Outside a terminal (CI, scripts) the flag is required. You're then asked for the provider's API key, with the input hidden. A key already in your `.env` is kept without asking, and you can leave it blank to add it later.

AI has no dependencies and doesn't need a backend: it works in any SvelteKit project with a server. A project that builds with `@sveltejs/adapter-static` is refused, because a static site has no server to keep the key private or stream the reply. [`vela enable backend`](/enable/backend) moves a static project to `@sveltejs/adapter-node`.

### What you get

- `src/lib/server/ai.ts`, which exports `languageModel()`: the configured model, or `undefined` while the API key is blank. Import it from any server code.
- A streaming chat endpoint at `src/routes/api/chat/+server.ts`. It validates the conversation, sends it to the model with `streamText` and streams the reply back.
- A demo chat page at `/ai`, built on the `Chat` class from `@ai-sdk/svelte`, with streaming replies, a Stop button and errors shown inline.
- A server test for the endpoint in `src/routes/api/chat/server.test.ts`, when the project has the [`vela test:server`](/test/server) harness. Its requests never reach the model, so it passes without an API key.
- The `ai` and `@ai-sdk/svelte` packages plus the provider's own, and the `button` and `textarea` components.
- The provider's API key in `.env`.

The endpoint reads the key from `$env/dynamic/private` on every request. While it's blank, the endpoint answers `503` with the name of the variable to set, and the demo page shows that message. Set the same key on each deploy target with [`vela env set`](/env/set).

In a project without shadcn-svelte, the demo page uses plain HTML elements instead. In a project without route groups, it lands directly in `src/routes/ai`.

### Providers

#### Vercel AI Gateway

```
$ vela enable ai --provider gateway
```

| Variable | Description |
| --- | --- |
| `AI_GATEWAY_API_KEY` | A Vercel AI Gateway API key. |

One key reaches models from every major provider. Model IDs take the form `creator/model`, and the default is `anthropic/claude-sonnet-5`. The gateway provider ships inside the `ai` package, so nothing else is installed.

#### OpenAI

```
$ vela enable ai --provider openai
```

| Variable | Description |
| --- | --- |
| `OPENAI_API_KEY` | An OpenAI API key, e.g. `sk-...`. |

Installs `@ai-sdk/openai`. The default model is `gpt-5.5`.

#### Anthropic

```
$ vela enable ai --provider anthropic
```

| Variable | Description |
| --- | --- |
| `ANTHROPIC_API_KEY` | An Anthropic API key, e.g. `sk-ant-...`. |

Installs `@ai-sdk/anthropic`. The default model is `claude-sonnet-5`.

### Who can chat

Every reply is billed to your API key. With [auth](/enable/auth) enabled, the endpoint answers only signed-in users (`401` otherwise) and the demo page sits behind sign-in in the `(app)` group. Without auth, both are public, so put the endpoint behind sign-in or a rate limit before you deploy.

Enabling auth later doesn't change the endpoint. Run `vela enable ai` again to regenerate it with the sign-in check, then delete the old demo page in `src/routes/(public)/ai`.

### Customising

- **Model**: change the model ID in `src/lib/server/ai.ts`.
- **Instructions**: `INSTRUCTIONS` at the top of the endpoint is sent ahead of every conversation, through the AI SDK's `instructions` option. System messages sent by the browser are refused.
- **Tools and more**: tools, structured output and the rest of the AI SDK work in the endpoint as usual. See the [AI SDK docs](https://ai-sdk.dev/docs).
- **Errors**: in development, provider errors such as a bad key or an unknown model are shown in the chat. In production they stay in the server log and the chat shows a generic message.

The demo page is yours to change or delete. The endpoint and `languageModel()` don't depend on it.

### Switching providers

Run the command again with a different `--provider`. `src/lib/server/ai.ts` is replaced, the provider's package is installed and its key is added to `.env`. The endpoint and demo page are written again too, so re-apply any changes you made to them. Remove the previous provider's package and key yourself.

To remove AI entirely, run [`vela disable ai`](/disable/ai).