diff --git a/src/agents/agent-scope.ts b/src/agents/agent-scope.ts index 27363a51d..8f5704dc7 100644 --- a/src/agents/agent-scope.ts +++ b/src/agents/agent-scope.ts @@ -20,6 +20,7 @@ type ResolvedAgentConfig = { workspace?: string; agentDir?: string; model?: AgentEntry["model"]; + thinkingDefault?: AgentEntry["thinkingDefault"]; memorySearch?: AgentEntry["memorySearch"]; humanDelay?: AgentEntry["humanDelay"]; heartbeat?: AgentEntry["heartbeat"]; @@ -103,6 +104,7 @@ export function resolveAgentConfig( typeof entry.model === "string" || (entry.model && typeof entry.model === "object") ? entry.model : undefined, + thinkingDefault: entry.thinkingDefault, memorySearch: entry.memorySearch, humanDelay: entry.humanDelay, heartbeat: entry.heartbeat, diff --git a/src/auto-reply/reply/get-reply-directives-apply.ts b/src/auto-reply/reply/get-reply-directives-apply.ts index c55e90539..b35a4ccdb 100644 --- a/src/auto-reply/reply/get-reply-directives-apply.ts +++ b/src/auto-reply/reply/get-reply-directives-apply.ts @@ -39,6 +39,7 @@ export async function applyInlineDirectiveOverrides(params: { agentId: string; agentDir: string; agentCfg: AgentDefaults; + agentThinkingDefault?: ThinkLevel; sessionEntry: SessionEntry; sessionStore: Record; sessionKey: string; @@ -74,6 +75,7 @@ export async function applyInlineDirectiveOverrides(params: { agentId, agentDir, agentCfg, + agentThinkingDefault, sessionEntry, sessionStore, sessionKey, @@ -147,6 +149,7 @@ export async function applyInlineDirectiveOverrides(params: { } const resolvedDefaultThinkLevel = (sessionEntry?.thinkingLevel as ThinkLevel | undefined) ?? + agentThinkingDefault ?? (agentCfg?.thinkingDefault as ThinkLevel | undefined) ?? (await modelState.resolveDefaultThinkingLevel()); const currentThinkLevel = resolvedDefaultThinkLevel; diff --git a/src/auto-reply/reply/get-reply-directives.ts b/src/auto-reply/reply/get-reply-directives.ts index dfc586640..320b97619 100644 --- a/src/auto-reply/reply/get-reply-directives.ts +++ b/src/auto-reply/reply/get-reply-directives.ts @@ -88,6 +88,7 @@ export async function resolveReplyDirectives(params: { agentDir: string; workspaceDir: string; agentCfg: AgentDefaults; + agentThinkingDefault?: ThinkLevel; sessionCtx: TemplateContext; sessionEntry: SessionEntry; sessionStore: Record; @@ -112,6 +113,7 @@ export async function resolveReplyDirectives(params: { cfg, agentId, agentCfg, + agentThinkingDefault, agentDir, workspaceDir, sessionCtx, @@ -341,6 +343,7 @@ export async function resolveReplyDirectives(params: { const resolvedThinkLevel = (directives.thinkLevel as ThinkLevel | undefined) ?? (sessionEntry?.thinkingLevel as ThinkLevel | undefined) ?? + agentThinkingDefault ?? (agentCfg?.thinkingDefault as ThinkLevel | undefined); const resolvedVerboseLevel = @@ -411,6 +414,7 @@ export async function resolveReplyDirectives(params: { agentId, agentDir, agentCfg, + agentThinkingDefault, sessionEntry, sessionStore, sessionKey, diff --git a/src/auto-reply/reply/get-reply.ts b/src/auto-reply/reply/get-reply.ts index 67b0c308e..ea7a2a89a 100644 --- a/src/auto-reply/reply/get-reply.ts +++ b/src/auto-reply/reply/get-reply.ts @@ -1,4 +1,5 @@ import { + resolveAgentConfig, resolveAgentDir, resolveAgentWorkspaceDir, resolveSessionAgentId, @@ -10,6 +11,7 @@ import { type OpenClawConfig, loadConfig } from "../../config/config.js"; import { defaultRuntime } from "../../runtime.js"; import { resolveCommandAuthorization } from "../command-auth.js"; import type { MsgContext } from "../templating.js"; +import type { ThinkLevel } from "../thinking.js"; import { SILENT_REPLY_TOKEN } from "../tokens.js"; import { applyMediaUnderstanding } from "../../media-understanding/apply.js"; import { applyLinkUnderstanding } from "../../link-understanding/apply.js"; @@ -39,6 +41,8 @@ export async function getReplyFromConfig( config: cfg, }); const agentCfg = cfg.agents?.defaults; + const perAgentConfig = resolveAgentConfig(cfg, agentId); + const agentThinkingDefault = perAgentConfig?.thinkingDefault as ThinkLevel | undefined; const sessionCfg = cfg.session; const { defaultProvider, defaultModel, aliasIndex } = resolveDefaultModel({ cfg, @@ -148,6 +152,7 @@ export async function getReplyFromConfig( agentDir, workspaceDir, agentCfg, + agentThinkingDefault, sessionCtx, sessionEntry, sessionStore, diff --git a/src/config/types.agents.ts b/src/config/types.agents.ts index f083c1897..47fffd10c 100644 --- a/src/config/types.agents.ts +++ b/src/config/types.agents.ts @@ -24,6 +24,8 @@ export type AgentConfig = { workspace?: string; agentDir?: string; model?: AgentModelConfig; + /** Per-agent default thinking level (overrides agents.defaults.thinkingDefault). */ + thinkingDefault?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh"; memorySearch?: MemorySearchConfig; /** Human-like delay between block replies for this agent. */ humanDelay?: HumanDelayConfig; diff --git a/src/config/zod-schema.agent-runtime.ts b/src/config/zod-schema.agent-runtime.ts index 7e95c3538..5e8429376 100644 --- a/src/config/zod-schema.agent-runtime.ts +++ b/src/config/zod-schema.agent-runtime.ts @@ -414,6 +414,17 @@ export const AgentModelSchema = z.union([ }) .strict(), ]); +export const ThinkingDefaultSchema = z + .union([ + z.literal("off"), + z.literal("minimal"), + z.literal("low"), + z.literal("medium"), + z.literal("high"), + z.literal("xhigh"), + ]) + .optional(); + export const AgentEntrySchema = z .object({ id: z.string(), @@ -422,6 +433,7 @@ export const AgentEntrySchema = z workspace: z.string().optional(), agentDir: z.string().optional(), model: AgentModelSchema.optional(), + thinkingDefault: ThinkingDefaultSchema, memorySearch: MemorySearchSchema, humanDelay: HumanDelaySchema.optional(), heartbeat: HeartbeatSchema,