---
title: AI
description: An optional language model, Claude or one on your own machine, for chat, drafting and agents.
section: Server
order: 8
---

# AI

<p class="lead">A model is optional and off until a superuser sets one up. Everything that uses it has an answer for when there is none, and what a model says comes back as a proposal: a person applies it, or doesn't.</p>

## Setting one up

In the admin UI, under **AI**:

| | |
|---|---|
| Provider | `anthropic` for Claude, or `openai` for anything that speaks the OpenAI chat shape: Ollama, LM Studio, llama.cpp's server |
| Model | For Claude, `claude-opus-5` unless you name another. Required for `openai` |
| Address | For `openai`, where it listens: `http://localhost:11434/v1` for Ollama |
| Key | Kept on the server; never sent back out of the API |
| Effort | How hard Claude thinks: `low`, `medium` (the default) or `high` |
| Per person, per day | How many questions one person may ask; `0` for no limit. Administrators aren't counted |

A model on the school's own machine keeps everything on it.

## In the browser

```ts title="app.ts"
const { text } = await sluurp.ai.chat([{ role: "user", text: "Summarise this week's notices" }]);

// As it is written, piece by piece:
await sluurp.ai.stream(turns, { onText: (piece, all) => (out.textContent = all) });
```

Both take `{ system, signal }`; stopping with the signal keeps what came so far. When a person has asked their day's share, the answer says so instead of throwing.

## In server code

`ai(system, prompt, schema)` asks for an answer as JSON in the schema's shape, or `null` when no model is set up:

```ts title="functions/tag-notice.ts"
const tags = await ai(
  "You tag school notices.",
  notice.body,
  { type: "object", properties: { tags: { type: "array", items: { type: "string" } } } },
);
if (tags) await collection("notices").update(notice.id, tags);
```

For a model that works in turns, reading what it needs through tools until it has an answer, see [Agents](/docs/agents).

## Where Sluurp uses it

[Pages](/docs/pages) offers its AI tools, and `sluurp/ai` an assistant for any app, only when a model is set up.
