LibreChat Agents 运行时架构领域语言全解:从 Agent Run Envelope 到 Event Actor
LibreChat 仓库根目录下的 CONTEXT.md 是一份被刻意设计为“领域语言”(Domain Language)的精确词汇表:它用 25 条带版本语义的定义,描述了 LibreChat 自研 Agents 执行子系统(调度、续跑、事件驱动、子代理、账户删除栅栏等)的全部核心对象与职责边界。本文以这份词汇表为主干,逐条还原其架构含义,并对照 packages/api/src/agents/ 下的真实源码、常量与测试加以印证。读完本文,你将能够:理解 Agent 请求从「入场契约」到「终端结账」被拆成了哪些职责互斥的运行时对象;厘清普通聊天续跑、队列轮次、事件驱动子 Actor、子代理唤醒等十余种触发路径为何能共用同一套持久化与恢复语义;并且能够在源码中按名定位这些术语对应的实现文件,用它作为阅读或二次开发 Agents 模块的“架构索引”。
为什么需要一份“领域语言”词汇表
LibreChat 的 Agent 执行路径横跨多个入口协议(Chat Completions、Responses、未来的 Channel 等)、多套持久化(Mongo 为权威、Redis 负责跨副本投递)、以及第三方 Agents SDK 的 Run/Checkpoint 模型。一旦“执行对象”的边界含糊,就会出现一类典型事故:把 Express 请求对象或序列化凭据带进了异步任务、把“传输已成功”误当作“工作已完成”、在账户删除过程中放行了新的模型调用。
CONTEXT.md 的第一使命,就是用名词把职责固定下来:每个术语都同时回答三个问题——它是什么、它拥有什么、它不拥有什么。例如“Agent execution context 永远不持有 Express 请求对象,也不持有序列化凭据”“MCP runtime request body 不把用户请求数据留在共享服务定义上”“Caller Capability Projection 只是证据数据,永远不是授权”。从源码结构看,这一整套命名与 packages/api/src/agents/ 目录的模块划分几乎一一对应:envelope.ts、context.ts、run.ts、plan.ts、queuedTurns.ts、subagentThreads.ts、subagentDelivery.ts、subagentCompletionWakeup.ts、callerCapabilities.ts、steering/、remote/、triggers/ 等文件即这些术语的落点。
一、Agent Run 的执行主轴:Envelope → Context → Host → Enrollment → Plan
这一组五个术语构成了任何一次 Agent 运行都要穿越的“执行主轴”。它们的共同设计原则是:认证与协议校验之后立刻把信息降级成纯数据,运行时再按最小标识重建全部状态。
1. Agent run envelope:穿过执行缝的版本化请求契约
定义核心:在入口认证、协议校验完成之后、Agent/Provider/Tool/MCP 初始化之前创建的、可 JSON 序列化的版本化请求对象;只携带“经过校验的协议载荷 + 最小可信主体标识”,执行宿主(execution host)据此重建全部运行时状态。
源码印证:envelope.ts 是这一契约的直接实现。文件中 AGENT_RUN_ENVELOPE_VERSION = 1 定义了版本常量;AgentRunEnvelope 是判别联合(discriminated union),按协议区分为 ChatCompletionRunEnvelope 与 ResponsesRunEnvelope 两种形态(envelope.ts)。所有形态共享同一组基础字段:version、requestId、receivedAt 与 principal。其中 principal 只含 userId,可选 role、tenantId(envelope.ts)——这正是“最小可信主体标识”的字面实现。createAgentRunEnvelope() 构造器会对主体字段做非空校验,校验失败抛 AgentRunEnvelopeError。文件头注释也给出了清晰的“不变量”声明:运行时对象、Provider 客户端、回调、凭据与 Express 状态都属于执行宿主,永远不得进入 envelope。被模型消费的非公开扩展字段(临时 Agent、手动技能、时区、临时会话等)通过 AgentRunPayloadExtensions 显式声明,与公开协议载荷分离。
2. Agent execution context:仅运行时存在、无传输痕迹的会话事实
定义核心:紧邻 envelope 重建的“仅运行时”状态,包含已认证用户、应用配置、规范化请求元数据与已解析的会话事实;供初始化阶段使用,但绝不包含 Express request/response 对象或序列化凭据。
源码印证:context.ts 展示了 context 层实际处理的一类“会话事实”——从 Agent 的工具或可序列化工具定义中解析出依赖的 MCP 服务名。它通过 Constants.mcp_delimiter 识别带命名空间的工具,将工具回退到其原始 MCP 服务名,再借助 MCPManager 拉取服务指令。这正好体现了 context 的定位:它不是传输层,而是“把身份与配置翻译成初始化所需事实”的中间层。
3. Agent execution host:协议无关的执行宿主
定义核心:协议无关的模块,拥有“运行准入(admission)、断连取消、Provider 启动围栏(fencing)、终端结算”四项所有权。协议实现跑在它的回调接口之后,HTTP 适配器只负责校验与最终流渲染。
源码印证:remote/host.ts 与 triggers/host.ts 分别承载远程执行与触发执行两条 host 实现,且都位于同一 agents 命名空间下;两侧 host 的职责差异仅在于“源适配器”不同(前者接 Responses/远程调用,后者接调度、webhook、队列等异步源),而“准入—执行—结算”的骨架一致。host 模式下,HTTP 层不再直接驱动模型运行,只完成请求解析与响应渲染,这从模块组织上印证了 host 与 transport 的分离。
4. Agent execution enrollment:可恢复的“运行终身管理”对象
定义核心:为已准入运行服务的持久化、协议无关生命周期权威。它在用户与租户下于用户侧初始化之前被创建;注册后会再次检查共享的“所有者删除准入栅栏”;暴露唯一的 Provider 中止信号;围栏 Provider 精确启动;终结运行;等待所有尾随的 usage、artifact 与存储写入;最后才确认 Provider drain。临时终结失败会在尾随写入后被调和;只要精确任务未终结,就绝不确认 Provider drain。“删除全部”会持有所有者栅栏,在选取首个持久化快照前排空所有所有者运行,并在任何栅栏失效恢复后重复排空与幂等清扫;精确会话删除还会对不可变删除 ID 集做无条件幂等清理。Chat Completions、Responses、Channels 及未来入口共享这一权威,而不把 LibreChat 持久化策略推进 Agents SDK 内部。
源码印证:remote/lifecycle.ts 中的 AgentExecutionEnrollment 类是对应的核心实现。构造时要求任务必须带 providerExecutionId,否则直接报错——这正是“必须持有一个可围栏的 Provider 执行身份”的落点。它暴露三个关键方法:
abort():包装内部AbortController,即“唯一 Provider 中止信号”;track(write):把每次尾随写入登记进trailingWrites列表,且一旦进入结算阶段再调用即抛错;beginProviderExecution():向任务管理器提交 Provider 启动的 CAS(compare-and-swap),若信号已中止则抛AgentExecutionAdmissionError(HTTP 409,code 为ACCOUNT_DELETION_IN_PROGRESS或RUN_REPLACED,见 remote/lifecycle.ts);即使 CAS 的响应丢失也标记providerStarted,避免重复启动。
waitForAgentExecutionWrites() 用 Promise.allSettled 等待全部尾随写入,任一失败即上抛——这就是“终端结算前等待每一次 usage/artifact/存储写入、失败可调和”的实现细节。
5. Agent turn execution plan:不可变的“本轮决策”,不执行模型也不持有持久化
定义核心:在认证、Agent 解析、工具初始化完成后只编译一次的、请求内不可变决策。记录可信轮次来源、会话谱系、暂停能力、绑定/动作上下文,以及选用 checkpoint、history 或 fresh 状态加载策略;不执行模型、不拥有持久化。Checkpoint 失败在同一 Agents 生命周期内回退到持久 history。
源码印证:plan.ts 精确实现了这一语义。AgentTurnOrigin 枚举了 'user' | 'subagent' | 'completion' | 'schedule' | 'event' | 'resume' 六种可信来源;AgentTurnContinuationStrategy 枚举 'checkpoint' | 'history' | 'fresh'。AgentTurnExecutionPlan 被 Object.freeze() 冻结为不可变对象。resolveAgentTurnExecutionPlan() 的关键决策逻辑是:isNewConversation 时无条件 fresh;否则只有“存在事件绑定 + 存在 expectedAction + checkpointer 非内存型 + (无暂停能力或具备持久挂起能力)”时才能尝试 checkpoint,其余一律 history(plan.ts)。这从代码层面解释了为何“checkpoint 策略是资格推导出来的,而非运维配置出来的”,也呼应了文档中“checkpoint 失败回退到 durable history 属于同一生命周期”的约束。
6. Effective agent selection:强制执行模型规格后的“同一身份”
定义核心:在应用了强制的 model spec 之后解析出的最终 endpoint 与 Agent 身份。授权与 Agent 加载必须在初始化 envelope 之前消费同一个身份。
这一术语解决的是“身份竞态”:如果授权阶段按 A 身份放行、加载阶段却按 B 身份执行,就会产生越权路径。因此词汇表要求把“模型规格覆盖后的有效身份”作为授权与加载的唯一输入。从源码结构看,selection.ts 与 load.ts 的存在即表明“身份选择”与“Agent 装载”被显式分离,二者共享解析结果,避免身份在入口之间漂移。
二、运行时的事实供给:MCP 请求体与调用方能力投影
7. MCP runtime request body:只活在 MCP 处理期内的可信聊天标识
定义核心:仅当某个 MCP 服务正在处理 Agent 请求时才会提供的可信聊天标识。它让“请求作用域的头占位符”成为可能,同时不会把用户特定请求数据留在共享的服务定义上。
这解决的是共享 MCP 服务的“残留污染”问题:如果用户请求数据写入全局服务定义,下一个用户的请求就会读到上一个用户的标识。该术语要求所有用户相关标识必须走请求作用域,服务定义保持无状态。其实现痕迹可见于 context.ts 中围绕 MCP 的 MCPManager 使用——上下文按需获取 MCP 指令,而请求特定的内容由运行时单独提供。
8. Caller Capability Projection:调用方视角的工具能力“投影”,不是授权
定义核心:由 SDK 持有的、版本化的“当前活动工具”分类视图,供直接与程序化两类调用方使用。事件驱动执行把该投影当作数据传输;LibreChat 将其与自身的可信注册表相交集,永不重新计算延迟工具发现策略,也不把投影当作授权。
源码印证:callerCapabilities.ts 与其配套测试文件 callerCapabilities.spec.ts 即该术语的落点。设计意图很明确:LibreChat 信任自己的注册表,外部传来的能力声明最多只能用于“该工具是否对调用方可见”,绝不能回答“该调用方是否有权执行”。把“能力投影”与“授权”分开,是从源头杜绝通过伪造能力列表提权的攻击面。
三、子代理的执行模型:子线程、任务所有者与完成唤醒
9. Subagent thread:只读的持久化“子会话”
定义核心:由单一父会话与子代理身份拥有的、持久化、只读(view-only) 的子会话。父 Agent 可凭稳定的 threadId 续跑它;每次续跑都使用从规范子记录(canonical child transcript)恢复的全新执行租约。它不是普通的人类可写聊天。
源码印证:subagentThreads.ts 实现了线程的创建、恢复与续跑逻辑。文件头部的常量透露了执行模型的关键参数:SCOPE_VERSION = 1、DEFAULT_MAX_THREAD_DEPTH = 1(默认子代理嵌套深度为 1 层)、DEFAULT_LEASE_TTL_MS = 30_000、DEFAULT_LEASE_HEARTBEAT_MS = 10_000、DEFAULT_OWNER_DRAIN_TIMEOUT_MS = 45_000——“执行租约”通过 TTL 与心跳在代码中落地,Owner 排空超时为 45 秒。这也与词汇表所述“续跑使用全新执行租约”“Mongo 只持久化逻辑子线程与其续跑围栏”一致。
10. Live subagent task owner:唯一持有“游离执行”的 API 进程
定义核心:唯一持有已分离子执行(detached child execution)、其 abort controller 与有界控制队列的 API 进程。Redis 可以把可信的 poll/control 信封路由给该 owner,但不迁移也不持久化执行器;Mongo 只持久化逻辑子线程与其续跑围栏。
源码印证:subagentTaskRouting.ts 中可见 SubagentTaskOwnerUnavailableError、boundedClaim、boundedTaskList、controlFingerprint 等实现单元——控制信封先做指纹校验再路由,owner 不可用时抛明确的“owner 不可用”错误;subagentTaskContext.ts 提供 runWithDetachedSubagentUsage 这一“在分离任务上下文中执行并归集 usage”的运行器。Redis 路由与 Mongo 权威的分工,正是“进程可死、任务语义不丢”的实现前提。
11. Subagent completion wakeup:崩溃也不丢的“继续”触发器
定义核心:在分离子执行开始之前预先注册的持久化内部 continue 触发,因此进程崩溃不会丢失唤醒。投递会推迟到子会话的终结记录持久化之后,目标锁定“发起 Agent + 精确父响应分支”,携带的是任务元数据而非子输出;它会等待父代生成安定后再启动收集结果的父轮次(经由既有任务存储)。
源码印证:subagentCompletionWakeup.ts 与其 spec 文件 subagentCompletionWakeup.spec.ts(__tests__ 等目录内同名 spec)共同验证“先注册唤醒、后执行子任务、终结后触发”的时序。backgroundCompletionWakeup.ts 则是后台完成的同类唤醒实现。值得注意的是,父 Agent 的输出必须经由“既有任务存储”收集——子任务输出不随唤醒信封投递,避免了大负载消息在 Redis 与 Mongo 之间反复搬运。
12. Agent continuation preparation:投递前的“单一来源分发缝”
定义核心:在准入前立即解析持久化 continue 投递的单一分发缝(single source-dispatch seam)。Bound Event Actor 工作选择绑定适配器;内部完成工作按稳定来源身份选择适配器。它可解析权威输入与分支状态、或结算已消费的工作,但不拥有来源结果真值、投递排序与代际执行。
源码印证:triggers/continuation.ts 与 triggers/bindingResolver.ts 的组合即是该“缝”。bindingResolver 负责把绑定解析成“用户、租户、API Key、绑定 ID”下的权威会话身份;continuation 则在准入前一刻决定该继续工作应走哪条适配器并取回输入与分支状态。这种“单一分发点”设计保证了无论唤醒来自 event actor 还是内部完成,续跑决策都收敛到同一路径,避免多路分发造成的竞争。
13. Warm terminal steer continuation:终端边界的“预热转向”
定义核心:在一代生成的终端边界(terminal boundary)之前被接受的排队 steer,可以不新建替代生成、直接延续同一个 SDK Run。并行 Stop 钩子折叠后,串行化的 StopFinalize 阶段会告知任务存储“是否已有下一段 continuation 已计划 / 或终端进度已被禁止”。存储原子地在三类动作间选择:认领当前 protocol-v2 FIFO 批次、为已计划段保持空准入、或密封准入使一切竞争/后续消息变成普通跟进。被认领的 steer 回执是崩溃恢复权威;protocol-v1 代永远密封,因为无法恢复歧义终端认领。Tool-batch、抢占与终端边界共享同一个持久 apply-and-inject 适配器,SDK 则拥有有界的 Stop-continuation 循环。
源码印证:steering/ 目录整体即该机制的实现区,内含 runtime.ts、request.ts、media.ts、refs.ts、offset.ts 等模块,说明“steer 请求”本身也被建模为受控对象。其“协议 v1 永远密封、v2 可认领”的差别对待,本质上是对“旧版无法恢复歧义终端认领”这一能力差距的补偿策略。
四、排队轮次与事件处理结局:入队 ≠ 完成
14. Agent queued turn:服务端持有的普通跟进轮次
定义核心:当某代 Agent 正在运行时被接受的服务端普通跟进。它的 Mongo 行是唯一的 FIFO、载荷与生命周期权威;触发投递只是可重放的唤醒,Enrollment 只是执行适配器。生命周期先为确定性的投递身份预留、只有在被捕获分支具备干净的持久化前驱结局后才准入;只有在 Provider 调用已注册后才会提交来源持有的代际回执。已接受或去重后的回环响应要求精确回执;回执前的进程死亡表现为“明确的准入不确定证据”,而非静默吞掉文本。准入调和是带租约、退避调度的工作;删除会话会取消行、退役投递、移除载荷,然后才删除会话波次。
源码印证:queuedTurns.ts 是核心实现(超过千行)。常量区透露了大量可观察参数:AGENT_QUEUED_TURN_SOURCE = 'agent-queued-turn'、claim 与调和租约均为 2 * 60 * 1000 ms、调和退避基数为 5 秒、上限 5 分钟、恢复周期默认 30 秒、恢复批量上限 100;尤其值得注意 PROCESS_CLAIM_OWNER = agent-queued-turn:${process.pid}:${randomUUID()} 及其注释——“容器副本间 PID 通常相同,保持进程内认领所有者稳定,同时围栏每一个其他进程实例”。GenerationAdmissionEvidence 携带 generationId 与 generationCreatedAt,用于精确比对“这一代是否真的准入”,与术语中“绝不从瞬时任务状态推断 Provider 结局”的约束互为印证。
15. Subagent activity stream:面板可见的只读活动投影
定义核心:面向当前打开的私有面板、任务作用域的有界子进程实时投影。它可经 Redis 跨 API 副本,绝不携带隐藏推理文本,绝不控制或结算执行。持久子线程仍是权威,其既有轮询视图是丢失/不可用实时事件时的回退。
源码印证:subagentActivity.ts 与其 spec 定义了 SubagentActivityStream、SubagentActivitySubscriber、SubagentActivityTerminalStatus 等类型,以及 boundSubagentActivityUpdate 绑定更新器。观察路径与控制路径被强制分开:任何活动事件都到不了中止或结算接口,防止“看得到 = 改得动”的权限放大。
16 & 17. Agent event handling outcome 与 Agent event expected action:以“结局”与“预期动作”取代模型自述
定义核心(outcome):先前已接受事件投递的、持久化且按代围栏(generation-fenced)的结果。started 证明代际准入;终端态区分“已验证工具应用、无动作的干净完成、失败、取消”。传输成功保持独立,因此“已接受的事件”不能伪装成“已完成的工作”。
定义核心(expected action):可选的、由来源声明的工具名与有界参数子集,由宿主对照已观察到的完整运行步骤求值。它是证据策略,不是授权,也不是模型撰写的成功声明。
源码印证:triggers/outcome.ts 实现了“结局”记录,triggers/README.md 对 handling 生命周期做了权威说明:投递成功 ≠ 工作完成,succeeded 之后还应观察到唯一的 applied / completed_no_action / failed / cancelled 结局。更重要的是,README 明确写道:LibreChat 只有在宿主观察到的工具证据匹配 expectedAction 契约时才上报 applied,“模型撰写的散文永远不当作证明”;同时 expectedAction 只对 bound-child 事件开放,fire、steer 与未绑定 continue 一律拒绝该契约。这正是“evidence policy, not authorization, not model-authored success claim”的工程化表述。凡带 expectedAction 的投递还拒绝 coalescing,因为单次代际无法证明多个互不相同的动作围栏。
五、Event Actor:事件驱动的持久子执行器
Event Actor 是 LibreChat 把“事件驱动的子代理”做成崩溃可恢复、结局可证明的核心机制,也是 CONTEXT.md 中条目密度最高的一组术语。其落点在 packages/api/src/agents/triggers/ 目录:actor.ts、turn.ts、engine.ts、delivery.ts、envelope.ts、host.ts、ingress.ts、bindings.ts、batch.ts、dispatch.ts、outcome.ts、continuation.ts、detachedAction.ts 等文件覆盖了从注册、投递、排队到执行、结算的完整链路;目录内 README(triggers/README.md)则是对外契约的权威文档。
18. Event actor head:子会话上“最后一个已提交 checkpoint”的私有指针
定义核心:事件绑定的子会话上、指向其最新已提交 LangGraph checkpoint(外加一个供安全清理的前一 checkpoint)的私有持久指针。只有“合格的应用动作”能通过 compare-and-swap 推进它;失败、取消或无动作的调用都不改变它。旧路径事件会把 head 标记为“需从持久消息历史冷重建”,之后才能恢复 fork 模式。任何已提交提交冲突、未验证提交或提交后持久化失败都会被保留在私有调和日志中,阻止后续 Actor 轮次从过期状态继续;精确标记只有在 checkpoint 被验证为权威、历史被修复、或外部动作被显式补偿后才能清除。
源码印证:actor.ts 中的导入项即见 forkAgentEventCheckpoint、checkpoint overlay、checkpointMatches 等实现;state 中携带 actorThreadId、generation、checkpoint、checkpointNamespace 等字段。CAS 推进与调和日志的并用,保证了“head 不因并发动作或半途写入而漂移”。
19. Event actor invocation fork:投递拥有的 checkpoint 命名空间
定义核心:从 actor head 复制的、投递专属的 checkpoint 命名空间。每个绑定 Event Actor 只进入一个回合模块;fresh、history、checkpoint 是内部状态加载适配器,由 actor 状态与不可变请求能力自动选择,绝不由运维配置决定。history 适配器拥有自己的持久回合围栏与 token 排序;不可变 protocol-v1 token 在其任务排空前保持只读兼容。热调用只接收新可信事件,观察到预期动作即提交终端 checkpoint,否则删除 fork。挂起等待审批 / Ask User 时,SDK 发出带签名、带版本的挂起证据;子 Conversation 是权威的一击性(one-shot)挂起权威,generation job 只携带供 UI、滚动部署路由与既有 resume 端点使用的版本化投影。Resume、再挂起、取消与过期都会先认领或替换精确挂起,再触碰其 job 投影,因此后续 mailbox 投递在终端历史与处理证据安定前保持阻塞。
源码印证:triggers/actor.ts 中 fresh|history|checkpoint 三种加载适配器与 canPause、checkpointer 类型的组合判断,与 plan.ts 中策略推导逻辑一脉相承(checkpoint 尝试仅在绑定 + expectedAction + 非 memory checkpointer + 持久挂起能力同时满足时发生)。挂起“先 Conversation、后投影”的顺序,正是为了消除“UI 已显示动作完成但持久化尚未安定”的窗口。
20. Event actor receipt:权威 AgentTriggerDelivery 行上的私有终端证明
定义核心:一次绑定 Actor 调用存储在权威 AgentTriggerDelivery 行上的私有终端证明。它携带唯一投递身份、终端决议、精确 checkpoint 与有界动作身份,可在保留窗口内提供重放与恢复,而不存储提示词、事件、工具参数、工具输出与会话历史。它不拥有 actor checkpoint;在回执持久化前,会话只保留 actor head 与任何未解决调和。
这条定义的关键价值是“证据的最小化”:所有可重建的信息都不进回执,回执只保留让系统“知道这一投递最终怎样了”的最小身份集——这既控制了存储膨胀,也避免把用户内容泄露进调度基础设施。
21. Agent event actor mailbox:自动的持久投递排序车道
定义核心:单条已认证来源绑定的自动持久投递排序车道。在子轮次记录权威终端结局之前,后续投递保持在传输准入之后排队;它串行化既有合并批次与单事件,而不成为第二个执行控制器或 checkpoint 存储。
源码印证:triggers/README.md 对 mailbox 语义有明确描述:绑定 actor 的下一条投递在当前投递达到传输成功后会继续排队,直到子代际记录 applied/completed_no_action/failed/cancelled 之一;不同绑定相互独立可并行;既有的合并批次占据一个 mailbox 位置且保留各成员独立回执;活动的 mailbox 记录不享受常规成功 TTL,90 天保留窗口从终端结局记录后才开始。可同时参考 delivery.ts 及其 spec 验证排队与认领细节。
22. Agent trigger capability shield:混合版本下的“能力盾”
定义核心:面向内部触发工作的持久化、混合版本表示,只有具备能力的 worker 才能执行。Mongo 侧使用旧版可发布的 staging 壳;无 owner 与 deadline 的排队 leased 壳,旧 worker 无法认领但可用于有界车道复查;执行期只存在私有租约;死亡后遗留 capability_dead 终端壳。私有能力字段持有当前认领、重试与死信真值。Redis 侧使用版本化的 fail-closed 终端状态与恢复索引,旧替换脚本与清扫器无法消费。该盾是存储缝的实现细节,绝不是部署开关或用户可配置的产品模式。
语义要点:这是滚动发布(rolling deploy)场景下的“兼容性安全阀”——新版本产出的内部任务,旧版本既不能错误认领(会破坏语义),也不能被它拖死(可做有界复查);任务最终要么被有能力者消化,要么以终端态退出。将其定义为“实现细节”是为了防止运维层误把它当功能开关摆弄。
23. Event actor 的对外契约(阅读源码前的实操落点)
要真正运行这套系统,triggers/README.md 是必读入口,其核心契约包括:
- 统一入队:调度、webhook、队列消费者、MCP 集成或内部事件适配器都产出同一份版本化 envelope,调用
enqueueAgentTrigger,适配器不直接调用 Agent 运行时。契约要求:入队前认证与授权来源、从event.payload剥离凭据与传输密钥、为每个事件给稳定event.id、为重试保持稳定deliveryId、continue只能带已持久化的conversationId与精确parentMessageId。典型入队代码如下(完整示例见 triggers/README.md):
const { createAgentTriggerEnvelope } = require('@librechat/api');
const { enqueueAgentTrigger } = require('~/server/services/Agents/triggers');
await enqueueAgentTrigger(
createAgentTriggerEnvelope({
mode: 'fire',
requestId,
deliveryId,
receivedAt: Date.now(),
principal: { id: userId, role, tenantId },
event: {
id: eventId,
type: 'resource.ready',
occurredAt,
source: { id: webhookId, type: 'webhook' },
payload: sanitizedPayload,
},
target: { agentId },
input,
}),
{ orderingKey: resourceId },
);
-
远程事件入口:已认证控制器与来源适配器可通过
POST /api/agents/v1/events(Remote Agents API-key 认证)入队同一持久 envelope,须发送且只发送一个稳定的Idempotency-Key;成功准入返回202 Accepted、不透明投递id与Location,轮询该位置可读到pending/leased/succeeded/dead。来源绑定注册走POST /api/agents/v1/events/bindings,响应含不透明id与子threadId。 -
投递保证:Mongo 在重启与多副本间拥有队列状态、租约、重试历史与死信;每次认领(含同进程再认领)都用全新 token 围栏;投递是 at-least-once,fire/continue/steer 复用 envelope 的幂等身份;可重试失败使用有界指数退避并尊重
Retry-After;无效 envelope、永久授权失败与耗尽重试成为持久死信。成功记录 90 天后过期,死信保留至显式重排或删除;账户删除先围栏准入并排空活动租约,不破坏排队工作。 -
事件合批(coalescing):可证明“互换观察”的多个 bound
continue可用同一coalesce.key合入一次子轮次。LibreChat 最多收集 750 ms、8 个事件、512 KiB 信封,随后以kind为librechat.agent_event_batch的确定性 JSON 文档调用子代理一次。但fire、steer、未绑定continue与任何expectedAction投递都拒绝 coalescing。
六、Theme definition:数据化的主题定义(外观层约定)
定义核心:对 LibreChat 语义色与共享外观角色的版本化、纯数据描述,可按亮/暗模式特化。主题模块在适配器应用前,先对照内置默认值校验并解析局部定义。主题定义不包含任意 CSS、应用行为或替代功能布局。
语义要点:它把“换肤”约束在“数据描述 + 语义角色”层:主题只声明语义色与外观角色(并可做明暗特化),解析器负责补全缺省与校验合法性,最后由适配器把语义角色翻译成实际样式。由于禁止任意 CSS 与应用行为进入主题定义,主题既不会成为任意代码执行面,也不会干扰功能布局。这份词汇表在仓库中更偏向“架构演进目标”与契约描述——例如前端基础外观层仍可看到按本地存储 color-theme 与 prefers-color-scheme 决定 light/dark 的传统路径(见 theme.ts);而“版本化主题定义”所描述的动态语义主题机制,应按 CONTEXT.md 的表述理解为该领域语言的既定设计契约,实际接入以对应版本实现为准。
七、把词汇表当“索引”继续读源码
CONTEXT.md 的价值不仅在于定义本身,更在于它是一张源码导航图。推荐的阅读路径是:
- 先读 triggers/README.md,建立“envelope → 入队 → 投递 → 结局”的端到端心智模型;
- 按执行主轴依次读 envelope.ts(请求契约)、plan.ts(回合决策)、remote/lifecycle.ts(Enrollment 终身管理)、run.ts(运行入口);
- 深入排队与事件域读 queuedTurns.ts、subagentThreads.ts、subagentActivity.ts、callerCapabilities.ts;
- 每个目录都配套了同名
*.spec.ts与*.integration.spec.ts测试(例如 queuedTurns.spec.ts、subagentCrossReplica.integration.spec.ts),它们把本术语表中的“崩溃可恢复”“跨副本路由”“精确回执”等承诺转成了可重复的机器验证。
总而言之,CONTEXT.md 是一份少见的、以“精确名词”承载“分布式执行正确性”的设计文档。把握住“谁拥有什么、谁不拥有什么、谁是权威、谁是投影、传输成功不等于工作完成”这几条主线,就能真正读懂 LibreChat Agents 子系统——并在生产排障或二次开发时,用同一套语言与源码、日志和队友对齐。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python08
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00