feat(agents): add per-agent thinkingDefault override
Allows setting thinkingDefault on individual agent entries to override the global agents.defaults.thinkingDefault.
Priority order (highest to lowest):
1. Inline /think directive
2. Session-level thinking (persisted /think)
3. Agent-specific thinkingDefault (NEW)
4. Global agents.defaults.thinkingDefault
5. Model default
Example config:
```yaml
agents:
defaults:
thinkingDefault: low
list:
- id: code-reviewer
thinkingDefault: high # uses more reasoning for reviews
- id: quick-responder
thinkingDefault: off # fast responses
```
This commit is contained in:
parent
da71eaebd2
commit
ded9ef6bde
@ -20,6 +20,7 @@ type ResolvedAgentConfig = {
|
|||||||
workspace?: string;
|
workspace?: string;
|
||||||
agentDir?: string;
|
agentDir?: string;
|
||||||
model?: AgentEntry["model"];
|
model?: AgentEntry["model"];
|
||||||
|
thinkingDefault?: AgentEntry["thinkingDefault"];
|
||||||
memorySearch?: AgentEntry["memorySearch"];
|
memorySearch?: AgentEntry["memorySearch"];
|
||||||
humanDelay?: AgentEntry["humanDelay"];
|
humanDelay?: AgentEntry["humanDelay"];
|
||||||
heartbeat?: AgentEntry["heartbeat"];
|
heartbeat?: AgentEntry["heartbeat"];
|
||||||
@ -103,6 +104,7 @@ export function resolveAgentConfig(
|
|||||||
typeof entry.model === "string" || (entry.model && typeof entry.model === "object")
|
typeof entry.model === "string" || (entry.model && typeof entry.model === "object")
|
||||||
? entry.model
|
? entry.model
|
||||||
: undefined,
|
: undefined,
|
||||||
|
thinkingDefault: entry.thinkingDefault,
|
||||||
memorySearch: entry.memorySearch,
|
memorySearch: entry.memorySearch,
|
||||||
humanDelay: entry.humanDelay,
|
humanDelay: entry.humanDelay,
|
||||||
heartbeat: entry.heartbeat,
|
heartbeat: entry.heartbeat,
|
||||||
|
|||||||
@ -39,6 +39,7 @@ export async function applyInlineDirectiveOverrides(params: {
|
|||||||
agentId: string;
|
agentId: string;
|
||||||
agentDir: string;
|
agentDir: string;
|
||||||
agentCfg: AgentDefaults;
|
agentCfg: AgentDefaults;
|
||||||
|
agentThinkingDefault?: ThinkLevel;
|
||||||
sessionEntry: SessionEntry;
|
sessionEntry: SessionEntry;
|
||||||
sessionStore: Record<string, SessionEntry>;
|
sessionStore: Record<string, SessionEntry>;
|
||||||
sessionKey: string;
|
sessionKey: string;
|
||||||
@ -74,6 +75,7 @@ export async function applyInlineDirectiveOverrides(params: {
|
|||||||
agentId,
|
agentId,
|
||||||
agentDir,
|
agentDir,
|
||||||
agentCfg,
|
agentCfg,
|
||||||
|
agentThinkingDefault,
|
||||||
sessionEntry,
|
sessionEntry,
|
||||||
sessionStore,
|
sessionStore,
|
||||||
sessionKey,
|
sessionKey,
|
||||||
@ -147,6 +149,7 @@ export async function applyInlineDirectiveOverrides(params: {
|
|||||||
}
|
}
|
||||||
const resolvedDefaultThinkLevel =
|
const resolvedDefaultThinkLevel =
|
||||||
(sessionEntry?.thinkingLevel as ThinkLevel | undefined) ??
|
(sessionEntry?.thinkingLevel as ThinkLevel | undefined) ??
|
||||||
|
agentThinkingDefault ??
|
||||||
(agentCfg?.thinkingDefault as ThinkLevel | undefined) ??
|
(agentCfg?.thinkingDefault as ThinkLevel | undefined) ??
|
||||||
(await modelState.resolveDefaultThinkingLevel());
|
(await modelState.resolveDefaultThinkingLevel());
|
||||||
const currentThinkLevel = resolvedDefaultThinkLevel;
|
const currentThinkLevel = resolvedDefaultThinkLevel;
|
||||||
|
|||||||
@ -88,6 +88,7 @@ export async function resolveReplyDirectives(params: {
|
|||||||
agentDir: string;
|
agentDir: string;
|
||||||
workspaceDir: string;
|
workspaceDir: string;
|
||||||
agentCfg: AgentDefaults;
|
agentCfg: AgentDefaults;
|
||||||
|
agentThinkingDefault?: ThinkLevel;
|
||||||
sessionCtx: TemplateContext;
|
sessionCtx: TemplateContext;
|
||||||
sessionEntry: SessionEntry;
|
sessionEntry: SessionEntry;
|
||||||
sessionStore: Record<string, SessionEntry>;
|
sessionStore: Record<string, SessionEntry>;
|
||||||
@ -112,6 +113,7 @@ export async function resolveReplyDirectives(params: {
|
|||||||
cfg,
|
cfg,
|
||||||
agentId,
|
agentId,
|
||||||
agentCfg,
|
agentCfg,
|
||||||
|
agentThinkingDefault,
|
||||||
agentDir,
|
agentDir,
|
||||||
workspaceDir,
|
workspaceDir,
|
||||||
sessionCtx,
|
sessionCtx,
|
||||||
@ -341,6 +343,7 @@ export async function resolveReplyDirectives(params: {
|
|||||||
const resolvedThinkLevel =
|
const resolvedThinkLevel =
|
||||||
(directives.thinkLevel as ThinkLevel | undefined) ??
|
(directives.thinkLevel as ThinkLevel | undefined) ??
|
||||||
(sessionEntry?.thinkingLevel as ThinkLevel | undefined) ??
|
(sessionEntry?.thinkingLevel as ThinkLevel | undefined) ??
|
||||||
|
agentThinkingDefault ??
|
||||||
(agentCfg?.thinkingDefault as ThinkLevel | undefined);
|
(agentCfg?.thinkingDefault as ThinkLevel | undefined);
|
||||||
|
|
||||||
const resolvedVerboseLevel =
|
const resolvedVerboseLevel =
|
||||||
@ -411,6 +414,7 @@ export async function resolveReplyDirectives(params: {
|
|||||||
agentId,
|
agentId,
|
||||||
agentDir,
|
agentDir,
|
||||||
agentCfg,
|
agentCfg,
|
||||||
|
agentThinkingDefault,
|
||||||
sessionEntry,
|
sessionEntry,
|
||||||
sessionStore,
|
sessionStore,
|
||||||
sessionKey,
|
sessionKey,
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
resolveAgentConfig,
|
||||||
resolveAgentDir,
|
resolveAgentDir,
|
||||||
resolveAgentWorkspaceDir,
|
resolveAgentWorkspaceDir,
|
||||||
resolveSessionAgentId,
|
resolveSessionAgentId,
|
||||||
@ -10,6 +11,7 @@ import { type OpenClawConfig, loadConfig } from "../../config/config.js";
|
|||||||
import { defaultRuntime } from "../../runtime.js";
|
import { defaultRuntime } from "../../runtime.js";
|
||||||
import { resolveCommandAuthorization } from "../command-auth.js";
|
import { resolveCommandAuthorization } from "../command-auth.js";
|
||||||
import type { MsgContext } from "../templating.js";
|
import type { MsgContext } from "../templating.js";
|
||||||
|
import type { ThinkLevel } from "../thinking.js";
|
||||||
import { SILENT_REPLY_TOKEN } from "../tokens.js";
|
import { SILENT_REPLY_TOKEN } from "../tokens.js";
|
||||||
import { applyMediaUnderstanding } from "../../media-understanding/apply.js";
|
import { applyMediaUnderstanding } from "../../media-understanding/apply.js";
|
||||||
import { applyLinkUnderstanding } from "../../link-understanding/apply.js";
|
import { applyLinkUnderstanding } from "../../link-understanding/apply.js";
|
||||||
@ -39,6 +41,8 @@ export async function getReplyFromConfig(
|
|||||||
config: cfg,
|
config: cfg,
|
||||||
});
|
});
|
||||||
const agentCfg = cfg.agents?.defaults;
|
const agentCfg = cfg.agents?.defaults;
|
||||||
|
const perAgentConfig = resolveAgentConfig(cfg, agentId);
|
||||||
|
const agentThinkingDefault = perAgentConfig?.thinkingDefault as ThinkLevel | undefined;
|
||||||
const sessionCfg = cfg.session;
|
const sessionCfg = cfg.session;
|
||||||
const { defaultProvider, defaultModel, aliasIndex } = resolveDefaultModel({
|
const { defaultProvider, defaultModel, aliasIndex } = resolveDefaultModel({
|
||||||
cfg,
|
cfg,
|
||||||
@ -148,6 +152,7 @@ export async function getReplyFromConfig(
|
|||||||
agentDir,
|
agentDir,
|
||||||
workspaceDir,
|
workspaceDir,
|
||||||
agentCfg,
|
agentCfg,
|
||||||
|
agentThinkingDefault,
|
||||||
sessionCtx,
|
sessionCtx,
|
||||||
sessionEntry,
|
sessionEntry,
|
||||||
sessionStore,
|
sessionStore,
|
||||||
|
|||||||
@ -24,6 +24,8 @@ export type AgentConfig = {
|
|||||||
workspace?: string;
|
workspace?: string;
|
||||||
agentDir?: string;
|
agentDir?: string;
|
||||||
model?: AgentModelConfig;
|
model?: AgentModelConfig;
|
||||||
|
/** Per-agent default thinking level (overrides agents.defaults.thinkingDefault). */
|
||||||
|
thinkingDefault?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
||||||
memorySearch?: MemorySearchConfig;
|
memorySearch?: MemorySearchConfig;
|
||||||
/** Human-like delay between block replies for this agent. */
|
/** Human-like delay between block replies for this agent. */
|
||||||
humanDelay?: HumanDelayConfig;
|
humanDelay?: HumanDelayConfig;
|
||||||
|
|||||||
@ -414,6 +414,17 @@ export const AgentModelSchema = z.union([
|
|||||||
})
|
})
|
||||||
.strict(),
|
.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
|
export const AgentEntrySchema = z
|
||||||
.object({
|
.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
@ -422,6 +433,7 @@ export const AgentEntrySchema = z
|
|||||||
workspace: z.string().optional(),
|
workspace: z.string().optional(),
|
||||||
agentDir: z.string().optional(),
|
agentDir: z.string().optional(),
|
||||||
model: AgentModelSchema.optional(),
|
model: AgentModelSchema.optional(),
|
||||||
|
thinkingDefault: ThinkingDefaultSchema,
|
||||||
memorySearch: MemorySearchSchema,
|
memorySearch: MemorySearchSchema,
|
||||||
humanDelay: HumanDelaySchema.optional(),
|
humanDelay: HumanDelaySchema.optional(),
|
||||||
heartbeat: HeartbeatSchema,
|
heartbeat: HeartbeatSchema,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user