Docs

Roles & Permissions

Named permission sets with read and write scopes — the authority behind every admin action.

What a Role Is

Every account carries exactly one role, and the link can never dangle.

A role is a named bundle of permission scopes assigned to platform accounts — human accounts and MCP accounts (the AI agents' logins) alike. Every account points at exactly one role, and KeenAgents guarantees that link is always valid — an account can never reference a role that does not exist, and deleting a role never leaves accounts behind. A role carries a human-facing Title, a machine Slug derived automatically from the title, and two scope lists: what the role can read (view) and what it can write (modify). Both title and slug are unique across your organization.

Permission changes take effect right away: saving a role signs out everyone currently signed in under it — they see Your access changed — please sign in again. and get the new permissions when they sign back in. An MCP account holding the role picks the change up at its next authentication. There is nothing for you to trigger.

Core Concepts

Slug
Generated from the title on create and on every rename: the title is lowercased, and spaces and punctuation become underscores — "Support Team" derives support_team. You never enter it directly. It is the role's stable identifier: what accounts reference and what integrations should store.
Write implies read
A writable scope is always readable too — after every save, KeenAgents ensures the read list contains everything in the write list, no matter what was sent. The permissions board makes the coupling visible: Write can only be switched on while Assigned is on, and switching Assigned off clears Write with it. Why: a role that can change something it cannot see would be an inconsistent grant.
Partial updates
A save that changes only one of the two lists never disturbs the other — KeenAgents combines what you sent with the stored value of the list you left out. A read-only change cannot strand stale write grants, and a write-only change cannot silently shrink read access.
Protected platform roles
Four roles ship with every organization and can never be deleted: admin ("Administrator"), owner ("Owner"), developer ("Developer") and default ("Default"). admin, owner and default cannot be edited at all; developer allows permission edits but keeps its title locked. default is additionally the landing role for accounts — human or MCP — whose role is deleted.
Audit trail
Every role create, update and delete is recorded in the audit trail together with who performed it — the operator's email, user id and role. Why: permission changes are the highest-impact admin actions, and the record answers "who granted this" later.

Permission Scopes

A closed set of fourteen values — unknown scopes are refused outright.

Scopes come from a fixed catalog; a value outside it can never be granted. The fourteen values: roles, account, consumer, spaces, agents, api_keys, clients, certificates, contracts, webhooks, cache, logs, mcp_accounts, mcp_consumers. All fourteen appear on the admin permissions board:

ScopeSurfaceRead grantsWrite grants
accountAccounts — platform user managementView accountsCreate/edit/delete accounts, assign roles
consumerConsumers — end-user managementView consumersCreate/edit/delete consumer accounts, assign their contracts
rolesRoles — permission managementView rolesCreate/edit/delete role definitions and their permissions
spacesAI Spaces — workspace managementView spaces and their deployment tokensCreate/edit/delete the spaces where agents are deployed
agentsAgents — AI agent managementView agents and their settingsCreate/edit/delete agents within spaces
api_keysAPI Keys — application secret managementView issued keys and their bindingsCreate/rotate/revoke keys
clientsClients — partner client credentialsView clientsCreate/rotate/delete client id and secret pairs
certificatesCertificates — signing certificatesView certificates and their public keysGenerate/rotate/delete certificate pairs
contractsContracts — consumer contractsView contracts, their spaces and policiesCreate/edit/delete contracts and their assignments
webhooksWebhooks — partner webhook recordsView webhook recordsCreate/edit/delete the name, origin and webhook bindings
cacheCache — platform cache administrationView cache statusCreate or invalidate platform caches
logsLogs — platform activity and flow execution logsView logsEnable/disable log channels
mcp_accountsMCP Accounts — the AI agents' loginsView MCP accounts (an MCP account may do this too, to check one exists)Create them, assign their role, enable or disable, rotate the secret, delete — humans only: an MCP account never gets these, whatever its role
mcp_consumersMCP Consumers — the consumers an AI agent creates for itselfView MCP consumersLets an MCP account create them, assign their contract and spaces, enable/disable, rotate, delete and mint their token through the MCP server; a human with this write level gets three console controls — the Enabled switch (Save), Rotate Secret and Delete — never Create or assign

Rules & Limits

  • Title is required and non-empty; the admin form trims it and caps it at 60 characters.
  • Forbidden titles: a title that is or merely contains a protected name — admin, owner, developer or default, matched case-insensitively — is refused at create and update with "title cannot be or include "admin", "owner", "developer" or "default"". "Default Support" fails; "Support" passes. Why: custom roles must never masquerade as the built-in ones.
  • Title and slug are both unique. Because the slug is normalized, two visually different titles can collide — "Support Team" and "Support-Team" both derive support_team, and the second create is refused as a duplicate.
  • Every granted scope must belong to the fourteen-value catalog; anything else is refused with "each permission must be one of: roles, account, consumer, spaces, agents, api_keys, clients, certificates, contracts, webhooks, cache, logs, mcp_accounts, mcp_consumers".
  • After every save the read list contains everything in the write list. The form additionally refuses submission when a write scope is not readable ("A writable scope must be readable too").
  • Protected roles: none of the four can be deleted; admin/owner/default refuse any update; developer ignores title changes but accepts permission edits.
  • Renaming a role regenerates its slug, and every assigned account follows in the same atomic step — accounts are never split between the old and the new name.
  • Refusals are deliberately general: a duplicate title, a protected role or an unknown role all answer with the same terse refusal, and only input-validation errors explain what to fix. Why: error responses should help you correct input, not map out the platform's internal state.

In the Admin UI

Where roles live, and what happens on delete.

  • /roles — Role Management landing page with a create card and a list card.
  • /roles/list — Role List: a table with sortable Title, Slug, ID and Created At columns (click a header to cycle ascending → descending → off) and a Visit link per row, plus a filter panel with repeatable rows of type + operator + value — free text for title, slug and id (equal / not / like / not like / in / not in) and a date picker for created at (equal / not / greater / less — day-granular). Filters live in the URL — refresh, share and back/forward all preserve them — and Clear All resets the list.
  • /roles/create — Create Role: a single Title field (helper text: "Up to 60 characters. The slug is derived from the title."). Success toasts and redirects straight to the new role's detail page, where permissions can be assigned.
  • /roles/<id> — Role Details: Title field + Permissions board + Save + Delete. Save is dirty-gated (enabled only when values actually deviate from the loaded role); Delete is two-step (Delete → Confirm delete / Cancel).
  • The Permissions board shows one row per catalog scope with an Assigned (read) and a Write switch. Caption: "Assigned grants read access; Write needs Assigned first. Turning Assigned off clears Write too."
  • Protected roles render a badge — protected — read only for admin/owner/default (entire form locked) and protected — title locked for developer (permissions still editable). All four hide the Delete button entirely.

Deleting a role is one atomic operation — there is no path that leaves an account pointing at a role that no longer exists:

  1. On confirm, KeenAgents refuses the delete if the role is protected or unknown.
  2. Otherwise, in a single atomic step, every account holding the role — human accounts and MCP accounts alike — is moved to default and the role is removed — either both happen or neither does.
  3. Anyone signed in under the deleted role is signed out, and permission checks across the platform reflect the change immediately.
  4. The action is written to the audit trail with the requester's email, id and role.
  5. The UI toasts 'Role "X" deleted — its accounts moved to "default"' and returns to the roles list.
Delete moves accounts silently
The move to default happens in the same step with no per-account confirmation of which accounts moved — MCP accounts included — and people working under the deleted role are signed out. Review who holds a role before deleting it.

Good to Know

  • Renaming a role regenerates its slug and every assigned account follows automatically — but anything external that stored the old slug string no longer matches. A rename is atomic, not a soft alias.
  • The four built-in platform roles start with empty permission lists — Administrator/Owner privileges are not expressed through the scope lists, which only drive the scope-gated surfaces.
  • Granting a write scope never fails for a missing read scope — the read grant is added automatically, so you never have to grant read separately.
  • The developer role fails "softly" on rename: a new title is ignored rather than rejected — the save succeeds, the permission changes apply, the title just stays "Developer".
  • Slug collisions are refusals even when titles differ — pick titles that normalize to distinct slugs, since the slug is the role's stable identifier.
  • The cache scope's write level separately gates the per-record Rebuild Resource Cache button on the Api Key, Client, Certificate, Contract, Webhook, Space and Agent detail pages: someone can hold a resource's own write scope and still not see Rebuild without cache:w — and, conversely, a cache manager can see Rebuild without holding that resource's write scope. (On an Api Key the button rebuilds only what is bound to that key — see Resource Cache.)
  • Two rules sit above the scope table. An MCP account (an AI agent's login) can never manage Accounts, Roles or MCP Accounts — those surfaces refuse it whatever its role, and it may only view human consumers. Conversely, creating an MCP consumer, assigning its contract and spaces and minting its token can only be done by an MCP account; a human with mcp_consumers write gets exactly the Enabled switch, Rotate Secret and Delete. See MCP Accounts.
  • The sidebar shows only the sections your role can read; a section whose entries are all hidden disappears with its title. Opening a page you lack read on shows You don't have permission to view this page — ask an administrator to grant the scope under Roles.
  • An MCP account is never signed out by a role change — it applies at its next authentication.

Previous

MCP Accounts

Next

Spaces

Keen Agents 2026

Documentation

Release 15