Bug Report: Subagent 未正确继承父 Agent 的模型配置 #2006
Replies: 4 comments
|
子代理未继承父 Agent 模型配置——和 #1369/#1442(动态指定子代理模型)是同一块:子代理的模型继承/选择机制还没完善。 当前 workaround:子代理创建时显式指定模型,或父会话切好模型再派发。第 9 章子代理配置 + 已知限制有记录:https://github.com/Electricitysheep/dsh-handbook/blob/main/docs/09-mcp-subagent-workflow.md |
|
https://github.com/alex04130/dsh-forge |
|
补一条已实证可用的替代路线(Pi 插件生态的子代理,不是对原生 subagent 的修复): dsh plugin --profile main add pi2dsh
dsh plugin --profile main add @tintinweb/pi-subagents这条路线上"继承"与"显式指定"两种都过了端到端:不指定模型的子代理继承调用者实时路由(会话内切换优先于创建时快照——我们第一版也犯过只读 示例与真机验收(stock CLI + 真模型,含 steer/resume/stop/跨重启四场景): |
Uh oh!
There was an error while loading. Please reload this page.
问题描述
当主 Agent 使用了非默认模型(如通过 agent-default-model 配置或运行时切换模型)时,通过 subagent / subagent_fork 工具创建的子 Agent 没有正确继承该模型配置。子 Agent 可能使用错误的默认模型,或者因 provider/model 为空导致 LLM 调用失败(返回 0 token / contextWindow 不一致)。
影响范围
所有通过 spawn 或 fork provider 创建的子 Agent
显式触发场景:用户通过 UI 切换模型后创建子 Agent
隐式触发场景:创建主 Agent 时 agentOptions 未设置 provider/model(依赖 agent-default-model 或 agent/request waterfall 运行时补全)
根因分析
问题涉及两个层面的缺陷:
文件:packages/subagent/subagent/src/child-agent.ts (第 68-83 行)
export function resolveChildAgentOptions(
parent: Agent,
requested: AgentOptions | undefined,
childDepth: number,
): AgentOptions {
const parentProvider = parent.options.provider
const parentModel = parent.options.model
const parentMaxTokens = parent.options.maxTokens
return {
...parentProvider !== undefined ? { provider: parentProvider } : {},
...parentModel !== undefined ? { model: parentModel } : {},
...parentMaxTokens !== undefined ? { maxTokens: parentMaxTokens } : {},
...requested,
subagentDepth: childDepth,
}
}
parent.options 是 ReactLoopAgent 构造函数中保存的不可变快照(agent.ts:80-84),它只在 Agent 创建时设置一次,后续不会更新。
然而,主 Agent 的实际运行模型可能在以下两种情况下与 parent.options 不一致:
运行时模型切换:installModelSelection(packages/core/agent/src/model-selection.ts)通过 agent/request waterfall 在每次 LLM 调用时覆盖 provider/model,但不会回写 parent.options。用户通过 UI 切换模型后,父 Agent 实际使用新模型,但 parent.options 仍保存旧值。
依赖 agent-default-model 服务:某些代码路径(如 packages/host/apiproxy/src/api-proxy.ts:1148-1168 的 selectionFor 函数)在创建 Agent 时可能不设置 options.provider/options.model,而是依赖 agent/request waterfall 在运行时通过 agent-default-model 补全。这种情况下 parent.options 的 provider/model 可能为 undefined。
2. 配置层面:tool-subagent 未设置 agentOptions
文件:packages/bundle/base/cordis.patch.yml (第 313-325 行)
id: tool-subagent
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: spawn
toolName: subagent
backgroundMode: continuable
缺少 agentOptions,子 Agent 在 resolveChildAgentOptions 返回空时没有兜底
id: tool-subagent-fork
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: fork
toolName: subagent_fork
backgroundMode: one-shot
同样缺少 agentOptions
tool-subagent 的 Config 类型(packages/subagent/tool-subagent/src/index.ts:52)已经定义了 agentOptions?: AgentOptions 字段,execute 方法(第 381 行)也会将其透传到 startContinuable 或 start 请求中。但当前配置文件中没有设置该字段,导致子 Agent 无法获得模型配置。
此外,子 Agent 在创建时没有安装 installModelSelection(packages/core/agent/src/model-selection.ts),因此即使主 Agent 通过 agent/request waterfall 动态切换了模型,子 Agent 也没有这个兜底机制,而是完全依赖 resolveChildAgentOptions 返回的 agentOptions。
修复建议
1.resolveChildAgentOptions 增加 agentDefaultModel 兜底
在 resolveChildAgentOptions 中,当 parent.options.provider 或 parent.options.model 缺失时,通过 agentDefaultModel 服务获取当前默认值作为 fallback:
export function resolveChildAgentOptions(
parent: Agent,
requested: AgentOptions | undefined,
childDepth: number,
): AgentOptions {
const parentProvider = parent.options.provider
const parentModel = parent.options.model
const parentMaxTokens = parent.options.maxTokens
// 如果父 Agent 没有显式设置 provider/model,尝试从 agent-default-model 服务读取
let fallbackProvider = parentProvider
let fallbackModel = parentModel
if (fallbackProvider === undefined || fallbackModel === undefined) {
try {
const defaultModel = parent.ctx.get('agentDefaultModel')
if (defaultModel !== undefined) {
const selection = defaultModel.currentSelection()
if (fallbackProvider === undefined) fallbackProvider = selection.provider
if (fallbackModel === undefined) fallbackModel = selection.model
}
} catch {
// agent-default-model 服务未安装,保持原行为
}
}
return {
...fallbackProvider !== undefined ? { provider: fallbackProvider } : {},
...fallbackModel !== undefined ? { model: fallbackModel } : {},
...parentMaxTokens !== undefined ? { maxTokens: parentMaxTokens } : {},
...requested,
subagentDepth: childDepth,
}
}
2.在 base/cordis.patch.yml(或其他 bundle 配置)中,为 tool-subagent 和 tool-subagent-fork 添加 agentOptions:
id: tool-subagent
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: spawn
toolName: subagent
backgroundMode: continuable
agentOptions:
provider: deepseek-api
model: deepseek-v4-flash
id: tool-subagent-fork
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: fork
toolName: subagent_fork
backgroundMode: one-shot
agentOptions:
provider: deepseek-api
model: deepseek-v4-flash
注意:这里的 provider/model 应该是模板变量或者从 agent-default-model 的配置中读取,而不是硬编码。不同部署环境的默认模型可能不同。
All reactions