Roles, permissions & assigned-only agents
One role per agent, wildcard permission matching, and a restricted scope enforced in the query rather than hidden in the interface.
Leodesk uses straightforward role-based access control: a role holds a set of permission strings, each agent holds one role, and every protected route checks the permission it needs. The part worth reading carefully is assigned-only visibility, because it is enforced in the database query rather than in the interface.
The roles you start with
Signing up seeds three roles and makes the person who signed up an Admin:
- Admin — holds
*, which matches every permission, including managing agents, roles, settings and billing. - Agent — holds
ticket.*andchat.*. A full support agent who can see and act on every ticket in the workspace. - Developer — holds
ticket.read,ticket.viewAllandticket.note. Can read every ticket and leave internal notes, but cannot reply to customers.
Those three cover a surprising number of teams. Build custom roles under Settings → Roles & permissions when they do not — note that custom roles are a Scale plan feature, as is the audit log.
The permission catalog
ticket.read— open and read ticketsticket.reply— send replies to customersticket.note— post internal notesticket.assign— change a ticket's assigneeticket.delete— delete ticketsticket.viewAll— see every ticket in the workspace, not only their ownchat.*— handle live chat conversationsreports.view— workspace-wide analytics; without it an agent sees only their own statisticsagents.manage— invite, edit and deactivate agentssettings.manage— workspace settings, channels, automations and SLA policies
How wildcards match
A permission check passes in one of three ways: the role holds *; the role holds the exact permission; or the role holds the group wildcard for it, so ticket.* satisfies ticket.read, ticket.reply and every other ticket. permission. Wildcards are one level deep — there is no partial matching beyond the group prefix.
The practical consequence is that ticket.* also grants ticket.viewAll. That is exactly why a restricted role has to be built up from granular permissions rather than by starting with the wildcard and trying to take one away.
When a request fails a check, the API returns a 403 naming the missing permission, so a report of "I get an error on this button" usually answers itself.
Assigned-only agents
Sometimes you want an agent — a contractor, an outsourced tier one, a brand-new hire — to work only the tickets assigned to them and see nothing else. In Leodesk that is not a separate mode or a toggle. It is the absence of one permission: omit ticket.viewAll and the role becomes assigned-only.
To build one: create a role with ticket.read, ticket.reply and ticket.note (add chat.* if they take chats), leave ticket.viewAll unticked, save, and assign it in the agent's edit dialog.
Why this holds up
The restriction is applied as a filter on the ticket query itself, not as a condition on what the interface chooses to draw. Any request from an agent without ticket.viewAll is constrained to tickets where they are the assignee — the ticket list, the unread and view counts, opening a ticket directly by its id, and every mutation: replying, noting, tagging, reassigning, resolving, deleting.
An assigned-only agent who takes a colleague's ticket URL and pastes it into their browser does not get a hidden ticket they can still act on. They get nothing, because that ticket was never in the result set. The same is true of a request made outside the interface entirely.
The filter also fails closed. If a session cannot resolve an agent id for any reason, the query is given a sentinel value that no ticket carries, so a broken session sees zero tickets rather than everyone's. The same principle governs workspace scoping: a request whose workspace cannot be resolved matches nothing, never everything.
The one thing to remember is that the seeded Agent and Developer roles both include ticket.viewAll — Agent through its ticket.* wildcard, Developer explicitly. Assigned-only is a role you deliberately create, not a default you inherit.
Three roles worth copying
Contractor
ticket.read,ticket.reply,ticket.note. Noticket.viewAll, noreports.view. They see their queue, answer it, and cannot browse the rest of your customer conversations or your team's numbers.Engineer on rotation
ticket.read,ticket.viewAll,ticket.note. They can investigate anything and leave findings on the thread, but customer-facing replies stay with support. This is the seeded Developer role.Support lead
ticket.*,chat.*,reports.view,agents.manage. Everything operational, withoutsettings.manage— so they run the desk without being able to reconfigure email channels or billing.
Beyond roles
Every workspace is isolated from every other one, and every list endpoint is workspace-scoped before permissions are even considered. Roles govern what an agent can do inside their own workspace; they are not the mechanism that stops one workspace seeing another's data.
On plan limits: the Free plan allows three agent accounts and one mailbox. Custom roles and the audit log both require Scale. If you are on Free and need a fourth agent, that is a plan change rather than a permission problem.
New to the workspace? Start with the quickstart, then set up outbound email and inbound mail.