跳转到内容

LibreChat — 自托管多模型会话与 Agent 平台

已复核

LibreChat 是一个开源、自托管的多模型聊天与 Agent 平台。它把会话 UI、用户鉴权、模型 endpoint、Agent、MCP、Skills、Artifacts 和可恢复 stream 放进同一产品。

日常类比:像一台通用遥控器——同一份按键面板(聊天 UI),后面接的电视可以是索尼、三星、海信。你按”换台”,遥控器内部翻译成各家厂商的红外协议,但你不需要知道。

自托管意味着你控制应用、账号和会话存储,不等于 prompt 自动留在内网:选择 OpenAI、Anthropic 或外部 MCP/tool 时,相应数据仍会发给配置的上游。只有模型、工具和存储也全部自托管,才能进一步讨论完整的数据驻留。

固定源码版本是 v0.8.7,仓库同时包含 React client、Node API、共享 packages、MongoDB 数据层和可选 Redis stream 后端。它不是一个浏览器皮肤,而是 conversation-first 的完整应用。

不理解 LibreChat 的设计,下面这些事都没法解释:

  • 为什么 conversation 仍是根对象,即使产品已经加入 Agent、MCP 和 Skills
  • 为什么可恢复 stream 要把持久 job state、pub/sub 和不可序列化 runtime state 分开
  • 为什么 Agent 的工具审批不能只活在一次 HTTP 连接里
  • 为什么自托管应用、外部模型调用和真正的数据驻留是三个不同问题
  • 为什么单机 InMemory 与多副本 Redis 可以共享上层 stream 合同,但运维保证不同

LibreChat 的工程主链可以从三个边界看:

  1. Conversation-first 产品边界:controller 接收会话请求,endpoint/Agent 层组装模型、工具、MCP 和 Skills,最终事件归约回消息 UI。Agent 是可保存和共享的产品对象,但会话仍承载用户交互与历史。

  2. 可恢复 StreamGenerationJobManagerjobStoreeventTransport 和本机 runtimeState 分开。前两者可以从 InMemory 换到 Redis;abort controller、promise 等不可序列化对象留在当前进程。重连时用 streamId 读取持久内容并重新订阅事件。

  3. Agent 能力进入产品治理:MCP 与 Skills 不只是 SDK 连接,还要进入 Agent 定义、用户可见范围、凭证、工具批准、resume state 和前端配置。固定源码中的 approval lifecycle 会把 job 从 running 迁到 requires_action,匹配 action ID 后才恢复。

案例 1:docker compose 起全栈,UI 里切换 provider

Section titled “案例 1:docker compose 起全栈,UI 里切换 provider”

完整命令清单(约 3 分钟拉镜像 + 启动):

Terminal window
git clone --depth 1 https://github.com/danny-avila/LibreChat.git
cd LibreChat
cp .env.example .env # 编辑填 OPENAI_API_KEY 和 ANTHROPIC_API_KEY
cp librechat.example.yaml librechat.yaml
docker compose up -d # 起 mongo + meilisearch + librechat 三个容器
docker compose ps
open http://localhost:3080

这是固定 README/仓库结构对应的最小启动形态,不是本文已执行的部署记录。真实部署前应重新核对 .env、Compose services、注册策略、provider 凭证和数据出网范围。

api/server/controllers/agents/
→ packages/api/src/agents/
→ GenerationJobManager.createJob(streamId, ...)
→ jobStore.appendChunk(...)
→ eventTransport.emitChunk(...)
→ reconnect: getResumeState(streamId) + subscribe(...)

这条链解释了为什么断开浏览器不必等于取消 generation。jobStore 是持久内容边界,eventTransport 是投递边界;两者都必须使用相同 tenant/user 身份约束。

案例 3:浏览器刷新看 resumable SSE

Section titled “案例 3:浏览器刷新看 resumable SSE”

让 Anthropic 写一段 500 字回答,写到一半时按浏览器刷新。新页面打开后,前端会带 streamId 重新连 /chat/stream/:id,后端把已生成 chunks 从 jobStore 重放一遍,然后把后续的实时 chunks 续上——你看到回答从开头出现,到刷新前的位置时速度变慢(实时 token),整段不丢

要让这一切工作,SSE 入口必须设三个 header:Content-Type: text/event-streamCache-Control: no-cache, no-transformX-Accel-Buffering: no(专门告诉 Nginx 别缓冲)。少一个都会导致 chunk 在中间某层被攒起来,体验直接退回到”等几秒一卡顿”。

如果切到 Redis store/transport,新副本可以重建最小 runtime 并继续订阅;这只是代码合同。本文没有启动 Redis 或执行 cross-replica 测试,不能据此声称你的部署已经具备无损横向扩容。

  1. 自托管不等于不出网:provider、MCP server、搜索和 Code Interpreter 都可能成为外部数据边界。
  2. 把 SSE 连接当任务所有者:连接断开与 generation 生命周期应分离,否则刷新页面就会误取消任务或丢失结果。
  3. 只持久化文本 chunk:HITL、tool step、usage、pending steer 和审批状态也要进入 resume contract。
  4. 跨副本只换 Redis 地址:真正多副本还要验证 tenant 隔离、事件顺序、reconnect、abort 和 stale job 清理。
  5. 忽略许可 metadata 冲突:固定提交的 LICENSE 是 MIT 文本,但 package.jsonISC;使用前应按发布工件和维护者说明进一步核对,而不是只抄一个字段。

适用

  • 团队需要统一的多模型会话入口,并能明确区分本地存储与 provider 出网数据
  • 想给业务系统暴露 OpenAI 兼容的 /v1/chat/completions endpoint,用 LibreChat 做网关 + logging + quota(业务侧 SDK 改 baseURL 就能接入)
  • 接团队私有的 MCP server(如内部数据库、Slack、GitHub)让 agent 调用
  • 需要”浏览器刷新不丢消息”的可恢复流式输出
  • 愿意根据并发和恢复目标验证单机或 Redis/Mongo 多副本部署

不适用

  • 个人 BYO key 重 UI 美学 → 用 Lobe Chat(前端做得最漂亮,后端最薄)
  • 主要跑 Ollama 本地模型 → 用 Open WebUI(Ollama 团队主推,本地模型一等公民)
  • PM / 设计师不写代码做 LLM 应用 + RAG → 用 dify(visual workflow 平台派,重 10 倍但定位是”做应用”而非”做 chat”)
  • 极简部署 + Vercel 一键 → 用 NextChat(无后端、零运维)
  • 真正的多租户 SaaS(给 100 个企业用)→ LibreChat 的 tenantId 校验是 row-level 不是物理隔离,需自己加额外保护
  • 本文绑定 danny-avila/LibreChat@20cd00c...,提交日期为 2026-07-16,根 package 版本为 v0.8.7
  • 固定仓库包含 conversation、Agent、MCP、Skills、stream、HITL、Helm 和 OTel 等产品面。
  • GenerationJobManager 支持 InMemory/Redis 两套 store 与 transport,但 Redis 集成测试需要显式环境。
  • LICENSEpackage.json 的许可证字段不一致,本文不替代法律核验。
  • 本文未运行 Compose、provider、Redis 或浏览器重连实验,运行状态保持 UNVERIFIED
  1. Conversation-first 也能吸收 Agent 能力——关键是把工具、审批和 resume state 映射回稳定消息体验。
  2. 资源所有权要和 pub/sub 解耦——jobStoreeventTransportruntimeState 分别解决事实、投递和本机控制。
  3. MCP 接入是治理问题,不只是连接问题——凭证、用户范围、审批和重连都必须进入产品合同。
  4. 自托管是一组可审计边界——应用在哪里运行,数据发给谁,不能用一句”私有化”代替。
  1. LibreChat 和 MongoDB 都在内网,但选择 Anthropic endpoint。能否声称 prompt 不出公司?
  2. 浏览器断线后连到另一副本,为什么只保存 runtimeState 不够?
  3. 两个审批请求先后出现,旧标签页提交了第一个 action ID。服务端应直接恢复最新任务吗?

检查点:

  1. 不能。模型请求仍会进入外部 provider,需单独审计 payload 和服务条款。
  2. runtimeState 含不可序列化本机对象;跨副本至少需要共享 job state、事件和身份边界。
  3. 不应。必须核对 pending action ID/状态,拒绝 stale decision,防止批准错工具调用。
  • LibreChat GitHub 主仓 —— README / 配置示例 / 部署文档
  • 固定源码:danny-avila/LibreChat —— 本文绑定提交 20cd00c492a84cbc240a208eef4eaa8ba54a694a
  • LibreChat 官方文档 —— self-host 教程 + librechat.yaml 配置参考
  • MCP 协议规范 —— 想理解 plugin 抽象层就要读这份
  • Anthropic Vertex AI deployment 指南 —— 解释 LibreChat 为什么要在 anthropic/llm.ts 里搞 Vertex 双路径
  • dify —— 平台派对照组:visual workflow + 多租户 + plugin daemon RPC,定位”做应用”而非”做 chat”
  • continue —— IDE 派对照组:编辑器内嵌 + 本地 + 远端模型混合
  • claude-code —— Anthropic 官方 CLI agent,与 LibreChat 都重度依赖 MCP 但形态完全不同
  • dify —— 同 Season AI 应用范式三角的”平台派”,与 LibreChat 的”通用 chat 派”形成对照
  • continue —— 同三角的”IDE 派”,三家心智模型互相参照才能看清解空间
  • mcp-ts-sdk —— LibreChat plugin 生态的协议底座,由 Anthropic 维护
  • langchain —— LibreChat 的 agent 子模块(@librechat/agents)封装了 LangGraph
  • express —— LibreChat 后端框架,中间件链式架构是它的工程范式
  • mongodb —— LibreChat 的对话存储,messages / convos / agents 都在这里
  • react —— LibreChat 前端,ChatView / Endpoints / Agents 组件树跑在 React 19
  • redis —— 多副本部署时 SSE 走 Redis Stream + Pub/Sub,单进程默认 InMemory
  • meilisearch —— LibreChat 的全文搜索引擎,对话历史中文分词友好
  • claude-code —— Anthropic 官方 CLI,同样深度依赖 MCP 协议但形态完全不同

(暂无反向链接)