Summary
The runtime treats verboseDefault and elevatedDefault as valid per-agent overrides (resolver, plugin-SDK types, status text, command handlers), but the strict zod entry schema does not declare them, so openclaw config set agents.list.<idx>.verboseDefault on (or elevatedDefault) is rejected with Unrecognized key. Only agents.defaults.* accepts these keys today, which forces a global default even when the operator only wants to change one agent.
thinkingDefault, reasoningDefault, and fastModeDefault are accepted per agent — they are listed in AgentEntrySchema. verboseDefault/elevatedDefault are missing from that same schema, despite the rest of the stack already supporting them.
Environment
- OpenClaw
2026.4.24 (cbcfdf6)
- Linux x86_64 (Ubuntu VM)
- Config edited via
openclaw config set
Repro
# index 0 = any agent in agents.list, e.g. main
openclaw config set agents.list.0.verboseDefault on
# Error: Config validation failed: agents.list.0: Unrecognized key: "verboseDefault"
openclaw config set agents.list.0.elevatedDefault on
# Error: Config validation failed: agents.list.0: Unrecognized key: "elevatedDefault"
Same error when setting it in openclaw.json directly and running openclaw config validate.
thinkingDefault works as expected on the same path:
openclaw config set agents.list.0.thinkingDefault high
# OK
agents.defaults.verboseDefault and agents.defaults.elevatedDefault are also accepted and work as documented.
Expected
Either (preferred): allow verboseDefault and elevatedDefault on per-agent entries the same way thinkingDefault, reasoningDefault, and fastModeDefault are allowed, since the rest of the codebase already resolves them per agent.
Or: explicitly document that these are global-only and remove the per-agent resolution paths and SDK types so the surface stays consistent.
Evidence the rest of the stack already expects per-agent values
The strict schema is the only place the per-agent fields are missing. Everywhere else the resolver chain reads entry.verboseDefault / agentCfg.verboseDefault first and only then falls back to agents.defaults.verboseDefault:
dist/agent-scope-*.js:
verboseDefault: entry.verboseDefault ?? agentDefaults?.verboseDefault,
dist/directive-handling.levels-*.js:
currentVerboseLevel: params.sessionEntry?.verboseLevel ?? params.agentCfg?.verboseDefault,
dist/agent-command-*.js:
const resolvedVerboseLevel = verboseOverride ?? persistedVerbose ?? agentCfg?.verboseDefault;
dist/get-reply-*.js:
const resolvedVerboseLevel = directives.verboseLevel ?? targetSessionEntry?.verboseLevel ?? agentCfg?.verboseDefault;
dist/dispatch-*.js:
fallbackLevel: normalizeVerboseLevel(
sessionStoreEntry.entry?.verboseLevel
?? sessionAgentCfg?.verboseDefault
?? cfg.agents?.defaults?.verboseDefault
?? ""
) ?? "off"
dist/status-message-*.js:
const verboseLevel = args.resolvedVerbose
?? args.sessionEntry?.verboseLevel
?? args.agent?.verboseDefault
?? "off";
The Plugin-SDK type definitions also document the per-agent fields:
dist/plugin-sdk/src/config/types.agents.d.ts:
/** Optional per-agent default verbosity level. */
verboseDefault?: "off" | "on" | "full";
dist/plugin-sdk/src/config/zod-schema.agents.d.ts (the published TS schema):
verboseDefault: z.ZodOptional<z.ZodUnion<readonly [
z.ZodLiteral<"off">, z.ZodLiteral<"on">, z.ZodLiteral<"full">
]>>;
dist/plugin-sdk/src/agents/agent-scope-config.d.ts:
verboseDefault?: AgentDefaultsConfig["verboseDefault"];
Where the runtime schema diverges
dist/zod-schema.agent-runtime-*.js declares AgentEntrySchema as z.object({...}).strict() and only includes thinkingDefault, reasoningDefault, and fastModeDefault. verboseDefault and elevatedDefault are absent:
const AgentEntrySchema = z.object({
id: z.string(),
// ...
thinkingDefault: z.enum(["off","minimal","low","medium","high","xhigh","adaptive","max"]).optional(),
reasoningDefault: z.enum(["on","off","stream"]).optional(),
fastModeDefault: z.boolean().optional(),
// verboseDefault <-- missing
// elevatedDefault <-- missing
// ...
}).strict();
The defaults schema (AgentDefaultsConfig in zod-schema-*.js) does declare them:
verboseDefault: z.union([
z.literal("off"), z.literal("on"), z.literal("full")
]).optional(),
elevatedDefault: z.union([
z.literal("off"), z.literal("on"), z.literal("ask"), z.literal("full")
]).optional(),
openclaw config schema confirms it at runtime — agents.list[] lists thinkingDefault, reasoningDefault, fastModeDefault but not verboseDefault or elevatedDefault.
Documentation
docs.openclaw.ai/gateway/config-agents documents verboseDefault and elevatedDefault only under agents.defaults.*. There is no documented per-agent override for them, even though thinkingDefault is documented as available both at agents.defaults.thinkingDefault and agents.list[].thinkingDefault. The doc lookup at https://docs.openclaw.ai/tools/thinking even references Per-agent default (agents.list[].thinkingDefault in config), which sets the expected pattern.
Suggested fix
Add the two fields to AgentEntrySchema in zod-schema.agent-runtime:
verboseDefault: z.enum(["off", "on", "full"]).optional(),
elevatedDefault: z.enum(["off", "on", "ask", "full"]).optional(),
…and document them under agents.list[] in gateway/config-agents.mdx with the same precedence note used for thinkingDefault (per-agent overrides default, omitted falls back to agents.defaults.*).
Workaround
Set the value globally via agents.defaults.verboseDefault / elevatedDefault. Per-agent toggling currently has to happen via runtime /verbose and /elevated slash commands per session, which doesn't survive new sessions.
Summary
The runtime treats
verboseDefaultandelevatedDefaultas valid per-agent overrides (resolver, plugin-SDK types, status text, command handlers), but the strict zod entry schema does not declare them, soopenclaw config set agents.list.<idx>.verboseDefault on(orelevatedDefault) is rejected withUnrecognized key. Onlyagents.defaults.*accepts these keys today, which forces a global default even when the operator only wants to change one agent.thinkingDefault,reasoningDefault, andfastModeDefaultare accepted per agent — they are listed inAgentEntrySchema.verboseDefault/elevatedDefaultare missing from that same schema, despite the rest of the stack already supporting them.Environment
2026.4.24 (cbcfdf6)openclaw config setRepro
Same error when setting it in
openclaw.jsondirectly and runningopenclaw config validate.thinkingDefaultworks as expected on the same path:agents.defaults.verboseDefaultandagents.defaults.elevatedDefaultare also accepted and work as documented.Expected
Either (preferred): allow
verboseDefaultandelevatedDefaulton per-agent entries the same waythinkingDefault,reasoningDefault, andfastModeDefaultare allowed, since the rest of the codebase already resolves them per agent.Or: explicitly document that these are global-only and remove the per-agent resolution paths and SDK types so the surface stays consistent.
Evidence the rest of the stack already expects per-agent values
The strict schema is the only place the per-agent fields are missing. Everywhere else the resolver chain reads
entry.verboseDefault/agentCfg.verboseDefaultfirst and only then falls back toagents.defaults.verboseDefault:dist/agent-scope-*.js:dist/directive-handling.levels-*.js:dist/agent-command-*.js:dist/get-reply-*.js:dist/dispatch-*.js:dist/status-message-*.js:The Plugin-SDK type definitions also document the per-agent fields:
dist/plugin-sdk/src/config/types.agents.d.ts:dist/plugin-sdk/src/config/zod-schema.agents.d.ts(the published TS schema):dist/plugin-sdk/src/agents/agent-scope-config.d.ts:Where the runtime schema diverges
dist/zod-schema.agent-runtime-*.jsdeclaresAgentEntrySchemaasz.object({...}).strict()and only includesthinkingDefault,reasoningDefault, andfastModeDefault.verboseDefaultandelevatedDefaultare absent:The defaults schema (
AgentDefaultsConfiginzod-schema-*.js) does declare them:openclaw config schemaconfirms it at runtime —agents.list[]liststhinkingDefault,reasoningDefault,fastModeDefaultbut notverboseDefaultorelevatedDefault.Documentation
docs.openclaw.ai/gateway/config-agentsdocumentsverboseDefaultandelevatedDefaultonly underagents.defaults.*. There is no documented per-agent override for them, even thoughthinkingDefaultis documented as available both atagents.defaults.thinkingDefaultandagents.list[].thinkingDefault. The doc lookup athttps://docs.openclaw.ai/tools/thinkingeven referencesPer-agent default (agents.list[].thinkingDefault in config), which sets the expected pattern.Suggested fix
Add the two fields to
AgentEntrySchemainzod-schema.agent-runtime:…and document them under
agents.list[]ingateway/config-agents.mdxwith the same precedence note used forthinkingDefault(per-agent overrides default, omitted falls back toagents.defaults.*).Workaround
Set the value globally via
agents.defaults.verboseDefault/elevatedDefault. Per-agent toggling currently has to happen via runtime/verboseand/elevatedslash commands per session, which doesn't survive new sessions.