From b9a61aa0d2b7c65c0a89ef64f810eddd112b3e37 Mon Sep 17 00:00:00 2001 From: Billion Bian Date: Mon, 23 Feb 2026 13:56:54 +0800 Subject: [PATCH] fix(agents): fall back to agents.defaults.model when agent has no model config When an agent in agents.list lacks a model configuration, resolveAgentModelPrimary now correctly falls back to cfg.agents.defaults.model instead of returning undefined. This fixes embedded agents (like slug-generator) silently falling back to a hardcoded DEFAULT_MODEL when the main agent omits the model block but global defaults are configured. Fixes openclaw#24168 --- src/agents/agent-scope.test.ts | 32 ++++++++++++++++++++++++++++++++ src/agents/agent-scope.ts | 25 ++++++++++++++++++++----- 2 files changed, 52 insertions(+), 5 deletions(-) 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(