Agent Plugins
Experimentally bundle deployment Skills, MCP servers, and command hooks into startup-loaded packages.
Agent Plugins let an operator package related Skills, MCP servers, and optional command hooks together on the LibreChat filesystem. LibreChat implements the Agent Plugins 1.0.0 package format and loads each immediate child directory as one plugin at startup.
Experimental
Agent Plugins are experimental. The package format, supported components, configuration, and runtime behavior may change during the experimentation phase. Test plugins before using them in a production deployment.
Configure the Directories
# Defaults to ./plugin relative to the LibreChat project root
DEPLOYMENT_PLUGINS_DIR=./plugin
# Persistent data allocated separately for each plugin manifest name
DEPLOYMENT_PLUGIN_DATA_DIR=./data/plugins
# Optional and disabled by default; see Command Hooks below
DEPLOYMENT_PLUGIN_HOOKS=trueRelative 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.
Restart LibreChat after adding, removing, or changing a plugin.
Package Layout
Each immediate child of DEPLOYMENT_PLUGINS_DIR is one plugin package:
plugin/
analytics-tools/
plugin.json
skills/
analyze-events/
SKILL.md
scripts/
analyze.py
mcp.json
ai.librechat/
hooks/
hooks.json
scripts/
guard.shplugin.json is required. skills/, mcp.json, and ai.librechat/hooks/hooks.json are optional and fail independently, so one invalid component does not prevent another valid component in the same plugin from loading. An invalid or missing manifest rejects the complete plugin. Diagnostics are written to the LibreChat startup logs.
Manifest
The manifest must use the exact Agent Plugins 1.0.0 schema URL:
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "analytics-tools",
"version": "1.0.0",
"description": "Skills and tools for analyzing event data"
}The name is also used for the plugin's persistent data directory. It must be 1-64 characters, start and end with a lowercase letter or number, use only lowercase letters, numbers, hyphens, and periods, and cannot contain consecutive -- or .. sequences. Plugin names must be unique within the deployment.
Bundled Skills
Put each Skill in an immediate child directory under skills/, with SKILL.md at that child's root. LibreChat loads valid entries as read-only deployment Skills and applies the normal Skills capability and access rules.
The standalone DEPLOYMENT_SKILLS_DIR takes precedence over a plugin Skill with the same name. Within the plugin directory, the first package to claim a Skill name wins and later conflicts are skipped with a warning.
Bundled MCP Servers
Define optional MCP servers in mcp.json with the exact 1.0.0 schema URL:
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
"mcpServers": {
"analytics": {
"type": "stdio",
"command": "node",
"args": ["${PLUGIN_ROOT}/server.js"],
"cwd": "${PLUGIN_ROOT}",
"env": {
"PLUGIN_CACHE": "${PLUGIN_DATA}/cache"
}
}
}
}Supported transports are stdio, streamable-http, and sse. Remote HTTP transports must use HTTPS except for loopback destinations. Server names must survive LibreChat's MCP tool-name normalization unchanged and cannot use reserved JavaScript object names.
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.
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
LibreChat creates one directory at <DEPLOYMENT_PLUGIN_DATA_DIR>/<plugin-name> and exposes it to stdio components as ${PLUGIN_DATA}. Use it for plugin-owned persistent state. Do not write persistent state into ${PLUGIN_ROOT}, which should be treated as package content.
Command Hooks
Agent Plugins can run command hook handlers at Agent lifecycle boundaries. Hook execution is disabled by default. Enable it explicitly and restart LibreChat:
DEPLOYMENT_PLUGIN_HOOKS=trueWhen the variable is false or unset, LibreChat ignores hook documents and logs a startup warning; the plugin's independently valid Skills and MCP servers still load.
Trusted code only
A command hook runs an operator-installed child process on the LibreChat API host. The restricted
environment reduces accidental exposure but is not a sandbox. Enable hooks only for plugin
packages you trust at the same level as LibreChat code and toolApproval hook modules.
Declare hooks at ai.librechat/hooks/hooks.json:
{
"description": "Reject writes outside the workspace",
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/guard.sh",
"timeout": 30,
"allowedEnvVars": ["WORKSPACE_POLICY"]
}
]
}
]
}
}Execution Contract
- LibreChat starts the command from the plugin root and sends a Claude-compatible event payload as JSON on standard input.
${PLUGIN_ROOT},${PLUGIN_DATA}, and${CLAUDE_PLUGIN_ROOT}are expanded once incommandandargsand are also available to the child process.- The child environment contains only
PATH,HOME,LANG,LC_ALL, andTZwhen present, the three plugin path variables, and names explicitly listed inallowedEnvVars. - Exit code
0succeeds. JSON written to standard output can return event-appropriate decisions and bounded context; plain output is treated as additional context only forSessionStartandUserPromptSubmit. - Exit code
2blocks 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
commandWindowsor select PowerShell.
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.
Supported source events are RunStart, SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch, SubagentStart, Stop, StopFailure, PreCompact, and PostCompact. Unsupported events or declarations are skipped and reported in startup diagnostics. Only command handlers execute in this release; prompt, http, mcp_tool, and agent handlers remain unsupported.
SessionStart and handlers with once: true are deduplicated per conversation by a bounded process-local store. In a multi-replica deployment, the same once-only handler can run once on each process. An ask decision requires LibreChat's resumable human-approval flow; when that flow is unavailable, LibreChat tightens the decision to deny instead of leaving the run paused without a resume path.
Related
How is this guide?