openclaw - ✅(Solved) Fix Per-agent `verboseDefault` / `elevatedDefault` rejected by config schema, despite resolver and SDK types supporting them [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#73680Fetched 2026-04-29 06:16:31
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
0
Timeline (top)
commented ×1cross-referenced ×1

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.

Error Message

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"

Root Cause

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.

Fix Action

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.

PR fix notes

PR #73696: fix(config): allow per-agent verbose and elevated defaults

Description (problem / solution / changelog)

Summary

  • allow verboseDefault and elevatedDefault on agents.list[] entries
  • keep the generated base config schema in sync
  • add schema coverage for accepted and rejected per-agent default values

Fixes #73680

Tests

  • pnpm exec vitest run src/config/config-misc.test.ts src/agents/agent-scope.test.ts
  • pnpm config:schema:check
  • pnpm check:changed

Changed files

  • src/config/config-misc.test.ts (modified, +34/-0)
  • src/config/schema.base.generated.ts (modified, +8/-0)
  • src/config/types.agents.ts (modified, +2/-0)
  • src/config/zod-schema.agent-runtime.ts (modified, +2/-0)

Code Example

# 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"

---

openclaw config set agents.list.0.thinkingDefault high
# OK

---

verboseDefault: entry.verboseDefault ?? agentDefaults?.verboseDefault,

---

currentVerboseLevel: params.sessionEntry?.verboseLevel ?? params.agentCfg?.verboseDefault,

---

const resolvedVerboseLevel = verboseOverride ?? persistedVerbose ?? agentCfg?.verboseDefault;

---

const resolvedVerboseLevel = directives.verboseLevel ?? targetSessionEntry?.verboseLevel ?? agentCfg?.verboseDefault;

---

fallbackLevel: normalizeVerboseLevel(
    sessionStoreEntry.entry?.verboseLevel
      ?? sessionAgentCfg?.verboseDefault
      ?? cfg.agents?.defaults?.verboseDefault
      ?? ""
  ) ?? "off"

---

const verboseLevel = args.resolvedVerbose
    ?? args.sessionEntry?.verboseLevel
    ?? args.agent?.verboseDefault
    ?? "off";

---

/** Optional per-agent default verbosity level. */
  verboseDefault?: "off" | "on" | "full";

---

verboseDefault: z.ZodOptional<z.ZodUnion<readonly [
    z.ZodLiteral<"off">, z.ZodLiteral<"on">, z.ZodLiteral<"full">
  ]>>;

---

verboseDefault?: AgentDefaultsConfig["verboseDefault"];

---

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();

---

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(),

---

verboseDefault: z.enum(["off", "on", "full"]).optional(),
elevatedDefault: z.enum(["off", "on", "ask", "full"]).optional(),
RAW_BUFFERClick to expand / collapse

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.

extent analysis

TL;DR

Add verboseDefault and elevatedDefault to the AgentEntrySchema in zod-schema.agent-runtime to enable per-agent configuration.

Guidance

  • Update the AgentEntrySchema to include verboseDefault and elevatedDefault with their respective types and optional status.
  • Verify the change by running openclaw config set agents.list.0.verboseDefault on and checking that it no longer returns an "Unrecognized key" error.
  • Document the per-agent override for verboseDefault and elevatedDefault in gateway/config-agents.mdx to reflect the updated configuration options.
  • Test the per-agent configuration by setting different values for verboseDefault and elevatedDefault on multiple agents and verifying that they are applied correctly.

Example

const AgentEntrySchema = z.object({
  // ...
  thinkingDefault: z.enum(["off","minimal","low","medium","high","xhigh","adaptive","max"]).optional(),
  reasoningDefault: z.enum(["on","off","stream"]).optional(),
  fastModeDefault: z.boolean().optional(),
  verboseDefault: z.enum(["off", "on", "full"]).optional(),
  elevatedDefault: z.enum(["off", "on", "ask", "full"]).optional(),
  // ...
}).strict();

Notes

The current workaround of setting verboseDefault and elevatedDefault globally via agents.defaults may not be desirable for all users, as it does not allow for per-agent configuration. The suggested fix enables this functionality, but may require additional testing to ensure that it does not introduce any unintended behavior.

Recommendation

Apply the suggested fix by adding verboseDefault and elevatedDefault to the AgentEntrySchema, as it enables per-agent configuration and aligns with the existing configuration options for thinkingDefault, `reasoning

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Per-agent `verboseDefault` / `elevatedDefault` rejected by config schema, despite resolver and SDK types supporting them [1 pull requests, 1 comments, 2 participants]