Roles & Access Control
GoClaw provides role-based access control (RBAC) to manage what users can do.
Overview
The access control system has three layers:
- Users — Who is allowed access (defined in
users.json) - Roles — What permissions a user has (defined in
goclaw.json) - Authentication — How users prove their identity
Users
Users are defined in users.json:
{
"users": [
{
"name": "Alice",
"role": "owner",
"identities": [
{"provider": "telegram", "id": "123456789"},
{"provider": "whatsapp", "id": "1234567890"},
{"provider": "http", "id": "alice"}
],
"credentials": [
{"type": "password", "hash": "<argon2-hash>", "label": "web-login"}
]
},
{
"name": "Ratpup",
"role": "user",
"identities": [
{"provider": "telegram", "id": "987654321"}
],
"permissions": ["read", "memory_search"]
}
]
}
| Field | Required | Description |
|---|---|---|
name | Yes | Display name |
role | Yes | owner or user |
identities | Yes | How to identify this user |
credentials | No | For password/API key auth |
permissions | No | Tool whitelist (non-owners only) |
Identities
Identities link external accounts to GoClaw users:
| Provider | ID Format | Example |
|---|---|---|
telegram | Telegram user ID | 123456789 |
whatsapp | Phone number (no +) | 1234567890 |
http | Username for web UI | alice |
local | owner for CLI | owner |
Built-in Roles
GoClaw recognizes three built-in role names:
| Role | Default Permissions | Description |
|---|---|---|
owner | Full access (built-in) | Has built-in defaults even if not defined in config |
user | Must define in config | Authenticated user with configurable permissions |
guest | Must define in config | Unauthenticated user — no access unless explicitly configured |
Security by default: Only owner has built-in permissions. Both user and guest roles must be explicitly defined in the roles section of goclaw.json or users with those roles will be denied access.
Role Configuration
Define custom role permissions in goclaw.json:
{
"roles": {
"owner": {
"tools": "*",
"skills": "*",
"memory": "full",
"transcripts": "all",
"commands": true
},
"user": {
"tools": ["read", "memory_search", "transcript"],
"skills": "*",
"memory": "full",
"transcripts": "own",
"commands": true
}
}
}
Note: The guest role is not defined by default (secure by default). See Unknown Users
for how to enable guest access.
| Option | Values | Description |
|---|---|---|
tools | "*" or ["tool1", "tool2"] | Allowed tools |
skills | "*" or ["skill1"] | Allowed skills |
memory | "full", "none" | Memory file access |
transcripts | "all", "own", "none" | Transcript search scope |
commands | true, false | Slash commands enabled |
systemPrompt | string | Custom system prompt |
systemPromptFile | path | Load prompt from file |
Authentication
Password Authentication
For web UI access:
goclaw user set-password <username>
This prompts for a password interactively and stores the hash in users.json.
API Key Authentication
For programmatic access:
{
"credentials": [
{"type": "apikey", "hash": "<hash>", "label": "automation-key"}
]
}
Role Elevation
The user_auth tool allows guests to elevate their role by providing credentials:
{
"auth": {
"script": "./scripts/auth.sh",
"allowedRoles": ["user"],
"rateLimit": 3,
"timeout": 10
}
}
| Option | Default | Description |
|---|---|---|
script | - | Auth script path |
allowedRoles | [] | Roles the script can grant |
rateLimit | 3 | Max attempts per minute |
timeout | 10 | Script timeout (seconds) |
Security rules:
- Elevation to
owneris always blocked — Even if the auth script returnsowner, GoClaw refuses. Owner access requires being defined inusers.json. - Role must be in
allowedRoles— The script can only grant roles explicitly listed. - Role must be defined — The target role must exist in the
rolesconfig.
Supervision
Owners can supervise active sessions — watching, guiding, or ghostwriting agent responses in real-time.
See Session Supervision for full documentation on:
- Real-time session monitoring
- Guidance messages (visible only to agent)
- Ghostwriting mode (respond as the agent)
- Interrupt generation
- Configuration options
Owner-Only Tooling
Some tools are deliberately restricted to owners because they control privileged background work or remote peer activity.
Delegated runs and subagent access
Subagent tooling is owner-only.
This includes:
subagent_spawnsubagent_statussubagent_cancelsubagent_fanout
How enforcement works:
- Registration gate (config):
- Tools are only registered when
tools.subagent.enabled=true.
- Tools are only registered when
- Delegated background-work gate (config):
- Subagents and related background runs are controlled by
gateway.delegatedRuns.enabled.
- Subagents and related background runs are controlled by
- Execution authorization (hard check):
- Each subagent tool checks
sessionCtx.User.IsOwner()at execution time. - Non-owner calls are rejected even if a role or user tool allowlist includes the tool name.
- Each subagent tool checks
This means subagent access cannot be granted to non-owner users by role config alone.
A2A tool access
The native a2a tool is also owner-only.
This includes all A2A tool actions:
statuspeerstaskspairpingsubmitresumecancel
How enforcement works:
- Role filtering:
- Non-owner users do not get the
a2atool in their normal tool list.
- Non-owner users do not get the
- Execution authorization (hard check):
- The tool also checks
sessionCtx.User.IsOwner()at execution time. - Non-owner calls are rejected even if a role or user tool allowlist accidentally includes
a2a.
- The tool also checks
This means A2A peer control cannot be granted to non-owner users by role config alone.
RBAC implications
- Keep normal users on bounded or readonly tools such as
read,memory_search, ortranscript. - Treat delegated tooling and A2A peer control as operator capabilities.
- If you need non-owner async or remote-peer workflows, prefer narrowly scoped custom tools rather than exposing subagent or A2A control directly.
Unknown Users and Guest Role
Users not in users.json are treated as guests. By default, no guest role is defined, which means unknown users have no access — this is secure by default.
To allow unknown users (e.g., for a public-facing bot with authentication):
{
"roles": {
"guest": {
"tools": ["read", "user_auth"],
"skills": [],
"memory": "none",
"transcripts": "none",
"commands": false,
"systemPrompt": "You are in guest mode. Ask the user for credentials to authenticate."
}
}
}
Important: If you define a guest role, consider:
- Keep permissions minimal (read-only, no skills)
- Include
user_authtool if you want guests to authenticate - Use a system prompt that guides the agent to request credentials
- The agent can then use
user_authto elevate the guest touserrole
Unknown users appear in logs:
telegram: unknown user ignored userID=999999999
Examples
Read-only User
{
"name": "Viewer",
"role": "user",
"identities": [{"provider": "telegram", "id": "111111111"}],
"permissions": ["read"]
}
Power User with Custom Role
In goclaw.json:
{
"roles": {
"poweruser": {
"tools": "*",
"skills": "*",
"memory": "full",
"transcripts": "all",
"commands": true
}
}
}
In users.json:
{
"name": "PowerUser",
"role": "poweruser",
"identities": [{"provider": "telegram", "id": "222222222"}]
}
See Also
- Configuration — Full config reference
- Telegram — Telegram user setup
- WhatsApp — WhatsApp user setup
- Web UI — HTTP authentication
- Tools — Available tools
- Delegated Runs — Delegated/subagent architecture and controls