Skip to main content
LibreChat is joining ClickHouse to power the open-source Agentic Data Stack 🎉 Learn more
LibreChat

Access Control

Role feature permissions and their defaults, people picker visibility, Entra ID group sync, promoting admins, admin capabilities, and the ACL migrations for older instances.

How roles, groups, and sharing behave for users is described on the Access Control feature page. This page covers what an admin sets up.

Feature permissions

Each role holds one set of switches per permission type. You can change them in three places:

  • In LibreChat, through the Admin Settings button in the agents, prompts, MCP servers, memories, and skills panels (admins only).
  • In the Admin Panel, under Access, for any role including custom ones.
  • In the interface block of librechat.yaml. These keys seed the permissions of the built-in USER role at startup only, so they cannot express different settings per custom role.

The table lists each permission type, the interface key that seeds it, its actions, and which actions the USER role has by default.

Permission typeinterface keyActionsOn by default for USER
AGENTSagentsUSE, CREATE, SHARE, SHARE_PUBLICUSE, CREATE
PROMPTSpromptsUSE, CREATE, SHARE, SHARE_PUBLICUSE, CREATE
MCP_SERVERSmcpServersUSE, CREATE, SHARE, SHARE_PUBLIC, CONFIGURE_OBOUSE, CREATE
SKILLSskillsUSE, CREATE, SHARE, SHARE_PUBLICUSE, CREATE
REMOTE_AGENTSremoteAgentsUSE, CREATE, SHARE, SHARE_PUBLICnone
SHARED_LINKSsharedLinksCREATE, SHARE, SHARE_PUBLICCREATE, SHARE
SCHEDULESschedulesUSE, CREATEUSE, CREATE
MEMORIESmemoriesUSE, CREATE, UPDATE, READ, OPT_OUTall
BOOKMARKSbookmarksUSEUSE
MULTI_CONVOmultiConvoUSEUSE
TEMPORARY_CHATtemporaryChatUSEUSE
RUN_CODErunCodeUSEUSE
WEB_SEARCHwebSearchUSEUSE
FILE_SEARCHfileSearchUSEUSE
FILE_CITATIONSfileCitationsUSEUSE
MARKETPLACEmarketplaceUSEnone
PEOPLE_PICKERpeoplePickerVIEW_USERS, VIEW_GROUPS, VIEW_ROLESall

SHARE lets a role share with specific users, groups, or roles; SHARE_PUBLIC lets it share with everyone on the instance. CONFIGURE_OBO allows setting up On-Behalf-Of token exchange on an MCP server, which forwards users' delegated tokens to that server, so it is off by default.

People picker

The PEOPLE_PICKER actions control which kinds of principal a role can find in the share dialog's search. Hiding roles is common when sharing by role should stay an admin concern:

interface:
  peoplePicker:
    users: true
    groups: true
    roles: false

This only changes what the search shows. Existing shares with a hidden principal type keep working. See interface.peoplePicker.

Entra ID group sync

Groups from Microsoft Entra ID are synced into LibreChat when a user signs in through OpenID Connect with Entra and OPENID_REUSE_TOKENS=true. LibreChat reads the user's group memberships from Microsoft Graph at each login and stores each group with its Entra object ID, so a group that is shared with stays the same group even if it is renamed. Set up the provider with Azure / Entra ID and token reuse with OpenID Connect Token Reuse.

Promote another admin

In a single-tenant deployment, the first account registered gets the ADMIN role. Tenant-scoped deployments never promote their first user; provision tenant admins through a trusted administrative flow. To make another existing user an admin, use the Admin Panel's Users page, or set the role directly in MongoDB:

db.users.updateOne({ email: 'USER_EMAIL_ADDRESS' }, { $set: { role: 'ADMIN' } })

Have the user sign out and back in afterwards. With OpenID Connect you can also assign ADMIN from an IdP role or group with OPENID_ADMIN_ROLE; see the .env reference.

Admin capabilities

Capabilities are granted to a user, group, or role from the Admin Panel's Grants page. Users with the ADMIN role hold all of them implicitly; anyone else needs access:admin in addition to the capabilities for what they manage. Each manage: capability implies the matching read: one, including per section: manage:configs:endpoints also grants read:configs:endpoints. Someone with only section-scoped config access gets configuration responses filtered to the sections they can read; with no config read access at all, they get 403.

CapabilityAllows
access:adminSigning in to the Admin Panel
read:users, manage:usersViewing and changing user accounts
read:groups, manage:groupsViewing and changing groups and their members
read:roles, manage:rolesViewing and changing roles and their permissions
read:configs, manage:configsViewing and changing configuration; read:configs:<section> and manage:configs:<section> limit it to one top-level librechat.yaml section
assign:configs:user, assign:configs:group, assign:configs:roleAssigning configuration overrides to that kind of principal
read:agents, manage:agentsViewing and moderating every agent
read:prompts, manage:promptsViewing and moderating every prompt
read:skills, manage:skillsViewing and moderating every skill
read:sharedlinks, manage:sharedlinksViewing and moderating every shared link
manage:mcpserversManaging MCP servers instance-wide
manage:code_environmentsEnrolling and revoking deployment-owned code execution workers
read:usageViewing usage data
read:insightsViewing Insights for every agent
read:audit_logViewing, verifying, and exporting the grant audit log. It is append-only, so there is no manage: counterpart

read:assistants and manage:assistants also exist but are reserved; nothing enforces them yet.

Group membership cache

To check permissions, LibreChat looks up which groups a user belongs to and caches the result for five minutes. Group membership changes clear the affected entries right away. The user's role is not cached. Cache or lock failures fall back to the database and never block a permission check.

KeyTypeDescriptionExample
USER_PRINCIPALS_CACHE_TTL_MSnumberHow long, in milliseconds, a user's group memberships are cached. 0 disables the cache. Default: 300000 (5 minutes).USER_PRINCIPALS_CACHE_TTL_MS=300000
USER_PRINCIPALS_LOCK_TTL_MSnumberRedis deployments only. Lock lifetime in milliseconds that stops several replicas from rebuilding the same cache entry at once. 0 disables only the locking. Default: 5000.USER_PRINCIPALS_LOCK_TTL_MS=5000
USER_PRINCIPALS_LOCK_WAIT_MSnumberRedis deployments only. How long, in milliseconds, a replica waits for another one to finish building the entry. Defaults to USER_PRINCIPALS_LOCK_TTL_MS.USER_PRINCIPALS_LOCK_WAIT_MS=5000

Admin Insights

The Insights dashboard is off by default. Set ENABLE_INSIGHTS=true in .env and restart LibreChat; while it is off, the Insights routes answer 404 and the sidebar entry stays hidden.

Admins can open it as soon as it is enabled. To let others in, either grant read:insights (every agent) from the Admin Panel, or turn on View insights for specific people or groups in an agent's share dialog. Only admins can grant View insights, the person also needs access to the agent itself, and it cannot be granted to everyone. Insights shows names, email addresses, and the first message of recent conversations, so grant it accordingly.

Every Insights query is scoped to the viewer's tenant, and custom date ranges are limited to 30 days.

Migrating from pre-ACL versions

Versions before v0.8.0-rc3 used a simpler ownership model for agents and prompts. After upgrading, run the migrations so existing agents and prompts stay accessible; LibreChat warns at startup when it finds unmigrated agents. Shared links moved to the same system later, so instances that have shared links from before then should run the shared link migration too.

Start with a dry run to see what would change, then run the migration. The :batch variants process 50 records at a time, which helps on large databases.

docker compose exec api npm run migrate:agent-permissions:dry-run
docker compose exec api npm run migrate:agent-permissions
docker compose exec api npm run migrate:prompt-permissions:dry-run
docker compose exec api npm run migrate:prompt-permissions
docker compose exec api npm run migrate:shared-link-permissions:dry-run
docker compose exec api npm run migrate:shared-link-permissions
docker exec -it LibreChat-API /bin/sh -c "cd .. && npm run migrate:agent-permissions:dry-run"
docker exec -it LibreChat-API /bin/sh -c "cd .. && npm run migrate:agent-permissions"
docker exec -it LibreChat-API /bin/sh -c "cd .. && npm run migrate:prompt-permissions:dry-run"
docker exec -it LibreChat-API /bin/sh -c "cd .. && npm run migrate:prompt-permissions"
docker exec -it LibreChat-API /bin/sh -c "cd .. && npm run migrate:shared-link-permissions:dry-run"
docker exec -it LibreChat-API /bin/sh -c "cd .. && npm run migrate:shared-link-permissions"
npm run migrate:agent-permissions:dry-run
npm run migrate:agent-permissions
npm run migrate:prompt-permissions:dry-run
npm run migrate:prompt-permissions
npm run migrate:shared-link-permissions:dry-run
npm run migrate:shared-link-permissions

How is this guide?