Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 15 additions & 17 deletions content/docs/features/access_control.mdx
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
---
title: Access Control
icon: ShieldCheck
description: LibreChat's granular authorization system - control who can use, share, edit, and manage agents, prompts, MCP servers, and other resources at the user, group, role, and instance level.
description: "LibreChat's granular authorization system: control who can use, share, edit, and manage agents, prompts, MCP servers, and other resources at the user, group, role, and instance level."
---

# Granular Access Control

LibreChat ships with a full authorization system on top of authentication. Access is not "all-or-nothing": every shareable entity in the app (agents, prompts, MCP servers, remote agents, files, conversations) has its own Access Control List (ACL), and every feature can be independently enabled or restricted per **user**, **group**, **role**, or **publicly**.
LibreChat ships with a full authorization system on top of authentication. Access is not "all-or-nothing": every shareable entity in the app (agents, prompts, MCP servers, remote agents, skills, code environments, shared links) has its own Access Control List (ACL), and every feature can be independently enabled or restricted per **user**, **group**, **role**, or **publicly**.

This page explains how the pieces fit together so you can model permissions to match your organization, from a small team where everyone shares freely, to an enterprise deployment with sync'd Entra ID groups, custom roles, and delegated admins.

<Callout type="info" title="Admin Panel">
A dedicated [**LibreChat Admin Panel**](/docs/features/admin_panel) is the upcoming UI for
managing users, groups, roles, custom permission profiles, and system-wide grants introduced in
[v0.8.5](/changelog/v0.8.5). This page documents the underlying model, which is available today in
LibreChat itself.
</Callout>

## The Access Model at a Glance

LibreChat's authorization has three independent layers that compose together:
Expand Down Expand Up @@ -106,12 +99,12 @@ Resource ACLs currently apply to:
- **MCP Servers** (`mcpServer`)
- **Skills** (`skill`), see [Skills](/docs/features/skills)
- **Remote Agents** (`remoteAgent`), for the [Agents API](/docs/features/agents_api)
- **Files** (`file`), typically inherited from the resource that uses them
- **Projects** (`project`), supports inheritance so resources shared to a project automatically inherit ACLs
- **Code Environments** (`codeEnvironment`), for deployment-owned code workers; see [Code Interpreter](/docs/features/code_interpreter)
- **Shared Links** (`sharedLink`), see [Shareable Links](/docs/features/shareable_links)

### Access Roles (Permission Presets)

Rather than exposing raw permission bits to end users, sharing uses three named roles per resource type:
Rather than exposing raw permission bits to end users, sharing uses three named roles per resource type (shared links have only Viewer and Owner):

| Role | Permission bits | What the grantee can do |
| ---------- | ----------------------------------------------- | ------------------------------------------------------------------- |
Expand All @@ -121,6 +114,8 @@ Rather than exposing raw permission bits to end users, sharing uses three named

Under the hood, permissions are stored as a bitmask (`permBits`) against each (resource, principal) pair; supersets are handled automatically, so granting Editor implies Viewer.

A fifth bit, `VIEW_INSIGHTS` (`0b10000`), applies to agents only. It lets a principal that also holds `VIEW` see that agent's [Insights](/docs/features/insights). It is not part of the Viewer, Editor, or Owner presets: only administrators can grant it, through the **View insights** toggle in an agent's share dialog, and it cannot be given to the public principal.

### Granting Access from the UI

1. Open the resource (agent builder, prompt form, MCP server settings, etc.)
Expand All @@ -145,10 +140,6 @@ Under the hood, permissions are stored as a bitmask (`permBits`) against each (r
- **Owners** have the same UI as the original author, and can delete and re-share freely.
- **The original author** always retains full control regardless of ACL state, and admins can manage any resource on the instance.

### Project Inheritance

Permissions can be inherited from a parent **project**. When an ACL entry is inherited, the `inheritedFrom` link points back to the source. This is what powers the "Global" project in LibreChat, where a resource added to the global project becomes available to all users without needing an entry per principal.

## Layer 3: System Grants (Admin Capabilities)

System grants are a separate grant table used for **admin-level capabilities**, answering questions like _"Can this user access the admin panel?"_ or _"Can this group manage MCP servers globally?"_. They are always scoped to a principal (user, group, or role) and a capability string.
Expand All @@ -167,13 +158,20 @@ The canonical capabilities include:
| `read:usage` | View platform usage and telemetry |
| `read:agents` / `manage:agents` | View / moderate every agent on the instance |
| `read:prompts` / `manage:prompts` | View / moderate every prompt |
| `read:skills` / `manage:skills` | View / moderate every skill |
| `read:sharedlinks` / `manage:sharedlinks` | View / moderate every shared link |
| `manage:mcpservers` | Manage MCP servers globally |
| `manage:code_environments` | Enroll and revoke deployment-owned code workers |
| `read:insights` | View [Insights](/docs/features/insights) for every agent |
| `read:audit_log` | List, view, and export the grant audit log (read-only; there is no manage counterpart) |

Manage capabilities imply their corresponding read capability (e.g. holding `manage:users` automatically grants `read:users`). This also applies to configuration sections: `manage:configs:endpoints` satisfies `read:configs:endpoints`. Users with only section-scoped config access receive admin configuration responses filtered to the sections they can read; users with no config-read grant receive `403`.

`read:assistants` and `manage:assistants` also exist but are reserved: no middleware enforces them yet.

A `SystemRoles.ADMIN` user implicitly holds all capabilities; grants let you **delegate** a subset of admin powers to non-admin principals without making them full admins. Access to the admin UI itself still requires `access:admin`.

System grants are issued and revoked via the admin panel.
System grants are issued and revoked via the [Admin Panel](/docs/features/admin_panel).

## Principals in Depth

Expand Down
28 changes: 18 additions & 10 deletions content/docs/features/admin_panel.mdx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
---
title: Admin Panel
icon: LayoutDashboard
description: A standalone web UI for managing LibreChat users, groups, roles, configuration overrides, and system grants - without editing librechat.yaml by hand.
description: A standalone web UI for managing LibreChat users, groups, roles, configuration overrides, and system grants, without editing librechat.yaml by hand.
---

# LibreChat Admin Panel

The **LibreChat Admin Panel** is a standalone browser-based management interface for LibreChat. It connects to the same database as LibreChat itself and provides a GUI for the administrative tasks that power [granular access control](/docs/features/access_control): user and group administration, role management, configuration overrides scoped to roles or groups, and system-level capability grants.

<Callout type="info" title="Status: Preview">
The admin panel is available for testing now and is the upcoming management surface that builds on
the admin APIs introduced in [LibreChat v0.8.5](/changelog/v0.8.5). Source, issues, and releases
The admin panel ships as the `admin-panel` service in `docker-compose.yml` and `deploy-compose.yml`
and builds on the admin APIs introduced in [LibreChat v0.8.5](/changelog/v0.8.5). Source, issues, and releases
live at
[github.com/ClickHouse/librechat-admin-panel](https://github.com/ClickHouse/librechat-admin-panel).
</Callout>
Expand All @@ -20,7 +20,7 @@ The **LibreChat Admin Panel** is a standalone browser-based management interface
The admin panel is a thin client: all data lives in LibreChat's database, and every action goes through the versioned `/api/admin/*` endpoints on the LibreChat API server. It gives administrators a single place to:

- **Manage configuration**: view and edit every LibreChat setting through a dynamic, schema-driven form. New fields added to the config schema appear automatically, no admin-panel release required.
- **Apply per-principal overrides**: scope configuration overrides to specific roles or groups, with a priority-based cascade that determines the final resolved value each user sees at login.
- **Apply per-principal overrides**: scope configuration overrides to specific roles, groups, or users, with a priority-based cascade that determines the final resolved value each user sees at login.
- **Administer users**: list, search, and view every account on the instance.
- **Manage groups**: create and delete groups, add/remove members, and use groups as first-class principals in ACLs and overrides.
- **Manage roles**: create custom roles beyond the built-in `USER` / `ADMIN`, edit their feature-permission matrix, and assign users to roles.
Expand Down Expand Up @@ -54,6 +54,12 @@ The admin API surface exposed by LibreChat is:
| `/api/admin/roles` | Custom role CRUD + permission editing + member management |
| `/api/admin/grants` | System capability grants (assign/revoke/list) |
| `/api/admin/config` | Base + per-principal configuration overrides |
| `/api/admin/skills` | GitHub skill sync: status, run, and sync credentials |
| `/api/admin/code-environments` | Pair and revoke code environment workers (`manage:code_environments`) |
| `/api/admin/langfuse` | Langfuse connection read, update, and test, plus per-conversation session links |
| `/api/admin/audit-log` | Grant audit log (`read:audit_log`) |

The audit log endpoints are `GET /` (list), `GET /export.csv` (CSV export), `GET /verify` (integrity check), and `GET /:id` (single entry). They require `access:admin` and `read:audit_log`. The log is append-only, so there is no manage capability and no write endpoint.

## Getting Started

Expand All @@ -65,7 +71,7 @@ The admin API surface exposed by LibreChat is:

### Bundled with LibreChat (recommended)

If you run LibreChat with its official [`docker-compose.yml`](https://github.com/LibreChat-AI/LibreChat/blob/main/docker-compose.yml) or [`deploy-compose.yml`](https://github.com/LibreChat-AI/LibreChat/blob/main/deploy-compose.yml), the admin panel ships as a service and starts automatically alongside LibreChat -- no separate deployment needed.
If you run LibreChat with its official [`docker-compose.yml`](https://github.com/LibreChat-AI/LibreChat/blob/main/docker-compose.yml) or [`deploy-compose.yml`](https://github.com/LibreChat-AI/LibreChat/blob/main/deploy-compose.yml), the admin panel ships as a service and starts automatically alongside LibreChat, with no separate deployment needed.

| Compose file | Admin panel URL | How it is served |
| ------------------------------ | ------------------------ | ----------------------------------------------------------------- |
Expand Down Expand Up @@ -96,7 +102,7 @@ The compose files wire the rest automatically: `API_SERVER_URL` points at the `a

### Standalone (separate deployment)

To host the admin panel on its own -- pointed at a LibreChat instance running elsewhere -- use the published image from GHCR:
To host the admin panel on its own, pointed at a LibreChat instance running elsewhere, use the published image from the LibreChat registry (`registry.librechat.ai/librechat-ai/librechat-admin-panel:latest`, the image the bundled compose files use):

```bash
# 1. Create an env file
Expand All @@ -118,7 +124,7 @@ docker run -p 3000:3000 \
--add-host=host.docker.internal:host-gateway \
-e SESSION_SECRET=replace-with-32-char-random-string \
-e VITE_API_BASE_URL=http://host.docker.internal:3080 \
ghcr.io/clickhouse/librechat-admin-panel:latest
registry.librechat.ai/librechat-ai/librechat-admin-panel:latest
```

<Callout type="warning" title="Docker Networking">
Expand Down Expand Up @@ -163,7 +169,7 @@ When the admin panel is hosted on a separate URL from LibreChat, set `ADMIN_PANE
ADMIN_PANEL_URL=https://admin.example.com/admin
```

When set, LibreChat also shows an **Admin Panel** link to administrators under **Settings -> General**. Non-admin users do not see the link.
When set, LibreChat also shows an **Admin Panel** link to administrators under **Settings > General**. Non-admin users do not see the link.

For Helm deployments, set `librechat.adminPanelUrl` in your values file. The chart renders it as `ADMIN_PANEL_URL` for LibreChat's admin OAuth flow:

Expand Down Expand Up @@ -207,7 +213,9 @@ Google admin SSO requests offline access and consent so the panel can refresh an
The panel renders the LibreChat config as a dynamic form driven by the config schema. This has two useful properties:

- **Forward-compatible**: when LibreChat ships a new config field, the panel picks it up automatically from the schema. No admin-panel upgrade or redeploy is required.
- **Layered overrides**: the base config (from `librechat.yaml`) can be shadowed by per-principal overrides scoped to a role or group. When a user logs in, overrides are resolved in priority order and merged on top of the base to produce the effective config that user sees.
- **Layered overrides**: the base config (from `librechat.yaml`) can be shadowed by per-principal overrides scoped to a role, group, or user. When a user logs in, the documents that apply merge in one fixed order: the Base profile first regardless of its priority, then ascending priority, then role before group before user, then creation order. A new profile written without a priority gets its principal type's default (role 10, group 20, user 100, Base 0), and a write that omits the priority keeps the stored one.
- **Encrypted credentials**: MCP server credentials, Azure group keys, and web search keys stored through the admin API are encrypted at rest and returned only as masked previews. A write that keeps a stored key while changing where it is sent (such as a server URL or base URL) must enter the key again.
- **Environment references**: `${ENV_VAR}` references in overrides are limited to the names `librechat.yaml` already references, the built-in endpoint credentials, and the names listed in `CONFIG_OVERRIDE_ENV_ALLOWLIST`. Any other reference is rejected on write.

<Callout type="warning" title="Process-backed MCP servers stay in YAML">
MCP servers that use `type: stdio` or process fields such as `command`, `args`, `env`, `cwd`, or `stderr` are operator-owned. Configure them only in `librechat.yaml`; the admin API rejects attempts to create or modify them, and overrides cannot replace or remove them. Remote MCP server configuration remains available through the normal override system.
Expand All @@ -226,7 +234,7 @@ This is the surface behind LibreChat's [DB-backed per-principal configuration ov
- Let a "FinanceAdmins" role manage remote MCP servers while regular users can only use them
- Scope stricter `interface` permissions to external-contractor groups

Administrators can also use the opt-in [Admin Insights](/docs/features/insights) dashboard to review tenant-scoped MongoDB activity. Set `ENABLE_INSIGHTS=true`, then grant both `access:admin` and `read:insights` to an account with the `ADMIN` role.
Administrators can also use the opt-in [Admin Insights](/docs/features/insights) dashboard to review tenant-scoped MongoDB activity. Set `ENABLE_INSIGHTS=true`; who can review which Agents is described in [Admin Insights](/docs/features/insights#access-requirements).

### Override Validation

Expand Down
13 changes: 11 additions & 2 deletions content/docs/features/agent_plugins.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ DEPLOYMENT_PLUGINS_DIR=./plugin
DEPLOYMENT_PLUGIN_DATA_DIR=./data/plugins

# Optional and disabled by default; see Command Hooks below
DEPLOYMENT_PLUGIN_HOOKS=true
# DEPLOYMENT_PLUGIN_HOOKS=true
```

Relative paths are resolved from the LibreChat project root. If the default `./plugin` directory does not exist, startup continues with no plugins. If `DEPLOYMENT_PLUGINS_DIR` is set explicitly but cannot be read, startup fails so a deployment mistake is not silently ignored.
Expand Down Expand Up @@ -96,6 +96,14 @@ Supported transports are `stdio`, `streamable-http`, and `sse`. Remote HTTP tran

For `stdio` servers, `${PLUGIN_ROOT}` and `${PLUGIN_DATA}` are expanded once in `args`, `env`, and `cwd`; both values are also added to the launched process environment. Plugin MCP configuration does not expand arbitrary variables from LibreChat's host environment. A value such as `${OPENAI_API_KEY}` remains literal through registry storage and runtime initialization. Keep credentials outside plugin files and provide them through a purpose-built authenticated service or another deployment-controlled mechanism.

LibreChat validates each `mcp.json` before registering its servers:

- `command` must be a single executable token: either a bare name such as `node` or a `./` path inside the plugin. Shell strings and absolute paths are rejected, and `${PLUGIN_ROOT}` is not expanded in `command`.
- `cwd` must start with `./`, `${PLUGIN_ROOT}`, or `${PLUGIN_DATA}`, and must resolve inside the base it names.
- `env` cannot declare `PLUGIN_ROOT` or `PLUGIN_DATA`; LibreChat sets them.
- Remote `url` values must be absolute `http` or `https` URLs without user information or a fragment, and must use `https` unless the host is a loopback address (such as `localhost` or `127.0.0.1`).
- A server entry with an unknown field is rejected and skipped. An unknown top-level field, or a `$schema` that does not match the supported `1.0.0` schema URL, disables MCP for the whole plugin.

An MCP server declared in `librechat.yaml` takes precedence over a plugin server with the same name. Duplicate plugin server names are skipped and logged.

## Persistent Plugin Data
Expand Down Expand Up @@ -148,7 +156,8 @@ Declare hooks at `ai.librechat/hooks/hooks.json`:
- The child environment contains only `PATH`, `HOME`, `LANG`, `LC_ALL`, and `TZ` when present, the three plugin path variables, and names explicitly listed in `allowedEnvVars`.
- Exit code `0` succeeds. JSON written to standard output can return event-appropriate decisions and bounded context; plain output is treated as additional context only for `SessionStart` and `UserPromptSubmit`.
- Exit code `2` blocks the applicable action or continuation and uses standard error as the reason. Other nonzero exits are logged and otherwise ignored.
- LibreChat terminates the process when the hook is aborted or times out. On POSIX hosts, commands run through Bash. Windows plugins must provide `commandWindows` or select PowerShell.
- `timeout` is in seconds, an integer from 1 to 3600.
- LibreChat terminates the process when the hook is aborted or times out. On POSIX hosts, commands run through `bash`, which must be available on the API host. On Windows hosts they run through `powershell.exe`, so plugins must provide `commandWindows` or select PowerShell. If the shell cannot start, LibreChat logs a startup warning and blocking hooks fail closed.

LibreChat translates the common Claude tool names `Bash`, `Write`, `Edit`, `Read`, and `WebSearch` and their file argument names to the corresponding LibreChat tools. A matcher written with LibreChat's native tool name keeps the native payload shape.

Expand Down
Loading
Loading