AI

AI is optional and off until a superuser configures a model. Every feature that uses it works without one, and model output is always a suggestion that a person accepts or rejects.

Setting one up

In the admin UI, under AI:

Provideranthropic for Claude, or openai for any OpenAI-compatible API: Ollama, LM Studio, llama.cpp server
ModelDefaults to claude-opus-5 for Claude. Required for openai
AddressFor openai, the base URL, e.g. http://localhost:11434/v1 for Ollama
KeyStored on the server; never returned by the API
EffortClaude’s reasoning effort: low, medium (default) or high
Per person, per dayRequest quota per user; 0 for unlimited. Admins aren’t counted

With a local model, no data leaves your machine.

In the browser

app.ts
const { text } = await sluurp.ai.chat([{ role: "user", text: "Summarise this week's notices" }]);

// Streaming:
await sluurp.ai.stream(turns, { onText: (piece, all) => (out.textContent = all) });

Both accept { system, signal }; aborting via the signal keeps what arrived so far. When a user hits their daily quota, the response says so instead of throwing.

In server code

ai(system, prompt, schema) returns JSON matching the schema, or null when no model is configured:

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 multi-turn tool use, see Agents.

Where Sluurp uses it

Pages shows its AI tools, and sluurp/ai provides an assistant for any app, only when a model is configured.