跳转到内容

子 Agent 委托与自生成

子 Agent 委托与自生成

学习目标

本章聚焦 LibreChat 的子 Agent 系统。你将了解:

  • 自生成(self-spawn)与显式子 Agent 两种模式的工作原理
  • 循环安全检测与深度限制机制
  • 子 Agent 上下文隔离策略
  • 配置数量限制与展开约束

前置知识

下文假设你已理解上述概念,直接聚焦 LibreChat 的具体实现。


项目实践

两种子 Agent 模式

LibreChat 支持两种子 Agent 模式,通过 buildSubagentConfigs 函数递归展开:

1. 自生成(self-spawn)

{
self: true,
type: 'self',
name: 'assistant',
description: 'Spawn assistant in an isolated context to handle a focused subtask.'
}

自生成复用父 Agent 的完整配置(模型、工具、指令),但创建隔离的图执行上下文。适合将复杂任务分解为多个独立子任务,每个子任务有自己的工具输出和上下文窗口。

2. 显式子 Agent

{
type: 'child-agent-id',
name: 'code-reviewer',
description: 'Delegate a subtask to the code-reviewer agent...',
agentInputs: childInputs, // 子 Agent 的独立输入
}

显式子 Agent 有自己独立的配置(不同的模型、工具、指令)。通过 subagents.agent_ids 配置指定。

循环安全检测

buildSubagentConfigs 使用 ancestors 集合防止循环委托:

buildSubagentConfigs(agent, ..., ancestors, depth):
nextAncestors = ancestors ∪ {agent.id}
for child in agent.subagentAgentConfigs:
if child.id in ancestors:
continue // 跳过,防止 A → B → A
buildSubagentConfigs(child, ..., nextAncestors, depth + 1)

深度限制MAX_SUBAGENT_DEPTH 防止过深嵌套。每次递归递增 depth,超过限制抛出错误。

配置数量限制MAX_SUBAGENT_RUN_CONFIGS 限制展开的总配置数。每个子 Agent(包括自生成和显式)都消耗一个配额。

子 Agent 上下文隔离

isSubagent: true 标志确保子 Agent 的工具上下文完全隔离:

维度父 Agent子 Agent(isSubagent: true
defer_loading 覆盖从历史提取跳过
工具定义注入从注册表添加跳过
toolRegistry原始引用深度克隆(Map + 每个 LCTool 浅拷贝)
initialSummary传递设为 undefined
discoveredTools从历史提取设为 undefined

为什么需要深度克隆:父 Agent 在构建子 Agent 后,可能继续参与同一个图的其他路径(如 handoff 目标)。如果子 Agent 共享 toolRegistry 引用,父 Agent 后续对 defer_loading 的修改会泄漏到子 Agent 的上下文中。

递归展开与多级委托

buildSubagentConfigs 不仅展开当前 Agent 的直接子 Agent,还递归解析子 Agent 自己的 spawn targets:

A → B → C
buildSubagentConfigs(A):
→ 构建 B 的 inputs
→ buildSubagentConfigs(B): // 递归
→ 构建 C 的 inputs
→ B 没有子 Agent → 返回
→ B.inputs.subagentConfigs = [C]
→ 返回 [self, B(C)]

这使得多级委托(A → B → C)可以正确工作——B 的子 Agent C 在 B 的 agentInputs 中被配置。


问题与规避

问题 1:子 Agent 继承了父 Agent 的工具搜索状态

规避isSubagent: true 时,跳过 defer_loading 覆盖、工具定义注入,并对 toolRegistry 进行深度克隆。

问题 2:A → A 自循环导致无限递归

规避ancestors 集合在递归前包含当前 Agent ID,child.id === agent.id 的条件也被显式跳过。

问题 3:子 Agent 配置数超限

规避countSubagentConfig 在每次添加子 Agent 配置时递增计数器,超过 MAX_SUBAGENT_RUN_CONFIGS 时抛出错误并记录详细日志(包含 rootAgentIds 和当前计数)。


设计取舍

自生成 vs 仅显式子 Agent

方案优势代价
支持自生成用户无需预定义子 Agent,动态分解任务需要确保隔离性,防止状态泄漏
仅显式简单明确,每个子 Agent 有清晰定义用户需要预定义所有子 Agent

LibreChat 同时支持两种模式,满足不同场景需求。


参考来源