Administration Members & roles Custom roles

Custom roles

A custom role is a named, admin-authored set of permissions from a fixed catalog, assigned to a member in place of one of the four system roles. It is not a fifth rung on the hierarchy — it replaces the member's rank entirely, pinning it to viewer for every rank-based check in the system, and grants access only through the specific permissions it carries.

That pin matters in one concrete way: a custom-role member does not inherit anything from "viewer" just because their rank reads viewer. Every resource they can reach, they reach because the role explicitly grants it — never because the rank check quietly passed.

Creating a custom role from the permission catalog, then assigning it to a member

The permission catalog

Permissions are named resource:aspect. Most resources have two aspects — view and manage (create, edit and delete bundled). A few resources where one action is genuinely irreversible split into three: view, write (create + edit) and delete as its own, separately grantable tier — Agents, Tool Registry, MCP Servers, Alerts and Members & Roles all work this way, so a role can edit an agent without being able to purge one.

ResourceWhat it covers
AgentsView / create & edit / delete an agent, including tool bindings and running or deploying it.
GuardrailsView / edit policy, autopause rules and denylist terms — no delete tier, every action here is reversible.
Tool Registry, MCP ServersView / write / delete, same three-tier shape as Agents.
Audit & observabilityRead the audit log; view traces, cost and dashboards.
Session InsightsView only — the cross-member team roster, per-person profiles, and team comparisons.
Billing & budgetsView only. No custom role can ever change a spend cap — that stays admin/owner rank, by design.
AlertsView / write / delete alert channels.
Members & rolesView / manage (invite, change role, assign a custom role, author roles) / delete (revoke an invite, delete a custom role).
API keys, SSO & SCIMView / write / delete keys; SSO/SCIM config is view / write, and the write side is reserved for owners only.
Model & provider configView the model catalog and provider secrets; view routing config and benchmarks.

Connectors, Workspaces and Org Settings are not in the catalog at all — those stay admin/owner rank only, with no custom-role path in.

Every permission key

The table above groups by resource; this is every individual key the role editor actually checks boxes against, grouped the same way.

Agents

PermissionNameWhat it allows
agents:viewView agentsSee agent inventory, config, and ownership.
agents:writeCreate & edit agentsRegister, edit, reassign owner, bind/unbind tools, run, or deploy an agent.
agents:deleteDelete agentsPurge an agent, or a purged tool binding. Permanent.

Guardrails

PermissionNameWhat it allows
guardrails:viewView guardrailsSee inbound + outbound policy, findings, activity feed.
guardrails:writeEdit guardrailsEdit inbound/outbound policy, autopause rules, denylist terms, and the per-agent on/off switch.

Tool & MCP governance

PermissionNameWhat it allows
tools:viewView tool registrySee the tool registry and agent bindings.
tools:writeCreate & edit tool registryRegister, edit, enable/disable, or bind/unbind a tool.
tools:deleteDelete tool registryPermanently delete an already-disabled tool.
mcp:viewView MCP serversSee registered MCP servers and their tools.
mcp:writeCreate & edit MCP serversRegister, edit, revoke, or enable/disable a server's tools.
mcp:deleteDelete MCP serversPermanently delete an already-revoked MCP server.

Audit & observability

PermissionNameWhat it allows
audit:readRead audit logRead the hash-chained audit ledger.
observability:viewView observabilityPer-call cost, tokens, audit linkage, dashboards, insights, notifications.

Session Insights

PermissionNameWhat it allows
sessions:viewView team Session InsightsSee the cross-member Session Insights team roster, per-person profiles, and team comparisons.

Billing & budgets

PermissionNameWhat it allows
billing:readView billingView invoices, plan, usage, and budget/rate-limit posture. There is no write permission here — changing a budget cap or rate limit stays admin/owner only.

Alerts

PermissionNameWhat it allows
alerts:viewView alert channelsSee configured budget-threshold alert channels.
alerts:writeCreate & edit alert channelsAdd, edit, or test-fire an alert channel.
alerts:deleteDelete alert channelsPermanently remove an alert channel.

Members & roles

PermissionNameWhat it allows
members:viewView membersSee the member, invite, and role list.
members:writeManage membersInvite/resend, change role/scopes, deactivate/reactivate, assign a custom role, and create/edit custom roles.
members:deleteDelete members & rolesRevoke a pending invite, or permanently delete a custom role.

Identity & access infra

PermissionNameWhat it allows
keys:viewView API keysSee a workspace's API keys and their last-used time.
keys:writeCreate & edit API keysCreate, edit or rotate your own developer keys. These keys can call any allowed model (the chat:write scope) and spend money, so set caps on them. Through a custom role this covers only keys you own: creating a key for someone else, reassigning one, or rotating another member's key is refused.
keys:deleteRevoke API keysPermanently revoke a developer key.
identity_config:viewView SSO/SCIM configSee the SSO / SCIM configuration status.
identity_config:writeManage SSO/SCIM configConfigure SSO connection and SCIM provisioning. Owner-only — no custom role can hold this.

Model & provider config

PermissionNameWhat it allows
models:viewView model catalogSee the served model catalog and live gateway configuration.
routing:viewView routingSee routing config, benchmarks, the routing model catalog, dry-run a routing plan, and past routing decisions.
routing:writeSend routing requestsExecute a routing request. This dispatches a real, billable call to a model.
secrets:viewView provider secretsSee which providers are configured, not the key values. There is no secrets:write/delete key — provider secrets stay admin/owner only, non-delegable.

Creating and assigning a role

  1. Open Members, Roles tab

    Admin and owner only. Lists the four system roles alongside every custom role already defined, each row showing its permission count and how many members currently hold it.

  2. New role: name it and pick permissions

    Tick individual resource:aspect boxes from the catalog above.

  3. Create role

    The role is validated against the catalog server-side — a permission key outside it is rejected, not silently dropped. It starts with zero members.

  4. Assign it

    From the Members tab, open a member's row ⋮ menu and choose Change role — the custom role appears in the same list as the four system roles. Or pick it directly while sending a new invite.

The Roles tab lists system and custom roles in one table — Role, Type (System or Custom), Permissions (a count), and Members (how many currently hold it) — so you can see at a glance how a custom role compares to the four built-in ones before assigning it.

Deleting a role that still has members assigned requires picking a reassignment role for them in the same action — there is no state where a member is left pointing at a role that no longer exists.

Some pages need more than one permission to render

A few console pages are agent-scoped: every real endpoint behind Guardrails, Tool Registry and MCP Servers reads or writes something under /v1/agents/{id}/.... A role holding only guardrails:view but not Agents access would open Guardrails to a page that 403s trying to load the agent list it needs to render its own table. Rather than let an admin build a role that looks complete but cannot actually be used, these three stay locked to whatever the Agents checkbox allows. API Keys works the same way against the model catalog: minting a key needs models:view for its model picker, so Keys access is locked to that too. Billing is not needed: without billing:read the Keys page still loads and keys can still be created; only the per-key spend column stays empty.

Read-scope grants

Beyond the permission catalog, a member can individually hold a small set of extra read scopes — audit:read, traces:read — layered on top of their role. These are not hand-picked through a dialog any more; they are seeded automatically when a member is invited or has their role changed, from a fixed default per role (viewer gets audit read; builder gets audit and traces read), and only when the member has no customized scopes of their own already. Admin and owner need no entry here — both already read everything through the role check itself.

How enforcement actually works

Every control-plane endpoint is gated by one of a small set of dependency checks, and they combine two things: a role floor, and (where the resource is in the permission catalog) a specific permission.

  • Role only (require_role("admin")) — the classic floor. A custom-role principal never passes this, at any level, because its rank is pinned to viewer regardless of what it can actually do.
  • Role or permission (require_permission_or_role) — the shape most catalog resources use. A caller passes if they hold the role floor or the specific permission key, whichever gets them there.
  • Role, scope, or permission (require_role_or_scope) — for resources reachable by both a human (role) and a machine API key (scope), now also admitting a custom-role principal via its permission.

A blocked request returns 403 naming what would have let it through — the role or the permission, whichever is relevant to how the caller authenticated. See Errors and refusals for the full shape of that response.

Next