Skip to content

Multi-tenancy

Myra AI Workspace organises everything into two levels: tenants and gateways.

A tenant is the top-level account — typically one company, application, or team. A gateway is a named deployment inside a tenant, such as production or staging. Each gateway has its own API keys, auth tokens, rate limits, and routing rules, completely isolated from every other gateway.

Most organisations start with one tenant and one or two gateways (e.g. production and development). Additional tenants are appropriate when you need to provide the gateway service to separate customers or business units with billing isolation between them.

Myra AI Workspace serves many tenants and gateways from a single process, with hard isolation boundaries between them.


Object hierarchy

graph TD
    T["Tenant<br/>budget · plan"]
    T --> G["Gateway<br/>config · provider keys<br/>auth tokens · routing rules"]
    T --> U["User<br/>role: admin · tenant_admin · ki_manager<br/>member · finance · viewer"]

A Tenant is the top-level grouping for users and gateways. Each tenant can have multiple Gateways — each gateway is an independent policy domain with its own config, keys, tokens, and rules.

Users belong to a tenant. The role of a user determines what the user can do within that tenant.

Whole product areas are per-tenant feature toggles: Agents, Workflows, Scheduled Tasks, and Billing settings are each enabled or disabled in tenant config, and the app hides a disabled area for that tenant's users. See Feature availability and the Tenants & gateways API.

Tenants list


URL routing

Every inference request encodes the tenant and gateway in the URL path:

POST /v1/{tenant_slug}/{gateway_slug}/{provider}/chat/completions
POST /v1/{tenant_slug}/{gateway_slug}/compat/chat/completions

The gateway resolves {tenant_slug} and {gateway_slug} on every request and loads the corresponding gateway config. Configuration changes take effect within seconds.


Isolation mechanisms

Boundary Mechanism
URL routing {tenant_slug}/{gateway_slug} prefix resolved on every request; unknown slugs return 404 tenant_not_found
Internal state isolation All internal state is namespaced per tenant and gateway — no cross-tenant data leakage is possible
Storage All data is strictly scoped to the owning tenant at the storage layer; cross-tenant access is not possible
BYOK keys Encrypted at rest; decrypted only for the matching gateway at request time
Auth tokens Scoped to a single gateway; a token issued for gateway A is rejected on gateway B
Rate limits and budgets Tracked per gateway, not shared across tenants or gateways

User roles

Role Can send inference? Administration
admin Yes Platform-wide: every tenant, gateway, user, token, routing rule, and provider key.
tenant_admin Yes Their own tenant: users, gateways, tenant settings, and the finance console.
ki_manager Yes Their own tenant: groups and workflows, plus group-scoped cost analytics. No user, tenant, or gateway administration.
member Yes None beyond their own account: chat, inference, and personal authentication tokens.
finance Yes Their own tenant: the finance and cost console only. No user, tenant, or gateway administration.
viewer No — returns 403 forbidden Read-only within their tenant.
demouser Demo entry point only (per-prompt cap) — entry point disabled, AGF-2997 None.

Role is enforced at the authentication step: a viewer token — and any token whose user has an unknown or disabled role — is rejected with 403 forbidden before the request body is read.

Role controls administration capability and whether inference is permitted; it never widens which gateway a token reaches. Every authentication token — an administrator's included — is scoped to a single gateway (see Isolation mechanisms above): a token issued for gateway A is rejected on gateway B. To call a second gateway, create a token on that gateway.

Deleting a user immediately disables all authentication tokens of that user.


Auth tokens

Tokens are scoped to a single gateway and carry optional per-token overrides:

Field Description
label Human-readable name, e.g. "ci-pipeline"
expiration Unix timestamp (seconds since epoch); requests after this date return 401
rate_limit {"requests": N, "window_sec": S} — overrides gateway-level rate limit
budget_usd Per-token spending cap; enforced independently of — and in addition to — the gateway budget (a request is refused when either is exhausted)
user_id Optional binding to a user; recorded in request logs

Token values are stored as a one-way hash. The plaintext token is shown only once at creation time — it cannot be recovered.

⚠️ Caution: Store the token value immediately after creation. The plaintext token is displayed only once and cannot be retrieved again.


See also