diff --git a/src/agents/agent-scope.test.ts b/src/agents/agent-scope.test.ts index d1d3c900a49..7b3c1d7c17e 100644 --- a/src/agents/agent-scope.test.ts +++ b/src/agents/agent-scope.test.ts @@ -59,6 +59,38 @@ describe("resolveAgentConfig", () => { }); }); + it("falls back to agents.defaults.model when agent has no model configured", () => { + const cfgWithStringDefault: OpenClawConfig = { + agents: { + defaults: { + model: "anthropic/claude-sonnet-4", + }, + list: [{ id: "main" }], + }, + }; + expect(resolveAgentModelPrimary(cfgWithStringDefault, "main")).toBe("anthropic/claude-sonnet-4"); + + const cfgWithObjectDefault: OpenClawConfig = { + agents: { + defaults: { + model: { + primary: "openai/gpt-5.2", + fallbacks: ["anthropic/claude-sonnet-4"], + }, + }, + list: [{ id: "main" }], + }, + }; + expect(resolveAgentModelPrimary(cfgWithObjectDefault, "main")).toBe("openai/gpt-5.2"); + + const cfgNoDefaults: OpenClawConfig = { + agents: { + list: [{ id: "main" }], + }, + }; + expect(resolveAgentModelPrimary(cfgNoDefaults, "main")).toBeUndefined(); + }); + it("supports per-agent model primary+fallbacks", () => { const cfg: OpenClawConfig = { agents: { diff --git a/src/agents/agent-scope.ts b/src/agents/agent-scope.ts index c1e5774e23a..685b8170bca 100644 --- a/src/agents/agent-scope.ts +++ b/src/agents/agent-scope.ts @@ -144,14 +144,29 @@ export function resolveAgentSkillsFilter( export function resolveAgentModelPrimary(cfg: OpenClawConfig, agentId: string): string | undefined { const raw = resolveAgentConfig(cfg, agentId)?.model; - if (!raw) { + if (raw) { + if (typeof raw === "string") { + const trimmed = raw.trim(); + if (trimmed) { + return trimmed; + } + } else { + const primary = raw.primary?.trim(); + if (primary) { + return primary; + } + } + } + + // Fallback to agents.defaults.model when agent has no model configured + const defaultModel = cfg.agents?.defaults?.model; + if (!defaultModel) { return undefined; } - if (typeof raw === "string") { - return raw.trim() || undefined; + if (typeof defaultModel === "string") { + return defaultModel.trim() || undefined; } - const primary = raw.primary?.trim(); - return primary || undefined; + return defaultModel.primary?.trim() || undefined; } export function resolveAgentModelFallbacksOverride(