Set up a team with RBAC

Create a team, define roles with scoped permissions, and invite members.

What you’ll build

A team with role-based access control: an Admin with full access, a Pentester who can run pentests and triage findings, and a read-only Viewer. You will list the available permissions, attach them to roles, invite a member into each role, and share an agent with the team.

Roles bundle permission IDs under a name and color. Permissions are added to a role with add_permissions; a member receives a role when invited, or later with client.teams.roles.assign_to_member.

Prerequisites

  • A Rank account that can create teams, and an API token (see Authentication).
pip install rank-sdk
export RANK_API_KEY=rk_...

Steps

  1. Create the team.

    team = client.teams.create(
        name="Red Team Alpha",
        description="Offensive security team for quarterly pentests.",
    )
  2. List the platform permissions. Every permission has an id and a name; you assign them to roles by ID.

    permissions = client.permissions.list().items
    all_ids = [p.id for p in permissions]
  3. Create roles. Give each role a name and color, then attach its permissions.

    admin = client.teams.roles.create(team.id, role_name="Admin", color="#E74C3C")
    client.teams.roles.add_permissions(team.id, admin.id, permission_ids=all_ids)
    
    pentester = client.teams.roles.create(team.id, role_name="Pentester", color="#3498DB")
    client.teams.roles.add_permissions(team.id, pentester.id, permission_ids=all_ids[:6])
    
    viewer = client.teams.roles.create(team.id, role_name="Viewer", color="#95A5A6")
    client.teams.roles.add_permissions(team.id, viewer.id, permission_ids=all_ids[:2])
  4. Invite members. Pass a role_id to assign the role on acceptance (the Administrator role cannot be granted by invitation).

    client.teams.invitations.create(team.id, email="pentester@example.com", role_id=pentester.id)
  5. See the team’s agents. List the agents available to the team — its own custom agents plus the defaults. Add a new shared agent with client.teams.agents.create(name=..., instructions=..., agent_type=...).

    team_agents = client.teams.agents.list(team.id)
    print(len(team_agents.team_agents), "custom,", len(team_agents.default_agents), "default")

Run it

Save the following as team_rbac.py, set RANK_API_KEY, then run python team_rbac.py.

"""Set up a team with role-based access control using the Rank SDK.

What this script does:
  1. Creates a team.
  2. Lists the permissions available on the platform.
  3. Creates three roles with different permission levels:
       - Admin     : every permission.
       - Pentester : run pentests and triage vulnerabilities.
       - Viewer    : read-only access.
  4. Invites a member for each role.
  5. Lists the agents available to the team (custom + default).

Roles map permission IDs to a name and color. Permissions are assigned to a
role with `add_permissions`; members receive a role when they are invited (or
later, with `client.teams.roles.assign_to_member`). A team gets its own shared
agents by creating them with `client.teams.agents.create(...)`.

Run:
    pip install rank-sdk
    export RANK_API_KEY=rk_...
    python team_rbac.py

Optional environment variables:
    RANK_TEAM_NAME  Name for the new team (default: Red Team Alpha).
"""

from __future__ import annotations

import os

import rank

TEAM_NAME = os.environ.get("RANK_TEAM_NAME", "Red Team Alpha")

# Substrings used to pick a realistic subset of permissions for each role.
# Permission tags vary by account, so we match defensively and fall back to a
# slice of the catalog when nothing matches.
PENTESTER_KEYWORDS = ("pentest", "vulnerability", "agent", "chat")
VIEWER_KEYWORDS = ("view", "read", "list", "show")


def pick_permissions(permissions: list, keywords: tuple[str, ...], fallback: int) -> list[int]:
    """Return permission IDs whose name matches any keyword, else a fallback."""
    matched = [
        p.id for p in permissions
        if any(k in (p.name or "").lower() for k in keywords)
    ]
    return matched or [p.id for p in permissions[:fallback]]


def main() -> None:
    with rank.Rank() as client:
        team = client.teams.create(
            name=TEAM_NAME,
            description="Offensive security team for quarterly pentests.",
        )
        print(f"Created team #{team.id}: {team.name}")

        permissions = client.permissions.list().items
        all_ids = [p.id for p in permissions]
        print(f"Platform exposes {len(all_ids)} permissions")

        pentester_ids = pick_permissions(permissions, PENTESTER_KEYWORDS, fallback=6)
        viewer_ids = pick_permissions(permissions, VIEWER_KEYWORDS, fallback=2)

        roles = {
            "Admin": ("#E74C3C", "Full access to every team resource.", all_ids),
            "Pentester": ("#3498DB", "Run pentests and triage findings.", pentester_ids),
            "Viewer": ("#95A5A6", "Read-only access to team resources.", viewer_ids),
        }

        created_roles = {}
        for role_name, (color, description, permission_ids) in roles.items():
            role = client.teams.roles.create(
                team.id,
                role_name=role_name,
                color=color,
                description=description,
            )
            client.teams.roles.add_permissions(
                team.id, role.id, permission_ids=permission_ids,
            )
            created_roles[role_name] = role
            print(f"  Role {role_name} (#{role.id}): {len(permission_ids)} permissions")

        invitations = [
            ("lead@example.com", created_roles["Admin"].id),
            ("pentester@example.com", created_roles["Pentester"].id),
            ("manager@example.com", created_roles["Viewer"].id),
        ]
        for email, role_id in invitations:
            try:
                client.teams.invitations.create(team.id, email=email, role_id=role_id)
                print(f"  Invited {email} (role #{role_id})")
            except rank.APIError as exc:
                print(f"  Could not invite {email}: {exc.message}")

        # Review the agents available to the team. This returns the team's own
        # custom agents plus the default agents everyone can use. Add a new
        # shared agent with client.teams.agents.create(name=..., instructions=...,
        # agent_type=..., phase_id=..., model_id=...).
        team_agents = client.teams.agents.list(team.id)
        print(f"  Team agents: {len(team_agents.team_agents)} custom, "
              f"{len(team_agents.default_agents)} default")
        for agent in team_agents.team_agents[:5]:
            print(f"    [{agent.id}] {agent.name} ({agent.agent_type})")

        print(f"\nTeam #{team.id} is ready. Manage it from the dashboard.")


if __name__ == "__main__":
    try:
        main()
    except rank.AuthenticationError:
        print("ERROR: invalid or missing API key. Set RANK_API_KEY.")
    except rank.APIError as exc:
        print(f"API error ({exc.status_code}): {exc.message}")

For the bigger picture on roles, permissions, and tiers, see Teams & tiers.