mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-23 15:11:42 +00:00
Agents: fix subagent model precedence
This commit is contained in:
committed by
Ayaan Zaidi
parent
d4cccda570
commit
e394262bd8
@@ -12,6 +12,7 @@ import {
|
||||
modelKey,
|
||||
resolveAllowedModelRef,
|
||||
resolveConfiguredModelRef,
|
||||
resolveSubagentConfiguredModelSelection,
|
||||
resolveThinkingDefault,
|
||||
resolveModelRefFromString,
|
||||
} from "./model-selection.js";
|
||||
@@ -857,3 +858,48 @@ describe("normalizeModelSelection", () => {
|
||||
expect(normalizeModelSelection(42)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveSubagentConfiguredModelSelection", () => {
|
||||
it("prefers the agent primary model over agents.defaults.subagents.model", () => {
|
||||
const cfg = {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "anthropic/claude-sonnet-4-6" },
|
||||
subagents: { model: "openai/gpt-5.4" },
|
||||
},
|
||||
list: [
|
||||
{
|
||||
id: "research",
|
||||
model: { primary: "anthropic/claude-opus-4-6" },
|
||||
},
|
||||
],
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
expect(resolveSubagentConfiguredModelSelection({ cfg, agentId: "research" })).toBe(
|
||||
"anthropic/claude-opus-4-6",
|
||||
);
|
||||
});
|
||||
|
||||
it("still prefers agent subagents.model over the agent primary model", () => {
|
||||
const cfg = {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "anthropic/claude-sonnet-4-6" },
|
||||
subagents: { model: "openai/gpt-5.4" },
|
||||
},
|
||||
list: [
|
||||
{
|
||||
id: "research",
|
||||
model: { primary: "anthropic/claude-opus-4-6" },
|
||||
subagents: { model: "google/gemini-2.5-pro" },
|
||||
},
|
||||
],
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
expect(resolveSubagentConfiguredModelSelection({ cfg, agentId: "research" })).toBe(
|
||||
"google/gemini-2.5-pro",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -440,8 +440,8 @@ export function resolveSubagentConfiguredModelSelection(params: {
|
||||
const agentConfig = resolveAgentConfig(params.cfg, params.agentId);
|
||||
return (
|
||||
normalizeModelSelection(agentConfig?.subagents?.model) ??
|
||||
normalizeModelSelection(params.cfg.agents?.defaults?.subagents?.model) ??
|
||||
normalizeModelSelection(agentConfig?.model)
|
||||
normalizeModelSelection(agentConfig?.model) ??
|
||||
normalizeModelSelection(params.cfg.agents?.defaults?.subagents?.model)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ async function runSubagentModelCase(params: {
|
||||
home: string;
|
||||
cfgOverrides?: Partial<OpenClawConfig>;
|
||||
jobModelOverride?: string;
|
||||
agentId?: string;
|
||||
}) {
|
||||
const storePath = await writeSessionStore(params.home);
|
||||
mockEmbeddedAgent();
|
||||
@@ -102,6 +103,9 @@ async function runSubagentModelCase(params: {
|
||||
if (params.jobModelOverride) {
|
||||
job.payload = { kind: "agentTurn", message: "do work", model: params.jobModelOverride };
|
||||
}
|
||||
if (params.agentId) {
|
||||
job.agentId = params.agentId;
|
||||
}
|
||||
|
||||
await runCronIsolatedAgentTurn({
|
||||
cfg: makeCfg(params.home, storePath, params.cfgOverrides),
|
||||
@@ -192,4 +196,25 @@ describe("runCronIsolatedAgentTurn: subagent model resolution (#11461)", () => {
|
||||
expect(call?.model).toBe("gpt-4o");
|
||||
});
|
||||
});
|
||||
|
||||
it("prefers the agent model over agents.defaults.subagents.model", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const call = await runSubagentModelCase({
|
||||
home,
|
||||
agentId: "research",
|
||||
cfgOverrides: {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "anthropic/claude-sonnet-4-5",
|
||||
workspace: path.join(home, "openclaw"),
|
||||
subagents: { model: "ollama/llama3.2:3b" },
|
||||
},
|
||||
list: [{ id: "research", model: { primary: "anthropic/claude-opus-4-6" } }],
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(call?.provider).toBe("anthropic");
|
||||
expect(call?.model).toBe("claude-opus-4-6");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,6 +19,7 @@ export type ResolveCronModelSelectionParams = {
|
||||
cfg: OpenClawConfig;
|
||||
cfgWithAgentDefaults: OpenClawConfig;
|
||||
agentConfigOverride?: {
|
||||
model?: unknown;
|
||||
subagents?: {
|
||||
model?: unknown;
|
||||
};
|
||||
@@ -61,6 +62,7 @@ export async function resolveCronModelSelection(
|
||||
|
||||
const subagentModelRaw =
|
||||
normalizeModelSelection(params.agentConfigOverride?.subagents?.model) ??
|
||||
normalizeModelSelection(params.agentConfigOverride?.model) ??
|
||||
normalizeModelSelection(params.cfg.agents?.defaults?.subagents?.model);
|
||||
if (subagentModelRaw) {
|
||||
const resolvedSubagent = resolveAllowedModelRef({
|
||||
|
||||
@@ -65,7 +65,7 @@ async function applySubagentModelPatch(cfg: OpenClawConfig) {
|
||||
}
|
||||
|
||||
function makeKimiSubagentCfg(params: {
|
||||
agentPrimaryModel: string;
|
||||
agentPrimaryModel?: string;
|
||||
agentSubagentModel?: string;
|
||||
defaultsSubagentModel?: string;
|
||||
}): OpenClawConfig {
|
||||
@@ -83,7 +83,7 @@ function makeKimiSubagentCfg(params: {
|
||||
list: [
|
||||
{
|
||||
id: "kimi",
|
||||
model: { primary: params.agentPrimaryModel },
|
||||
model: params.agentPrimaryModel ? { primary: params.agentPrimaryModel } : undefined,
|
||||
subagents: params.agentSubagentModel ? { model: params.agentSubagentModel } : undefined,
|
||||
},
|
||||
],
|
||||
@@ -400,7 +400,6 @@ describe("gateway sessions patch", () => {
|
||||
|
||||
test("allows global defaults.subagents.model for subagent session even when missing from global allowlist", async () => {
|
||||
const cfg = makeKimiSubagentCfg({
|
||||
agentPrimaryModel: "anthropic/claude-sonnet-4-6",
|
||||
defaultsSubagentModel: SUBAGENT_MODEL,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user