* ✨ feat: Custom Request Headers For Langfuse Self-hosted Langfuse behind an authenticating proxy or gateway could not be reached: every outbound Langfuse request hardcoded `Authorization` and nothing else. Adds `langfuse.headers`, mirroring `endpoints.custom` headers, and applies it to all four request surfaces — trace/media export (via the agents run config), feedback scores, central project-identity lookup, and admin credential verification. Values resolve through the same pipeline as endpoint headers, so `${ENV_VAR}` interpolation and header-safe encoding come along. `extractEnvVariable` continues to refuse infrastructure secrets, so a config cannot exfiltrate `MONGO_URI` through a header. A header whose variable is unset is dropped with a one-time warning rather than sent as a literal `${...}`, which a gateway would read as a wrong credential instead of a missing one. Headers merge beneath LibreChat's own `Authorization` on the REST surfaces, matching `mergeHeaders`, so a custom header can never displace the Langfuse credential. These are deployment-level and documented as such: trace export batches spans from every user through a single exporter, so unlike endpoint headers they cannot carry per-user placeholders. The central project-id cache key now includes the headers, so the header-less module warm-up cannot record a proxy rejection against the entry the request path later reads. * 🔒 fix: Keep Langfuse Headers Out Of Stored Overrides The generic admin config API accepts any field path inside an allowed section, so `langfuse.headers` could be written through it. Unlike `langfuse.secretKey`, headers are a map rather than one scalar path, so the config secret registry cannot encrypt them at rest or mask them on read — an admin-written map would sit in Mongo in plaintext and come back in plaintext, widening exposure of what are gateway credentials. Rejects them on both the dotted-patch and object-upsert routes, the same way process-backed MCP servers are held to librechat.yaml. This is what makes "deployment-level" true rather than merely documented. * 🐛 fix: Wire Config Middleware And Header Collisions For Langfuse Two codex review findings. P1 — `api/server/routes/admin/langfuse.js` never mounted `configMiddleware`, so `req.config` was undefined in production and credential verification silently ran without the deployment's proxy headers: exactly the deployments this feature targets could not save a connection. The handler unit tests injected `config` into their mock requests, so they stayed green. Mounts the middleware after the access checks (unauthorized callers still short-circuit first) and adds route-level tests that assert the handler actually receives a resolved config — the composition root, not the component. P2 — spreading custom headers under `Authorization` only replaced an exact-case collision. A configured `authorization` survived alongside the managed `Authorization` and fetch appends rather than replaces, sending both credentials in one combined value. All four request sites now use `mergeHeaders`, which already merges case-insensitively with the override winning; tests cover the lower- and upper-case variants. * 🔒 fix: Mask Langfuse Headers On Read And Harden Value Handling Three codex round-2 findings. P1 — the write guard blocked storing `langfuse.headers` in Mongo but did nothing for the read path: `GET /api/admin/config/base` serves the resolved AppConfig through `redactConfigSecrets`, which only knows registered scalar secrets, so a yaml-configured gateway credential was returned in full to any admin with Langfuse read access. Adds a secret-map registry that masks values while keeping key names, so an admin can still see which headers a deployment sets. Masking is safe precisely because these are yaml-only — a masked read cannot be round-tripped back over the real values. A malformed non-object value at that path is dropped rather than serialized. P2 — `mergeHeaders` indexes one spelling per lowercase name, so a config holding both `authorization` and `AUTHORIZATION` had only one displaced; the survivor was then appended by `Headers` into a combined value. Case variants are now collapsed at resolution, before any consumer sees them. P2 — `resolveHeaders` encodes only values it substitutes a user field into, and no user is supplied here, so a literal or interpolated character above U+00FF reached `Headers` unencoded and threw. Final values now go through `encodeHeaderValue`; Latin-1 still passes verbatim. * 🔒 fix: Keep Langfuse Header Credentials Out Of Logs And Validate Names Three codex round-3 findings, plus a documented boundary for the fourth. P1 — `loadCustomConfig` logs the parsed config at startup (`printConfig` defaults true), so a literal gateway credential in `langfuse.headers` was copied into application logs on every boot, undoing the masking the admin read path had just gained. The printed copy now goes through `redactConfigSecretMaps`, reusing the same registry. Scoped to map-valued secrets so scalar-secret log behavior is unchanged; the live config keeps its real values. P2 — a nonempty but invalid field name (` X-Token`, `X Proxy Token`) passed the emptiness check and then threw in the `Headers` constructor, which would break export, verification, lookup, and feedback for the whole deployment rather than that one header. Names are trimmed and validated against the RFC 7230 token grammar, and dropped with a warning otherwise. P2 — unresolved `${VAR}` detection tested the *resolved* value, so a credential legitimately containing `${...}` was mistaken for a failed substitution and dropped. Detection now inspects the configured text and checks the referenced variables directly, which also drops references to denylisted infrastructure secrets instead of forwarding them verbatim. The fourth (fanout gateway forwards only `Authorization`, so a tenant Langfuse behind its own proxy is not covered) is a real limitation in a separate component. Documented on the schema field and in the example config rather than left implied. * 🔒 fix: Scope Langfuse Headers To Configured Origins Three codex round-4 findings. P1 — one header map was attached to every destination a run resolves to. Under fanout that means a credential meant for an internal gateway was also sent to the central destination, typically Langfuse Cloud: an unrelated third-party origin. Headers are now attached only when the destination's origin is one the deployment explicitly configured (a self-hosted base URL, the fanout collector, or a tenant destination set by env). The built-in `*.cloud.langfuse.com` defaults are excluded precisely because nobody pointed at them. For trace export this also means attaching after the export branch settles on a `baseUrl` rather than before, since which destination wins depends on the branch. P2 — `encodeHeaderValue` only encodes above U+00FF, so a newline, CR, or NUL passed through and threw in `Headers`, breaking every request rather than the one header. Values are trimmed (the common trailing-newline case) then validated against the legal field-value bytes; an embedded CRLF is a request-splitting attempt and is dropped, not stripped. P2 — the write guard matched only the exact `headers` property, so `{ langfuse: { "headers.X-Token": "..." } }` and root-level dotted variants slipped through into the Mixed overrides document, where the nested-map redactor never walks them and a later read returns them in plaintext. All dotted spellings are now rejected. * 🔒 fix: Bind Langfuse Headers To One Configured Origin Four codex round-5 findings. P1 — the round-4 allowlist still authorized every configured origin, so a deployment with both a collector and an explicit central host sent the same credential to both. `langfuse.headers` is one map with no way to say which endpoint it authenticates to, so it is only unambiguous when the deployment configures exactly one Langfuse origin. Iterating on which origins to guess was the wrong axis; headers are now sent only when there is a single configured origin and the destination is it, with a warning when several make the intent unresolvable. That covers the self-hosted case this feature exists for; multi-destination deployments need per-destination headers the schema cannot yet express. P1 — `fetch` defaults to following redirects, and Node strips `Authorization` across origins but keeps arbitrary headers, so a redirect off an allowed origin would hand the gateway credential to a host that passed no check. Requests carrying custom headers now refuse redirects; requests without them keep the default, so nothing changes for existing deployments. P2 — `extractEnvVariable`'s whole-string branch is anchored and greedy, so `${CLIENT_ID}:${CLIENT_SECRET}` parsed as one variable name and the raw template was sent as the credential. References are expanded here now, so only literal values reach that path. P2 — a valid token name is not necessarily usable: `Transfer-Encoding` makes `fetch` throw and a fixed `Content-Length` misdescribes the body of every other request sharing the map. Request-framing names are dropped. * 🐛 fix: Expand Langfuse Header References Exactly Once Codex round 6 (P2). After expanding `${VAR}` references myself I still handed the result to `resolveHeaders`, which runs `extractEnvVariable` over it again — so a credential containing `${PATH}`, or any other name that happens to be set, was silently rewritten on export, verification, lookup, and feedback. The round-3 test only used an *unset* embedded name, which the second pass leaves alone, so it could not catch this. Resolution no longer round-trips through `resolveHeaders`. The only part still wanted from it was stripping `{{...}}` user placeholders, which is now applied directly; expansion, encoding, and validation were already local. Adds a test whose embedded variable is set, which fails against the previous pipeline. * 🐛 fix: Process Langfuse Header Templates Before Substitution Codex round 7 (P2), the mirror of round 6. Having stopped re-expanding the resolved credential, the placeholder strip was still running over it: a token containing `{{LIBRECHAT_USER_ID}}` had that span deleted and `abc{{...}}ghi` went out as `abcghi`. Establishes the invariant the last two rounds were circling. Every template operation — placeholder strip, unresolved-reference check, expansion — now runs on the operator's configured text, and the credential is substituted last and never touched again. Gateway credentials are arbitrary strings, so none of their bytes are syntax. Also moves the unresolved-reference check after the strip, so it no longer reports a variable inside a `{{...}}` span that the strip removes. |
||
|---|---|---|
| .claude/skills | ||
| .devcontainer | ||
| .github | ||
| .husky | ||
| .vscode | ||
| api | ||
| client | ||
| config | ||
| e2e | ||
| helm | ||
| otel/langfuse-fanout | ||
| packages | ||
| redis-config | ||
| scripts | ||
| search | ||
| skill | ||
| src/tests | ||
| utils | ||
| .dockerignore | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| .nvmrc | ||
| .prettierrc | ||
| AGENTS.md | ||
| bun.lock | ||
| CLAUDE.md | ||
| CONTEXT.md | ||
| deploy-compose.langfuse-fanout.yml | ||
| deploy-compose.yml | ||
| docker-compose.langfuse-fanout.yml | ||
| docker-compose.override.yml.example | ||
| docker-compose.yml | ||
| Dockerfile | ||
| Dockerfile.multi | ||
| eslint.config.mjs | ||
| librechat.example.yaml | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| rag.yml | ||
| README.md | ||
| README.zh.md | ||
| tool-intent-spec.md | ||
| turbo.json | ||
LibreChat
English · 中文
🚀 What's New in v0.8.8-rc1
- Agent run control: Interrupt or steer an Agent mid-run, queue follow-up messages, and reclaim, edit, or escalate pending steers.
- Human-in-the-loop Agents: Agents stream question progress, ask up to four related questions in one form, pause for input or tool approval, and resume.
- Unified Agent Builder: A redesigned Tools marketplace brings together Skills, MCP, Code Interpreter, orchestration, Programmatic Tool Calling, model-spec controls, and per-tool background and intent settings.
- Readable Agent activity: Generated activity-group headers, parent phase summaries, and live tool intent labels make long reasoning and tool runs easier to scan.
- Code Interpreter workflows: Code and shell tools can run in the background, sandbox images return as viewable artifacts, and highly experimental stateful sessions can reuse prewarmed conversation workspaces.
- Agent extensibility: Experimental Agent Plugins can bundle deployment Skills, MCP servers, and opt-in command hooks, while explicit subagents initialize only when selected.
- Memory, context, and identity: Agents can manage memory with optional per-agent isolation, expose support contacts safely, and show a more faithful Context Usage gauge.
- Sharing and files: Shared conversations show a badge and update at a stable URL, while signed-in viewers can continue them as personal copies.
- Artifact workflows: Open previews fullscreen, work with PowerPoint
.potxtemplates across upload, search, and code execution, upload shell scripts across common MIME variants, export Mermaid diagrams as SVG or PNG, and download original Office files from the artifact panel. - Models and reasoning: Added GPT-5.6 with Responses API reasoning controls, Claude Opus 5 and Sonnet 5, Gemini 3.7 and 3.6 Flash, and Gemini 3.5 Flash-Lite.
- Langfuse observability: Configure encrypted Langfuse connections in-app, let authorized admins open sampled sessions directly, optionally fan out traces by tenant, and suppress central export per run.
- Administration and security: Delegate config sections, encrypt registered secrets, enforce SSRF checks for speech, OCR, and web tools, and generate unique temporary credentials when secrets are blank.
- Messages and navigation: Right-aligned user turns, unified multi-part editing, full-message copy, a dock-style message rail, virtualized search, smooth streaming, and faster Agent startup.
- Streaming and tool reliability: Adaptive provider smoothing, Redis delta batching, dynamic MCP tool refresh, parsed MCP response media types, runtime OAuth recovery, and Agent stream circuit breakers improve long-running workflows.
- Deployment and reliability: Added configurable HTTP timeouts, Amazon DocumentDB 5.0+ support, low-noise Redis and browser observability, and a rolling-upgrade-safe generation protocol.
Read the full v0.8.8-rc1 changelog.
✨ Features
-
🖥️ UI & Experience inspired by ChatGPT with enhanced design and features
-
🤖 AI Model Selection:
- Anthropic (Claude), AWS Bedrock, OpenAI, Azure OpenAI, Google, Vertex AI, OpenAI Responses API (incl. Azure)
- Custom Endpoints: Use any OpenAI-compatible API with LibreChat, no proxy required
- Compatible with Local & Remote AI Providers:
- Ollama, groq, Cohere, Mistral AI, Apple MLX, koboldcpp, together.ai,
- OpenRouter, Helicone, Perplexity, ShuttleAI, Deepseek, Qwen, and more
-
- Secure, Sandboxed Execution in Python, Node.js (JS/TS), Go, C/C++, Java, PHP, Rust, and Fortran
- Seamless File Handling: Upload, process, and download files directly
- No Privacy Concerns: Fully isolated and secure execution
- Open-Source & Self-Hostable: powered by ClickHouse/code-interpreter
-
🔦 Agents & Tools Integration:
- LibreChat Agents:
- No-Code Custom Assistants: Build specialized, AI-driven helpers
- Agent Marketplace: Discover and deploy community-built agents
- Collaborative Sharing: Share agents with specific users and groups
- Flexible & Extensible: Use MCP Servers, tools, file search, code execution, and more
- Skills: Create reusable
SKILL.mdinstruction bundles for manual, automatic, or always-on agent workflows - Agent Plugins: Experimentally bundle deployment Skills and MCP servers into startup-loaded packages
- Subagents: Delegate focused work to isolated child agent runs with their own context windows
- Compatible with Custom Endpoints, OpenAI, Azure, Anthropic, AWS Bedrock, Google, Vertex AI, Responses API, and more
- Model Context Protocol (MCP) Support for Tools
- LibreChat Agents:
-
🔍 Web Search:
- Search the internet and retrieve relevant information to enhance your AI context
- Combines search providers, content scrapers, and result rerankers for optimal results
- Customizable Jina Reranking: Configure custom Jina API URLs for reranking services
- Learn More →
-
🪄 Generative UI with Code Artifacts:
- Code Artifacts create React, HTML, and Mermaid content directly in chat
- Open previews fullscreen and export Mermaid diagrams as SVG or PNG
-
🎨 Image Generation & Editing
- Text-to-image and image-to-image with GPT-Image-1
- Text-to-image with DALL-E (3/2), Stable Diffusion, Flux, or any MCP server
- Produce stunning visuals from prompts or refine existing images with a single instruction
-
💾 Presets & Context Management:
- Create, Save, & Share Custom Presets
- Switch between AI Endpoints and Presets mid-chat
- Edit, Resubmit, and Continue Messages with Conversation branching
- Create and share prompts with specific users and groups
- Fork Messages & Conversations for Advanced Context control
-
💬 Multimodal & File Interactions:
- Upload and analyze images with Claude 3, GPT-4.5, GPT-4o, o1, Llama-Vision, and Gemini 📸
- Chat with Files using Custom Endpoints, OpenAI, Azure, Anthropic, AWS Bedrock, & Google 🗃️
-
🌎 Multilingual UI:
- English, 中文 (简体), 中文 (繁體), العربية, Deutsch, Español, Français, Italiano
- Polski, Português (PT), Português (BR), Русский, 日本語, Svenska, 한국어, Tiếng Việt
- Türkçe, Nederlands, עברית, Català, Čeština, Dansk, Eesti, فارسی
- Suomi, Magyar, Հայերեն, Bahasa Indonesia, ქართული, Latviešu, ไทย, ئۇيغۇرچە
-
🧠 Reasoning UI:
- Dynamic Reasoning UI for Chain-of-Thought/Reasoning AI models like DeepSeek-R1
-
🎨 Customizable Interface:
- Customizable Dropdown & Interface that adapts to both power users and newcomers
-
- Never lose a response: AI responses automatically reconnect and resume if your connection drops
- Multi-Tab & Multi-Device Sync: Open the same chat in multiple tabs or pick up on another device
- Production-Ready: Works from single-server setups to horizontally scaled deployments with Redis
-
🗣️ Speech & Audio:
- Chat hands-free with Speech-to-Text and Text-to-Speech
- Automatically send and play Audio
- Supports OpenAI, Azure OpenAI, and Elevenlabs
-
📥 Import & Export Conversations:
- Import Conversations from LibreChat, ChatGPT, Chatbot UI
- Export conversations as screenshots, markdown, text, json
-
🔍 Search & Discovery:
- Search all messages/conversations
-
👥 Multi-User & Secure Access:
- Multi-User, Secure Authentication with OAuth2, LDAP, & Email Login Support
- Built-in Moderation, and Token spend tools
-
🎛️ Admin Panel:
- Browser-based UI to manage users, groups, roles, and configuration overrides
- Edit settings and per-role/group permissions live, without redeploying
- Bundled with the Docker Compose stacks for one-command setup
-
⚙️ Configuration & Deployment:
- Configure Proxy, Reverse Proxy, Docker, & many Deployment options
- Use S3 with CloudFront for stable media links, edge delivery, signed cookies, and secured downloads
- Use completely local or deploy on the cloud
-
📖 Open-Source & Community:
- Completely Open-Source & Built in Public
- Community-driven development, support, and feedback
For a thorough review of our features, see our docs here 📚
🪶 All-In-One AI Conversations with LibreChat
LibreChat is a self-hosted AI chat platform that unifies all major AI providers in a single, privacy-focused interface.
Beyond chat, LibreChat provides AI Agents, Model Context Protocol (MCP) support, Artifacts, Code Interpreter, custom actions, conversation search, and enterprise-ready multi-user authentication.
Open source, actively developed, and built for anyone who values control over their AI infrastructure.
🌐 Resources
GitHub Repo:
- RAG API: github.com/danny-avila/rag_api
- Website: github.com/LibreChat-AI/librechat.ai
Other:
- Website: librechat.ai
- Documentation: librechat.ai/docs
- Blog: librechat.ai/blog
📝 Changelog
Keep up with the latest updates by visiting the releases page and notes:
⚠️ Please consult the changelog for breaking changes before updating.
⭐ Star History
✨ Contributions
Contributions, suggestions, bug reports and fixes are welcome!
For new features, components, or extensions, please open an issue and discuss before sending a PR.
If you'd like to help translate LibreChat into your language, we'd love your contribution! Improving our translations not only makes LibreChat more accessible to users around the world but also enhances the overall user experience. Please check out our Translation Guide.
💖 This project exists in its current state thanks to all the people who contribute
🎉 Special Thanks
We thank Locize for their translation management tools that support multiple languages in LibreChat.