Scopes
Complete reference for Nenjo's scope system covering API keys, platform scopes, and mode escalation.
Scopes
Scopes control what actions an API key, agent role, or mode session can perform. They apply consistently across the MCP server, worker execution, and mode system.
Scope Format
Scopes follow the pattern resource:permission:
projects:read
projects:write
agents:readEach MCP resource family has a :read and :write scope.
Scopes stay coarse even when the MCP API exposes subresources. For example, agent prompt and agent MCP assignment operations still use agents:read and agents:write, not agents:prompt:read.
Complete Scope Reference
| Scope | Description |
|---|---|
agents:read | Read agents and agent subresources like prompt, scopes, abilities, context blocks, and MCP assignments |
agents:write | Modify agents and agent subresources |
projects:read | Read projects plus project-scoped tasks, documents, executions, and graph queries |
projects:write | Modify projects plus project-scoped tasks, documents, and executions |
routines:read | Read routines plus steps, edges, and councils |
routines:write | Modify routines plus steps, edges, and councils |
mcp_servers:read | Read MCP server configurations |
mcp_servers:write | Modify MCP server configurations |
chat:read | Read chat sessions and messages |
chat:write | Send chat notifications and other write-side chat actions |
models:read | Read model configurations |
models:write | Modify model configurations |
Total: 12 scopes across 6 resource groups.
Scope Rules
Write Implies Read
A :write scope automatically grants the corresponding :read scope for the same resource. If a key has projects:write, it can also perform projects:read operations without explicitly listing both.
Empty Scopes = Full Access
An API key or role with an empty scopes array has unrestricted access to all resources. This is the default when creating a key without specifying scopes.
Scope Checking Logic
The scope check follows this logic:
- If the scopes array is empty, access is granted (full access).
- If the exact scope is present, access is granted.
- If the requested scope is
:readand the corresponding:writescope is present, access is granted. - Otherwise, access is denied.
Where Scopes Apply
Scopes are used in three contexts with consistent behavior:
API Key Scopes
When you create an API key, the scopes field restricts which MCP tools are accessible. The tools/list response only includes tools whose scope is satisfied by the key's scopes.
{
"name": "Read-only Key",
"scopes": ["projects:read", "routines:read", "models:read"]
}This key can see the projects, routines, and models MCP tools, but not their write operations.
Subresources Do Not Add New Scope Names
Nenjo's MCP API may require an explicit subresource for some calls, especially under agents, but the scope check still happens at the top-level resource.
Examples:
- reading an agent prompt uses
resource = "agents",subresource = "prompt",action = "get", and still requiresagents:read - assigning an MCP server to an agent uses
resource = "agents",subresource = "mcp",action = "assign", and still requiresagents:write
Platform Scopes (Agent Roles)
Each agent role has a platform_scopes field (TEXT[] in the database) that controls which MCP tools the worker makes available when building the agent's tool set. These scopes are checked at agent build time and work identically to API key scopes.
Platform scopes are configured per role and are seeded with sensible defaults for system roles.
Mode Additional Scopes
Modes can temporarily escalate an agent's platform scopes for the duration of a mode session through the additional_scopes field in the mode's ModeToolConfig:
{
"additional_scopes": ["projects:write", "agents:write"]
}When a mode session is active, the worker merges these additional scopes with the role's base platform_scopes before filtering MCP tools. This allows modes like /the-creator to grant write access that the role does not normally have.
Worker Filtering
For Nenjo's built-in MCP tools, the worker relies primarily on server-side filtering via tools/list(agent_scopes=...). Those tools do not need per-tool scope strings because the backend enforces access dynamically from the MCP request arguments.
Legacy or external tools may still include explicit per-tool scopes, and the worker can use those when present.
Examples
Minimal read-only key
curl -X POST \
-H "Authorization: Bearer <clerk-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Dashboard Reader",
"scopes": ["projects:read", "routines:read", "models:read"]
}' \
https://your-instance/api/v1/api-keysFull-access key (no scopes)
curl -X POST \
-H "Authorization: Bearer <clerk-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Worker Full Access"
}' \
https://your-instance/api/v1/api-keysWrite-only for a specific resource
curl -X POST \
-H "Authorization: Bearer <clerk-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Project Manager",
"scopes": ["projects:write"]
}' \
https://your-instance/api/v1/api-keysThis key can read and write the projects MCP family (:write implies :read) but has no access to any other resource family.