Docs
Tenant
A company. It is the boundary everything else sits inside — people, agents, connections, credentials, knowledge — and nothing crosses it.
Has: a slug (its address in the Hub) · a name · a timezone · a plan · the Slack workspace it is linked to · many memberships · many agents · its own connections, credentials and secrets. Deleting a tenant takes all of those with it. Accounts survive: a person belongs to the platform, not to one tenant.
Creating one, and changing it
Only a platform operator sees every tenant on the platform and creates a new one. Anyone else asking for that screen is taken to their own tenant.
TENANT-OPERATOR-CREATESA tenant's slug is its address in the Hub: 1–40 lowercase letters, digits or dashes. Anything else is refused and nothing is created.
e.g.
TENANT-SLUGBad Slug→ refused, with the reason.A slug that would sit on top of one of the Hub's own pages — admin, sign-in, api, healthz, readyz, access-denied, verify-request — is refused.
TENANT-RESERVED-SLUGSTwo tenants never share a slug: a second attempt is refused and the tenant already holding it is untouched.
TENANT-SLUG-IS-UNIQUEA tenant must be given a name. A blank one is refused and nothing is created.
TENANT-NAME-REQUIREDA tenant's timezone is an IANA name, and it is the local time its agents work in. An unknown name is refused; none given means UTC.
e.g.
TENANT-TIMEZONEMars/Olympus→ refused.The operator may name a first owner when creating a tenant; that person is invited as owner (MEMBER-INVITE-IS-INSTANT) and the Members screen opens. Left blank, the tenant starts empty.
e.g. the invite fails → the tenant still exists, and the message says to invite them from Members.
TENANT-FIRST-OWNERCreating a tenant does not put the operator in it; an operator reaches every tenant anyway (MEMBER-OPERATOR-OWNS-ALL).
TENANT-CREATOR-NOT-MEMBER
Nothing crosses it
A tenant's data is reached by its slug. An unknown slug is "no such tenant", and another tenant's agent or member is simply not found.
TENANT-SCOPED-BY-SLUG
Its Slack workspace
A tenant records which Slack workspace it is in, learned when one of its agents' apps is installed, and shows it on the tenants list.
TENANT-SLACK-WORKSPACE-LINKA Slack workspace belongs to one tenant, from its first agent's binding on, and stays that tenant's when its agents are disabled or removed. An agent of another tenant binding to it is refused, and the binding already there stands; two tenants claiming it at once, one wins, and one tenant claiming two workspaces at once keeps one. The database enforces it: an upgrade that finds a workspace already claimed by two tenants stops, naming them, rather than start without that guard.
e.g. initech and globex agents both bound to workspace T1 before the upgrade → the upgrade fails with "T1: globex, initech"; nothing starts until it is resolved by hand.
TENANT-WORKSPACE-IS-THE-TENANTSThe workspace token is entered once, in the tenant's Settings, by an owner or admin. Every agent in that workspace is pushed, renamed and synced with it; an agent's screen never asks for it, and names the workspace whose token it uses. (An app made before the tenant had one keeps SLACK-PER-APP-TOKEN.)
e.g. a token is stored; an owner creates Golf → Push to Slack creates Golf's app with no configuration token asked; Slack may still ask someone to approve the install.
e.g. no token yet → the agent's screen says so and links to Settings; it does not take the token itself.
TENANT-WORKSPACE-TOKEN-ONCEThe workspace token that lets Tonoman create a tenant's Slack apps is never shown again; a person is told only that one is on file and when it expires.
TENANT-WORKSPACE-TOKEN-BY-REFERENCEA pasted workspace token is used once to prove it works before it is kept. A spent or wrong one is refused with the reason and nothing is saved.
TENANT-WORKSPACE-TOKEN-PROVEDA workspace token is kept only if it is for this tenant's workspace. One for another workspace is refused, and the token already stored keeps working.
e.g. saving workspace B's token over A's → refused; A's agents and token are unchanged.
TENANT-WORKSPACE-TOKEN-RIGHT-WORKSPACE
What a person sees
The person's own row at the foot of the rail is a button: it opens a menu with who they are signed in as, every tenant they belong to with a tick on the one they are in, and Sign out. Choosing a tenant goes there in one click and closes the menu; Escape or a click outside closes it. A person in one tenant sees that one tenant, ticked. Replaces a "Switch to …" line per tenant, which grows without end.
e.g. Ana (Globex, Northwind, Initech) on Initech → the menu shows all three, Initech ticked; Northwind → Northwind's agents.
TENANT-RAIL-SWITCHERAn operator opens any tenant by its address, reads it as an owner, and carries an Admin row in the rail nobody else has.
TENANT-OPERATOR-SEES-ALLEach tenant on the operator's list shows its slug, timezone, plan and Slack workspace, and its member and agent counts lead into those screens.
TENANT-ADMIN-LISTAn operator deactivates a tenant from Admin › Tenants, and reactivates it there. While inactive its agents are not served (gone from every worker's roster, so they answer nobody), its people cannot open it in the Hub, and nothing of it is deleted — people, agents, brains, credentials and runs all stay. The operator still sees it, marked Inactive. Reactivating puts everything back as it was.
TENANT-DEACTIVATEDeactivating a tenant closes it to people already signed in, at their next page, and reactivating opens it again: the Hub asks the registry who may open a tenant on every page instead of trusting the memberships stamped on the session at sign-in. The registry's
/v1/tenants/:slug/*routes answer only the Hub's own system token, so the Hub's gate is the gate.e.g. a trial tenant ends → Deactivate → its agent stops answering in Slack within the worker's next roster read; Reactivate → it answers again.
TENANT-DEACTIVATE-OPEN-SESSIONSEach tenant on the operator's list leads to its people in Admin › Members, filtered to that tenant (MEMBER-ONE-PAGE-TWO-PLACES).
TENANT-ADMIN-MEMBERS-LINKThe member count is the people on the tenant's Members list: those invited, an operator too if invited, never the operator's automatic ownership. An ownership given before this was recorded counts as invited.
TENANT-ADMIN-COUNTS-PEOPLE
Its mission
A tenant has one mission, shared by all its agents; setting it replaces it, a blank one is refused, and one never set reads as empty.
TENANT-MISSION
Its vocabulary
A tenant has one list of names to spell right, shared by all its agents: the words a transcriber mishears — client names, people, products, its own jargon. Setting it replaces it; an empty one is allowed and means nothing beyond what the registry already knows; one never set reads as empty. Everything on it is a hint to the transcriber and the write-up, which may still mishear a word: the tenant's spelling wins where it and a known name differ only in case.
TENANT-VOCABULARYTwo names the registry knows are hinted without being typed: the tenant's own name, and its agents' names, in name order. Nothing else is gathered: the people an agent knows are named by the tenant in its own words or not at all, because a name sent to a transcriber is a disclosure the tenant decides, and the folders meetings file under are matching rules, not words anyone says.
TENANT-VOCABULARY-KNOWN-NAMESThe list an agent works with is the tenant's own words first, then the known names, without repeats, cut whole words from the end so that all of it fits what a transcriber takes as a hint (600 characters, under Whisper's 224 tokens for proper nouns); what was cut is said in the Hub.
e.g. a tenant with 30 client names and 4 agents → its 30 names, then its name and its agents, until the limit.
TENANT-VOCABULARY-FITSThe list is written on the tenant's Settings page, beside the workspace token; everyone in the tenant may look, owners and admins change it (the Hub decides who, as on every screen); under it the Hub shows the list as agents will get it and what did not fit. A change reaches agents on their next roster reload, within a minute.
TENANT-VOCABULARY-IN-SETTINGSAn agent served from the registry spells with its own tenant's list and no other: a worker serving several tenants keeps them apart, and a roster with no list means none — never the worker's environment. Only a worker with no registry at all takes a list from its own configuration, and the open-source default is none: the words to spell are a tenant's knowledge and never ship in the code. Where the list is used — the transcriber's hint, the write-up's spelling, any transcription done for the tenant — is the skill's business (SKILL-GETS-TENANT-CONTEXT).
TENANT-VOCABULARY-IS-THE-TENANTS