Teams are the primary isolation unit in ManyLayers. Every API key belongs to a team. Every model access control, rate limit, token budget, and firewall setting is configured at the team level.
Use teams to reflect how your organization actually works — one team per product, department, or project. Each team operates independently: they have their own model allow-list, their own spending budget, and their own guardrail configuration.
What a team controls
| Setting | Description |
|---|
| Model allow-list | Which models this team’s keys can call. Requests to unlisted models return 403. |
| Rate limits | Requests per minute (RPM) and tokens per minute (TPM) for the team in aggregate. |
| Token budget | Monthly token cap. Exhausted budgets return 402 until the next period. |
| USD budget | Monthly spending cap in dollars. Enforced alongside the token budget. |
| Firewall mode | monitor (log prompt injection attempts) or block (reject them). |
| Default routing | The default gateway config applied to all requests from this team. |
Authorization model
Authorization has three rungs, and each is granted separately. Nothing is
inherited from the rung above it.
Organization → Product → Workspace
Organization
There is exactly one organization role: Owner, held by one person.
The Owner manages the organization — its members, its security settings, and
who may reach each product. That is authority over access to the products,
not access within them.
Owning the organization grants no product access. An Owner who has not been
granted Gateway cannot open Gateway, cannot call /v1, and sees no Gateway
workspaces. This is deliberate: the person who administers billing and
membership is often not a user of the products.
Ownership changes hands through an explicit, audited transfer. An organization
always has exactly one Owner — the database enforces it.
Product
Each product — Gateway, Studio, Deployer — is granted independently:
| Role | Access |
|---|
| No access | The default. The product is hidden in the switcher and every one of its API routes returns 403. |
| Member | Reads the product’s resources and uses them: calls models, holds conversations, views deployments. |
| Editor | Everything a Member does, plus creating and modifying resources — applications and keys in Gateway, agents and knowledge in Studio, training jobs in Deployer. |
| Admin | Everything an Editor does, plus product administration: providers, policies, guardrails, budgets, and who may reach the product’s workspaces. |
Product roles are product-specific. A Studio Editor authors agents; a Deployer
Editor runs training jobs and scales deployments. Granting one product never
grants another.
Workspace
A workspace belongs to exactly one product and takes the same three roles:
Admin, Editor, Member, set on the workspace’s own members list.
A workspace role is effective only while its holder also has access to the
workspace’s product. Gateway: No Access plus Gateway workspace: Admin is
denied. The membership is kept rather than deleted — it becomes effective
the moment the product is granted, so restoring somebody’s access is one
decision rather than a re-invitation to every workspace.
A product Admin reaches every workspace of their product, including ones
created later. An Editor or Member reaches only the workspaces they are a
member of, and inside one the workspace role decides what they can do — which
is what makes per-workspace permissions real.
Specific permissions
A role is a coarse bundle, and the useful cases often sit between two of them:
somebody who should manage rate limits and nothing else. Rather than promoting
them to Editor — which grants five other things — grant the single permission
on top of their role.
Permissions are namespaced to their product and can never cross:
gateway.policies.read studio.agents.manage deployer.training.manage
gateway.ratelimits.manage studio.knowledge.read deployer.deployments.scale
A grant is never a substitute for product access: gateway.policies.manage
held by somebody with no Gateway access grants nothing at all.
Roles and permissions are defined in application code, not in the database.
There is no roles table, no permissions table and no way to invent a permission
through the API — the database records only who holds what, where.
Account roles
Separately from the above, each account carries a role used by the content
routes: member, editor, admin. (curator was renamed to editor so that
a user row and an access row use one word for one authority.)
Account roles are assigned directly, or mapped from your identity provider’s
groups via the role_claim in your OIDC configuration.
Creating a team
From the admin UI: go to Admin → Teams → New team. Set the team name, choose which models to allow, and configure limits.
Via the API:
curl -X POST http://localhost:8180/admin/teams \
-H "Authorization: Bearer $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "engineering",
"allowed_models": ["gpt-4o", "claude-3-5-sonnet"],
"rpm_limit": 1000,
"tpm_limit": 500000,
"monthly_budget_usd": 500
}'
Adding members to a team
Users are assigned to a team when their account is created, or you can update their team membership later. In SSO deployments, team membership can be derived automatically from the team_claim in the JWT — so when someone joins the “engineering” group in your IdP, they’re automatically placed in the engineering gateway team.
Common patterns
One team per product — your mobile app, web app, and internal tools each get their own team with separate budgets. You can see exactly which product is spending what.
Shared model, different limits — both the data science team and the support team can use gpt-4o, but the data science team gets a higher TPM limit and larger monthly budget.
Strict customer-facing controls — your customer-facing product team is in firewall block mode with a conservative model allow-list. Internal tools teams are in monitor mode with broader model access.
Next steps