# Concepts

## Tenant
A business using Snakkbar, identified by a short id such as `amatec`. A tenant has an AI assistant
(name, portrait, tone, instructions), a website (`siteHosts`) the assistant reads, a knowledge base,
staff, and settings. Pages may only show the chat if their origin is in the tenant's
**allowed origins** (Settings → *Nettsteder som kan vise chatten*).

## Visitor
Someone chatting on the tenant's site.
- **Anonymous visitor** (default): the SDK creates one on first use and keeps its token in
  `localStorage`. Their chat history follows that browser.
- **Identified visitor**: your backend mints a visitor token for your own user id
  (`POST /api/v1/server/visitor-tokens`). Their chat history follows the user across devices, and
  staff see their name and email.

**Profile.** A visitor can carry `name`, `email`, `phone`, `company` and up to 30 custom
`attributes` (e.g. customer number, plan). Your backend sets them, trusted, with the visitor
token; the site can also send them from the browser (`Snakkbar.setUser`, `updateProfile`), which
is unverified and, for identified visitors, only fills gaps. Staff see the profile; the assistant
uses it instead of asking again.

**Live visitors.** While the widget (or the SDK's `startTracking()`) is on a page, the visitor
shows up for staff in «Besøkende», also before any chat: **online** means a heartbeat in the last
35 seconds. Staff see the current page, navigation history, device, rough location and where the
session came from (a session starts after 30 minutes of silence), and can **watch** a visitor:
their cursor, clicks and scroll, drawn over the same page in the operator's browser. No page
content is ever sent. A tenant switch (`liveVisitors`) turns it off, e.g. for sites without
consent for it. See [widget.md](widget.md#live-visitors) and [security.md](security.md#live-visitors).

## Operator
A staff member who answers chats.
- **Hosted operators** log in at `<host>/panel` with Snakkbar (Supabase) credentials.
- **Embedded operators** are users of the tenant's own system. Your backend exchanges its own
  session for a short-lived Snakkbar operator token (`POST /api/v1/server/operator-tokens`).
- **Both at once.** An operator your backend provisions (with an `externalId` and an e-mail) can
  also sign in to the hosted panel and the app with that e-mail (one-time link or code, no
  password). The first verified sign-in links the login to the existing row, so hosted and embedded
  use are the *same* operator: same id, history, departments and notification settings. Your
  backend keeps control of the row: removing the operator, changing the e-mail or reactivating
  them drops the panel login. See [api.md](api.md#panel-sign-in-for-provisioned-operators).
- **System operators** (`system: true`, set by your backend) are integration accounts: they can act
  through the API but are hidden from the team, @-mentions, round-robin, alerts and the dashboard.
Roles: `agent` (answers chats, manages knowledge) and `admin` (also settings, API keys, deleting
conversations). For an operator with an `externalId` the role is set by the customer's backend
only.

**Presence.** An operator who is *checked in* (`available: true`) and has sent a heartbeat in the
last 60 seconds is **online**. Checked in and active within the tenant's `nearbyMinutes` (default
30) is **nearby**. Visitors see nearby people in the team row and can @-mention them; the launcher
shows an online person's face.

## Conversation
One chat thread between a visitor, the assistant and any number of operators.

| Status | Meaning |
| --- | --- |
| `ai` | The assistant answers every visitor message. |
| `human` | An operator owns it. The assistant stays quiet unless someone writes `@<assistant>`. |
| `closed` | Closed by staff. A new visitor message reopens it with the assistant. |

**Owner and participants.** Operators *join* a conversation (become participants). One participant
is the *owner*. *Take over* makes you the owner. *Give back* (`release`) hands ownership to the next
participant, or back to the assistant when none is left. *Leave* stops participating.

**Asking for a person.** A visitor asks for a person by tapping a face, writing `@kari`, or saying
something like "kan jeg snakke med et menneske?". The assistant can do the same on the visitor's
behalf. Snakkbar writes a `requested` notice in the chat and alerts the named people, or the people
who are nearby, or the whole team. Staff see it as «Spør etter deg». If nobody is available, the
visitor can leave a callback request.

## Messages
Every message has a `role` (`visitor`, `assistant`, `operator`, `system`) and a `kind`: normal
`message`, assistant `products` (cards) and `suggestions` (reply chips), and system notices
(`joined`, `left`, `requested`, `navigation`, `handoff`, `callback`, `closed`). Messages can carry
up to 4 images.

**Translation.** Each reader reads in their own language. Visitors' messages are translated into
each operator's language; operator replies are translated into the visitor's language before the
visitor sees them. A message shows `translation` when one exists for the reader; UIs show it by
default with a «Vis original» toggle.

## The assistant
An AI agent (Claude, run by Snakkbar) with tools to search and read the tenant's website, search
uploaded documents and approved answers, show product cards, suggest replies, ask for a person and
register callbacks. It answers in the visitor's language.

## Overview
«Oversikt» in the admin (`GET /operator/dashboard`) sums up a period of 1–90 days in the tenant's
time zone: visitors and pageviews, conversations and how many a person joined, requests for a
person and the median time to the first reply, callbacks, conversations per day and hour, and the
top pages, plus what is happening right now.

## Knowledge
- **Website**: read live from `siteHosts`.
- **Documents**: PDF, Word, text, Markdown, CSV, or single web pages, uploaded in the admin.
- **Approved answers**: every operator reply becomes a *suggestion* pairing the visitor's question
  with the reply. When an admin approves it, the assistant can use it from then on.
