The authentication flow
A code received on an e-mail proves the e-mail, and the person is authenticated. This flow is the same everywhere: in the widget, in Claude, in ChatGPT, on WhatsApp. What changes from one surface to another is only where its steps show, and who keeps the result.
The station writes nothing more than its providers and the provider of each portal. Core derives the rest.
The invitation, and two ways in
Where the station can sign someone in and they are not, the conversation opens with an invitation to sign in: in the chat, not under the input. In the widget and the PWA it is the first bubble; in Claude and ChatGPT, the frame of the room's opening, with a "Sign in" button that opens the host's sign-in.
| entry | started by | the person may continue without |
|---|---|---|
a reserved skill, or the submit when submitted_by: owner | Core, when the person calls it (Asking for authentication) | no |
| the person asks: the invitation's button, or in words | sign_in: the steps show in the conversation | yes |
Autonomous agents
A coding agent or a LangChain agent has no window to open. The refusal it gets (401) says how to get a token: an MCP client that supports authorization runs the flow itself, opening a browser once; an agent without a browser gets from its operator a token obtained for it. The durable answer is the delegated sub-identity: a key the organisation gives its agent, with its limits. An agent is never handed a person's code.
The steps of a mechanism
Each mechanism is a sequence of steps. There are only four kinds:
| kind | means | example |
|---|---|---|
| input | a datum that is not secret | the e-mail |
| secret | a datum the model never sees | the code |
| redirect | an external page, then the return | the IdP, the tenant's sign-in page |
| silent | an exchange with no screen | the tenant site's signed assertion |
| mechanism | its steps |
|---|---|
otp | input the datum, then the secret (the code), then "verified" |
oidc | redirect to the IdP, then "verified" |
assertion | silent if the person is signed in on the tenant's site; otherwise redirect to its login_url |
What the person sees, by surface
| surface | where the steps show | what recognises them afterwards |
|---|---|---|
| widget, on the tenant's site | in the frame; nothing to do with assertion | their browser |
| PWA | in the frame | their browser |
| Claude, ChatGPT | Claude or ChatGPT opens its sign-in window; it leads to the tenant's Convoy page, with the same steps | their Claude or ChatGPT account, from one conversation to the next |
| in the conversation: Core asks the questions and reads the answers, the model does not see them; the phone is already proved by the channel | their number | |
| Teams, Slack | nothing to do if the organisation's IdP is the station's; otherwise a "Sign in" card | their platform account |
What recognises them is the holder: the most durable thing the surface can identify. The authentication belongs to it. It belongs neither to the conversation — a new conversation in Claude does not ask to sign in again — nor to the room.
The room and the person
- A room made by a signed-in person is theirs from the start. A room no one owns becomes theirs when they open it signed in, on any surface.
- Their rooms follow them. Signed in, a person who arrives without a room code (a new device,
Claude, ChatGPT) finds the room they used last, wherever it was. The ⋮ menu and the
room_listtool list their other rooms; New conversation makes one. - Only a use by someone who may enter counts as "last used". Reading a room, or opening it with its code without owning it, does not change the room they come back to.
- The list says what each room is about (the names of the facts kept), never what was said in it.
- If their rooms cannot be read, the call fails: no empty room is made in their place.
- A room's code gives no rights. Someone who opens the room with its code sees the selection,
but is not signed in for that: profiles, permissions and
submitted_by: ownerread the signed-in person, never the room.
On Claude and ChatGPT
Claude and ChatGPT follow the same method, MCP authorization (OAuth 2.1). The connector installs without signing in. When Core decides that signing in is needed, the MCP door sends the host the signal it expects; the host opens its sign-in window, then runs the call again itself.
For this, Convoy runs one authorization server per tenant. Its page proves nothing by itself: it
runs the provider's steps (the tenant's send and check operations, its IdP, its sign-in page),
then gives the host a token valid for Convoy's tools only. The token carries only the person's
opaque id, never the e-mail, and it is never passed to the tenant's API. There is no Convoy account
and no Convoy password.
What holds everywhere
- Only Core decides that signing in is needed. The model never starts it where the surface can show the steps.
- The model sees neither the datum nor the code.
- Authentication belongs to the holder; the room keeps its owner; a room's code authenticates no one.
- The code is checked by the provider only, and Convoy does not keep it.
- A call run again goes through every rule again.
- A value has one spelling.
- The provider's sentence reaches the person, the value masked: its refusal, and, on a sent code, where to read it (a demo inbox, the spam folder).
A new surface or a new mechanism is added only by passing the tests that check these seven points.