> ## Documentation Index
> Fetch the complete documentation index at: https://docs.concatflow.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How Concatflow works

> Three pieces, two doors, and why every value on screen comes from your database.

Concatflow puts an assistant in your product. It is a search bar or a chat bubble. Your customers type a question in plain language. The assistant queries your data and answers with text, tables, charts, lists, maps and detail cards.

## Three pieces

Three pieces run in three places.

| Piece | Runs in | Does |
| - | - | - |
| `widget.js` | your page | Draws the bar or the bubble. Opens an iframe on first use. Nothing else. |
| The assistant iframe | Concatflow's origin | Holds the conversation, calls the model, renders the answer. |
| Your server (per-user door only) | your backend | Says who is logged in, with your secret API key. |

The conversation never runs in your page. If it did, any flaw on Concatflow's side would reach your customer's session on your site. The iframe keeps the two apart.

## Two doors

An assistant has two doors. You open one, the other, or both, in the assistant's **Doors** tab.

> **Public door**
>
> For anonymous visitors. Your page carries a public **site token** (`st_…`). The assistant only reads the tables you marked public, and only rows shared by all customers.
>
> No server code. [Start here](https://docs.concatflow.com/quickstart.md).

> **Per-user door**
>
> For logged-in customers. Your server opens a **session** for one customer and hands a short-lived token to the page. The assistant only sees that customer's rows.
>
> A few lines on your server. [Read the guide](https://docs.concatflow.com/guides/per-user-door.md).

On the per-user door, you are the identity provider. Your server tells Concatflow which customer is logged in, for example `{ customer_id: "4712" }`. The browser never sees that. It only holds an opaque token that describes nothing and expires after 15 minutes.

## Every displayed value comes from your database

The model never writes the values you see in an interface.

When the assistant shows a list, a map or a detail card, the model only writes **keys**: a result ID such as `r1`, or an entity key such as `LP-1934`. The server then reads every price, title, image, address and link from your database, through the same access guard as the query. A list always shows the whole query result, in its order: the model cannot pick which rows to show.

Tables, metrics and charts are built the same way, from the rows of a query that passed the guard.

> [!NOTE]
>
> The written sentence around an interface is the model's. The assistant is instructed not to repeat figures in it: the interface shows them.

## What your customers never see

* SQL, table names or your schema. The model needs them to write queries. They never leave the server.
* Another customer's rows. On the per-user door, every query is filtered on the partition your server sent.
* Your API key. It stays on your server.

## Next steps

**1. Get your identifiers**

Find your site token, assistant ID and API key. [Where to find them](https://docs.concatflow.com/identifiers.md).

**2. Embed the public door**

Two tags in your page. [Quickstart](https://docs.concatflow.com/quickstart.md).

**3. Open the per-user door**

One route on your server, one call in your page. [Per-user door](https://docs.concatflow.com/guides/per-user-door.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.