Roles & Access Control

GoClaw provides role-based access control (RBAC) to manage what users can do.

Overview

The access control system has three layers:

  1. Users — Who is allowed access (defined in users.json)
  2. Roles — What permissions a user has (defined in goclaw.json)
  3. 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"]
    }
  ]
}
FieldRequiredDescription
nameYesDisplay name
roleYesowner or user
identitiesYesHow to identify this user
credentialsNoFor password/API key auth
permissionsNoTool whitelist (non-owners only)

Identities

Identities link external accounts to GoClaw users:

ProviderID FormatExample
telegramTelegram user ID123456789
whatsappPhone number (no +)1234567890
httpUsername for web UIalice
localowner for CLIowner

Built-in Roles

GoClaw recognizes three built-in role names:

RoleDefault PermissionsDescription
ownerFull access (built-in)Has built-in defaults even if not defined in config
userMust define in configAuthenticated user with configurable permissions
guestMust define in configUnauthenticated 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.

OptionValuesDescription
tools"*" or ["tool1", "tool2"]Allowed tools
skills"*" or ["skill1"]Allowed skills
memory"full", "none"Memory file access
transcripts"all", "own", "none"Transcript search scope
commandstrue, falseSlash commands enabled
systemPromptstringCustom system prompt
systemPromptFilepathLoad 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
  }
}
OptionDefaultDescription
script-Auth script path
allowedRoles[]Roles the script can grant
rateLimit3Max attempts per minute
timeout10Script timeout (seconds)

Security rules:

  • Elevation to owner is always blocked — Even if the auth script returns owner, GoClaw refuses. Owner access requires being defined in users.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 roles config.

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

Delegated Runs and Subagent Access

Yes — subagent tooling is owner-only by design.

This includes:

  • subagent_spawn
  • subagent_status
  • subagent_cancel
  • subagent_fanout

How enforcement works

Access is enforced in multiple layers:

  1. Registration gate (config):
    • Tools are only registered when tools.subagent.enabled=true.
  2. Delegated background-work gate (config):
    • Subagents and related background runs are controlled by gateway.delegatedRuns.enabled.
  3. Execution authorization (hard check):
    • Each subagent tool checks sessionCtx.User.IsOwner() at execution time.
    • Non-owner calls are rejected, even if a role/user tool allowlist includes the tool name.

This means subagent access cannot be granted to non-owner users by role config alone.

RBAC implications

  • Keep normal users on bounded/readonly tool sets (read, memory_search, etc.).
  • Treat delegated tooling as a privileged operator capability.
  • If you need non-owner async workflows, prefer narrowly scoped custom tools rather than exposing delegated subagent control.

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_auth tool if you want guests to authenticate
  • Use a system prompt that guides the agent to request credentials
  • The agent can then use user_auth to elevate the guest to user role

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